Commit 57e1a9cd authored by Davide Libenzi's avatar Davide Libenzi Committed by Linus Torvalds

[PATCH] The epoll saga continues ...

Proper wakeup code in ep_insert and ep_modify
parent 7ceefe99
...@@ -81,6 +81,10 @@ ...@@ -81,6 +81,10 @@
/* Maximum size of the hash in pages */ /* Maximum size of the hash in pages */
#define EP_MAX_HPAGES ((1 << EP_MAX_HASH_BITS) / EP_HENTRY_X_PAGE + 1) #define EP_MAX_HPAGES ((1 << EP_MAX_HASH_BITS) / EP_HENTRY_X_PAGE + 1)
/* Number of pages allocated for an "hbits" sized hash table */
#define EP_HASH_PAGES(hbits) ((int) ((1 << (hbits)) / EP_HENTRY_X_PAGE + \
((1 << (hbits)) % EP_HENTRY_X_PAGE ? 1: 0)))
/* Macro to allocate a "struct epitem" from the slab cache */ /* Macro to allocate a "struct epitem" from the slab cache */
#define DPI_MEM_ALLOC() (struct epitem *) kmem_cache_alloc(dpi_cache, SLAB_KERNEL) #define DPI_MEM_ALLOC() (struct epitem *) kmem_cache_alloc(dpi_cache, SLAB_KERNEL)
...@@ -131,9 +135,6 @@ struct eventpoll { ...@@ -131,9 +135,6 @@ struct eventpoll {
/* Size of the hash */ /* Size of the hash */
unsigned int hashbits; unsigned int hashbits;
/* Number of pages currently allocated for the hash */
int nhpages;
/* Pages for the "struct epitem" hash */ /* Pages for the "struct epitem" hash */
char *hpages[EP_MAX_HPAGES]; char *hpages[EP_MAX_HPAGES];
}; };
...@@ -261,9 +262,8 @@ static unsigned int ep_get_hash_bits(unsigned int hintsize) ...@@ -261,9 +262,8 @@ static unsigned int ep_get_hash_bits(unsigned int hintsize)
{ {
unsigned int i, val; unsigned int i, val;
for (i = 0, val = 1; val < hintsize && i < 8 * sizeof(int); i++, val <<= 1); for (i = 0, val = 1; val < hintsize && i < EP_MAX_HASH_BITS; i++, val <<= 1);
return i < EP_MIN_HASH_BITS ? EP_MIN_HASH_BITS: return i < EP_MIN_HASH_BITS ? EP_MIN_HASH_BITS: i;
(i > EP_MAX_HASH_BITS ? EP_MAX_HASH_BITS: i);
} }
...@@ -668,15 +668,13 @@ static int ep_init(struct eventpoll *ep, unsigned int hashbits) ...@@ -668,15 +668,13 @@ static int ep_init(struct eventpoll *ep, unsigned int hashbits)
INIT_LIST_HEAD(&ep->rdllist); INIT_LIST_HEAD(&ep->rdllist);
/* Hash allocation and setup */ /* Hash allocation and setup */
hsize = 1 << hashbits;
ep->hashbits = hashbits; ep->hashbits = hashbits;
ep->nhpages = (int) (hsize / EP_HENTRY_X_PAGE + (hsize % EP_HENTRY_X_PAGE ? 1: 0)); error = ep_alloc_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits));
error = ep_alloc_pages(ep->hpages, ep->nhpages);
if (error) if (error)
goto eexit_1; goto eexit_1;
/* Initialize hash buckets */ /* Initialize hash buckets */
for (i = 0; i < hsize; i++) for (i = 0, hsize = 1 << hashbits; i < hsize; i++)
INIT_LIST_HEAD(ep_hash_entry(ep, i)); INIT_LIST_HEAD(ep_hash_entry(ep, i));
return 0; return 0;
...@@ -728,7 +726,7 @@ static void ep_free(struct eventpoll *ep) ...@@ -728,7 +726,7 @@ static void ep_free(struct eventpoll *ep)
write_unlock_irqrestore(&eplock, flags); write_unlock_irqrestore(&eplock, flags);
/* Free hash pages */ /* Free hash pages */
ep_free_pages(ep->hpages, ep->nhpages); ep_free_pages(ep->hpages, EP_HASH_PAGES(ep->hashbits));
} }
...@@ -844,8 +842,15 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil ...@@ -844,8 +842,15 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
revents = tfile->f_op->poll(tfile, &pt); revents = tfile->f_op->poll(tfile, &pt);
/* If the file is already "ready" we drop it inside the ready list */ /* If the file is already "ready" we drop it inside the ready list */
if ((revents & pfd->events) && !EP_IS_LINKED(&dpi->rdllink)) if ((revents & pfd->events) && !EP_IS_LINKED(&dpi->rdllink)) {
list_add(&dpi->rdllink, &ep->rdllist); list_add_tail(&dpi->rdllink, &ep->rdllist);
/* Notify waiting tasks that events are available */
if (waitqueue_active(&ep->wq))
wake_up(&ep->wq);
if (waitqueue_active(&ep->poll_wait))
wake_up(&ep->poll_wait);
}
write_unlock_irqrestore(&ep->lock, flags); write_unlock_irqrestore(&ep->lock, flags);
...@@ -888,8 +893,16 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even ...@@ -888,8 +893,16 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
dpi->pfd.events = events; dpi->pfd.events = events;
/* If the file is already "ready" we drop it inside the ready list */ /* If the file is already "ready" we drop it inside the ready list */
if ((revents & events) && EP_IS_LINKED(&dpi->llink) && !EP_IS_LINKED(&dpi->rdllink)) if ((revents & events) && EP_IS_LINKED(&dpi->llink) &&
list_add(&dpi->rdllink, &ep->rdllist); !EP_IS_LINKED(&dpi->rdllink)) {
list_add_tail(&dpi->rdllink, &ep->rdllist);
/* Notify waiting tasks that events are available */
if (waitqueue_active(&ep->wq))
wake_up(&ep->wq);
if (waitqueue_active(&ep->poll_wait))
wake_up(&ep->poll_wait);
}
write_unlock_irqrestore(&ep->lock, flags); write_unlock_irqrestore(&ep->lock, flags);
...@@ -993,7 +1006,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync) ...@@ -993,7 +1006,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync)
if (EP_IS_LINKED(&dpi->rdllink)) if (EP_IS_LINKED(&dpi->rdllink))
goto is_linked; goto is_linked;
list_add(&dpi->rdllink, &ep->rdllist); list_add_tail(&dpi->rdllink, &ep->rdllist);
is_linked: is_linked:
/* /*
...@@ -1072,9 +1085,9 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m ...@@ -1072,9 +1085,9 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
EP_LIST_DEL(&dpi->rdllink); EP_LIST_DEL(&dpi->rdllink);
/* /*
* If the item is not linked to the main has table this means that * If the item is not linked to the main hash table this means that
* it's on the way to be removed and we don't want to send events * it's on the way to be removed and we don't want to send events
* to such file descriptor. * for such file descriptor.
*/ */
if (!EP_IS_LINKED(&dpi->llink)) if (!EP_IS_LINKED(&dpi->llink))
continue; continue;
...@@ -1125,7 +1138,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m ...@@ -1125,7 +1138,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
static int ep_poll(struct eventpoll *ep, struct pollfd *events, int maxevents, static int ep_poll(struct eventpoll *ep, struct pollfd *events, int maxevents,
int timeout) int timeout)
{ {
int res = 0, eavail; int res, eavail;
unsigned long flags; unsigned long flags;
long jtimeout; long jtimeout;
wait_queue_t wait; wait_queue_t wait;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment