summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavide Libenzi <davidel@xmailserver.org>2002-11-10 20:04:47 -0800
committerAndy Grover <agrover@groveronline.com>2002-11-10 20:04:47 -0800
commitd9bfacbad9db5f2ad34b8e27be6e90e93bdde5cb (patch)
tree52a06d865cadb0bbd91bf181933995e4b00c7c36
parenta3a67b1f88fb6723d14aa5c7b7b0cffb40b70416 (diff)
[PATCH] remove code duplication from fs/eventpoll.c
Clean up poll queue handling, avoid doing any wait-queue operations when we only want to get the current state.
-rw-r--r--fs/eventpoll.c53
-rw-r--r--fs/select.c9
-rw-r--r--include/linux/poll.h17
3 files changed, 27 insertions, 52 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 3aa50d4ad67a..9c765b18507b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -107,6 +107,8 @@
/* Get the "struct epitem" from a wait queue pointer */
#define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base)
+/* Get the "struct epitem" from an epoll queue wrapper */
+#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->dpi)
@@ -187,6 +189,12 @@ struct epitem {
atomic_t usecnt;
};
+/* Wrapper struct used by poll queueing */
+struct ep_pqueue {
+ poll_table pt;
+ struct epitem *dpi;
+};
+
static unsigned int ep_get_hash_bits(unsigned int hintsize);
@@ -201,7 +209,7 @@ static void ep_free(struct eventpoll *ep);
static struct epitem *ep_find(struct eventpoll *ep, struct file *file);
static void ep_use_epitem(struct epitem *dpi);
static void ep_release_epitem(struct epitem *dpi);
-static void ep_ptable_queue_proc(void *priv, wait_queue_head_t *whead);
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt);
static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfile);
static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int events);
static int ep_unlink(struct eventpoll *ep, struct epitem *dpi);
@@ -791,9 +799,9 @@ static void ep_release_epitem(struct epitem *dpi)
* This is the callback that is used to add our wait queue to the
* target file wakeup lists.
*/
-static void ep_ptable_queue_proc(void *priv, wait_queue_head_t *whead)
+static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt)
{
- struct epitem *dpi = priv;
+ struct epitem *dpi = EP_ITEM_FROM_EPQUEUE(pt);
/* No more than EP_MAX_POLL_QUEUE wait queue are supported */
if (dpi->nwait < EP_MAX_POLL_QUEUE) {
@@ -809,7 +817,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
int error, i, revents;
unsigned long flags;
struct epitem *dpi;
- poll_table pt;
+ struct ep_pqueue epq;
error = -ENOMEM;
if (!(dpi = DPI_MEM_ALLOC()))
@@ -830,7 +838,8 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
}
/* Initialize the poll table using the queue callback */
- poll_initwait_ex(&pt, 1, ep_ptable_queue_proc, dpi);
+ epq.dpi = dpi;
+ poll_initwait_ex(&epq.pt, ep_ptable_queue_proc);
/* We have to drop the new item inside our item list to keep track of it */
write_lock_irqsave(&ep->lock, flags);
@@ -839,7 +848,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
list_add(&dpi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile)));
/* Attach the item to the poll hooks and get current event bits */
- revents = tfile->f_op->poll(tfile, &pt);
+ revents = tfile->f_op->poll(tfile, &epq.pt);
/* If the file is already "ready" we drop it inside the ready list */
if ((revents & pfd->events) && !EP_IS_LINKED(&dpi->rdllink)) {
@@ -854,7 +863,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
write_unlock_irqrestore(&ep->lock, flags);
- poll_freewait(&pt);
+ poll_freewait(&epq.pt);
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %d)\n",
current, ep, pfd->fd));
@@ -874,20 +883,11 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
{
unsigned int revents;
unsigned long flags;
- poll_table pt;
-
- /*
- * This is a special poll table initialization that will
- * make poll_wait() to not perform any wait queue insertion when
- * called by file->f_op->poll(). This is a fast way to retrieve
- * file events with perform any queue insertion, hence saving CPU cycles.
- */
- poll_initwait_ex(&pt, 0, NULL, NULL);
write_lock_irqsave(&ep->lock, flags);
/* Get current event bits */
- revents = dpi->file->f_op->poll(dpi->file, &pt);
+ revents = dpi->file->f_op->poll(dpi->file, NULL);
/* Set the new event interest mask */
dpi->pfd.events = events;
@@ -906,8 +906,6 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
write_unlock_irqrestore(&ep->lock, flags);
- poll_freewait(&pt);
-
return 0;
}
@@ -1066,15 +1064,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
unsigned long flags;
struct list_head *lsthead = &ep->rdllist;
struct pollfd eventbuf[EP_EVENT_BUFF_SIZE];
- poll_table pt;
-
- /*
- * This is a special poll table initialization that will
- * make poll_wait() to not perform any wait queue insertion when
- * called by file->f_op->poll(). This is a fast way to retrieve
- * file events with perform any queue insertion, hence saving CPU cycles.
- */
- poll_initwait_ex(&pt, 0, NULL, NULL);
write_lock_irqsave(&ep->lock, flags);
@@ -1093,7 +1082,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
continue;
/* Fetch event bits from the signaled file */
- revents = dpi->file->f_op->poll(dpi->file, &pt);
+ revents = dpi->file->f_op->poll(dpi->file, NULL);
if (revents & dpi->pfd.events) {
eventbuf[ebufcnt] = dpi->pfd;
@@ -1108,10 +1097,8 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
*/
write_unlock_irqrestore(&ep->lock, flags);
if (__copy_to_user(&events[eventcnt], eventbuf,
- ebufcnt * sizeof(struct pollfd))) {
- poll_freewait(&pt);
+ ebufcnt * sizeof(struct pollfd)))
return -EFAULT;
- }
eventcnt += ebufcnt;
ebufcnt = 0;
write_lock_irqsave(&ep->lock, flags);
@@ -1129,8 +1116,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
eventcnt += ebufcnt;
}
- poll_freewait(&pt);
-
return eventcnt;
}
diff --git a/fs/select.c b/fs/select.c
index 0e2974a8154d..db80049720e2 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -77,14 +77,6 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
{
struct poll_table_page *table = p->table;
- if (!p->queue)
- return;
-
- if (p->qproc) {
- p->qproc(p->priv, wait_address);
- return;
- }
-
if (!table || POLL_TABLE_FULL(table)) {
struct poll_table_page *new_table;
@@ -112,6 +104,7 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
}
}
+
#define __IN(fds, n) (fds->in + n)
#define __OUT(fds, n) (fds->out + n)
#define __EX(fds, n) (fds->ex + n)
diff --git a/include/linux/poll.h b/include/linux/poll.h
index e88468c3b046..416d32e5d8e2 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -11,11 +11,12 @@
#include <asm/uaccess.h>
struct poll_table_page;
+struct poll_table_struct;
+
+typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct {
- int queue;
- void *priv;
- void (*qproc)(void *, wait_queue_head_t *);
+ poll_queue_proc qproc;
int error;
struct poll_table_page * table;
} poll_table;
@@ -25,16 +26,12 @@ extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, pol
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
if (p && wait_address)
- __pollwait(filp, wait_address, p);
+ p->qproc(filp, wait_address, p);
}
-static inline void poll_initwait_ex(poll_table* pt, int queue,
- void (*qproc)(void *, wait_queue_head_t *),
- void *priv)
+static inline void poll_initwait_ex(poll_table* pt, poll_queue_proc qproc)
{
- pt->queue = queue;
pt->qproc = qproc;
- pt->priv = priv;
pt->error = 0;
pt->table = NULL;
}
@@ -42,7 +39,7 @@ static inline void poll_initwait_ex(poll_table* pt, int queue,
static inline void poll_initwait(poll_table* pt)
{
- poll_initwait_ex(pt, 1, NULL, NULL);
+ poll_initwait_ex(pt, __pollwait);
}
extern void poll_freewait(poll_table* pt);