Commit af57e8ae authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ep_send_events() stack reduction

ep_send_events() uses ~350 bytes of stack for a local buffer of events to send
to userspace.  The patch fixes that by removing the double-buffering
altogether.  A pipe-based microbenchmark from Davide Libenzi
<davidel@xmailserver.org> was sped up by 1-2%.
parent c570d667
...@@ -147,14 +147,6 @@ ...@@ -147,14 +147,6 @@
/* Get the "struct epitem" from an epoll queue wrapper */ /* Get the "struct epitem" from an epoll queue wrapper */
#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi) #define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
/*
* This is used to optimize the event transfer to userspace. Since this
* is kept on stack, it should be pretty small.
*/
#define EP_MAX_BUF_EVENTS 32
/* /*
* Node that is linked into the "wake_task_list" member of the "struct poll_safewake". * Node that is linked into the "wake_task_list" member of the "struct poll_safewake".
* It is used to keep track on all tasks that are currently inside the wake_up() code * It is used to keep track on all tasks that are currently inside the wake_up() code
...@@ -1430,11 +1422,10 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist ...@@ -1430,11 +1422,10 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
struct epoll_event __user *events) struct epoll_event __user *events)
{ {
int eventcnt = 0, eventbuf = 0; int eventcnt = 0;
unsigned int revents; unsigned int revents;
struct list_head *lnk; struct list_head *lnk;
struct epitem *epi; struct epitem *epi;
struct epoll_event event[EP_MAX_BUF_EVENTS];
/* /*
* We can loop without lock because this is a task private list. * We can loop without lock because this is a task private list.
...@@ -1460,28 +1451,17 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, ...@@ -1460,28 +1451,17 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
epi->revents = revents & epi->event.events; epi->revents = revents & epi->event.events;
if (epi->revents) { if (epi->revents) {
event[eventbuf] = epi->event; if (__put_user(epi->event.events,
event[eventbuf].events &= revents; &events[eventcnt].events))
eventbuf++; return -EFAULT;
if (eventbuf == EP_MAX_BUF_EVENTS) { if (__put_user(epi->event.data,
if (__copy_to_user(&events[eventcnt], event, &events[eventcnt].data))
eventbuf * sizeof(struct epoll_event))) return -EFAULT;
return -EFAULT;
eventcnt += eventbuf;
eventbuf = 0;
}
if (epi->event.events & EPOLLONESHOT) if (epi->event.events & EPOLLONESHOT)
epi->event.events &= EP_PRIVATE_BITS; epi->event.events &= EP_PRIVATE_BITS;
eventcnt++;
} }
} }
if (eventbuf) {
if (__copy_to_user(&events[eventcnt], event,
eventbuf * sizeof(struct epoll_event)))
return -EFAULT;
eventcnt += eventbuf;
}
return eventcnt; return eventcnt;
} }
......
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