Message ID | 49F43B8F.2050907@cosmosbay.com |
---|---|
State | Not Applicable, archived |
Delegated to: | David Miller |
Headers | show |
Eric Dumazet wrote, On 04/26/2009 12:46 PM: ... > [PATCH] poll: Avoid extra wakeups in select/pol ... > Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> > --- > fs/select.c | 28 +++++++++++++++++++++++++--- > include/linux/poll.h | 3 +++ > 2 files changed, 28 insertions(+), 3 deletions(-) Eric, I wonder why you've forgotten about linux-kernel@ folks... Jarek P. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Jarek Poplawski a écrit : > Eric Dumazet wrote, On 04/26/2009 12:46 PM: > > ... >> [PATCH] poll: Avoid extra wakeups in select/pol > > ... > >> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> >> --- >> fs/select.c | 28 +++++++++++++++++++++++++--- >> include/linux/poll.h | 3 +++ >> 2 files changed, 28 insertions(+), 3 deletions(-) > > > Eric, I wonder why you've forgotten about linux-kernel@ folks... > Ah yes, I forgot, I only did a 'reply all' on David's mail. I'll resubmit it anyway, since it was only a followup. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Eric Dumazet <dada1@cosmosbay.com> Date: Sun, 26 Apr 2009 12:46:39 +0200 > [PATCH] poll: Avoid extra wakeups in select/poll Looks great to me: Acked-by: David S. Miller <davem@davemloft.net> But this has to go through something other than the networking tree, of course :-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
David Miller a écrit : > From: Eric Dumazet <dada1@cosmosbay.com> > Date: Sun, 26 Apr 2009 12:46:39 +0200 > >> [PATCH] poll: Avoid extra wakeups in select/poll > > Looks great to me: > > Acked-by: David S. Miller <davem@davemloft.net> > > But this has to go through something other than the > networking tree, of course :-) > > Sure, I'll do that promptly :) Thanks -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Eric Dumazet <dada1@cosmosbay.com> writes: > > When scheduled, thread does a full scan of all polled fds and > can sleep again, because nothing is really available. If number > of fds is large, this cause significant load. I wonder if the key could be used for more state. For example if you two processes are in recvmsg() on a socket and there's only a single packet incoming we only need to wake up the first waiter. Could that be done with keys too? > This patch makes select()/poll() aware of keyed wakeups and > useless wakeups are avoided. This reduces number of context > switches by about 50% on some setups, and work performed > by sofirq handlers. I'm late, but: very cool patch too. Acked-by: Andi Kleen <ak@linux.intel.com> -Andi
Andi Kleen a écrit : > Eric Dumazet <dada1@cosmosbay.com> writes: >> When scheduled, thread does a full scan of all polled fds and >> can sleep again, because nothing is really available. If number >> of fds is large, this cause significant load. > > I wonder if the key could be used for more state. For example if you > two processes are in recvmsg() on a socket and there's only a single > packet incoming we only need to wake up the first waiter. Could that > be done with keys too? I am not sure its possible. I'll take a look. > >> This patch makes select()/poll() aware of keyed wakeups and >> useless wakeups are avoided. This reduces number of context >> switches by about 50% on some setups, and work performed >> by sofirq handlers. > > I'm late, but: very cool patch too. > > Acked-by: Andi Kleen <ak@linux.intel.com> Thanks, I am going to send it again on lkml this time :) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/select.c b/fs/select.c index 0fe0e14..2708187 100644 --- a/fs/select.c +++ b/fs/select.c @@ -168,7 +168,7 @@ static struct poll_table_entry *poll_get_entry(struct poll_wqueues *p) return table->entry++; } -static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) +static int __pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) { struct poll_wqueues *pwq = wait->private; DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task); @@ -194,6 +194,16 @@ static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) return default_wake_function(&dummy_wait, mode, sync, key); } +static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key) +{ + struct poll_table_entry *entry; + + entry = container_of(wait, struct poll_table_entry, wait); + if (key && !((unsigned long)key & entry->key)) + return 0; + return __pollwake(wait, mode, sync, key); +} + /* Add a new entry */ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) @@ -205,6 +215,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, get_file(filp); entry->filp = filp; entry->wait_address = wait_address; + entry->key = p->key; init_waitqueue_func_entry(&entry->wait, pollwake); entry->wait.private = pwq; add_wait_queue(wait_address, &entry->wait); @@ -418,8 +429,16 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) if (file) { f_op = file->f_op; mask = DEFAULT_POLLMASK; - if (f_op && f_op->poll) + if (f_op && f_op->poll) { + if (wait) { + wait->key = POLLEX_SET; + if (in & bit) + wait->key |= POLLIN_SET; + if (out & bit) + wait->key |= POLLOUT_SET; + } mask = (*f_op->poll)(file, retval ? NULL : wait); + } fput_light(file, fput_needed); if ((mask & POLLIN_SET) && (in & bit)) { res_in |= bit; @@ -685,8 +704,11 @@ static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) mask = POLLNVAL; if (file != NULL) { mask = DEFAULT_POLLMASK; - if (file->f_op && file->f_op->poll) + if (file->f_op && file->f_op->poll) { + if (pwait) + pwait->key = pollfd->events | POLLERR | POLLHUP; mask = file->f_op->poll(file, pwait); + } /* Mask out unneeded events. */ mask &= pollfd->events | POLLERR | POLLHUP; fput_light(file, fput_needed); diff --git a/include/linux/poll.h b/include/linux/poll.h index 8c24ef8..3327389 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -32,6 +32,7 @@ typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_ typedef struct poll_table_struct { poll_queue_proc qproc; + unsigned long key; } poll_table; static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) @@ -43,10 +44,12 @@ static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_addres static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) { pt->qproc = qproc; + pt->key = ~0UL; /* all events enabled */ } struct poll_table_entry { struct file *filp; + unsigned long key; wait_queue_t wait; wait_queue_head_t *wait_address; };