diff -urN linux.10/fs/select.c linux.20/fs/select.c
--- linux.10/fs/select.c	Mon Jan 14 23:22:40 2002
+++ linux.20/fs/select.c	Tue Jan 15 04:31:27 2002
@@ -12,6 +12,8 @@
  *  24 January 2000
  *     Changed sys_poll()/do_poll() to use PAGE_SIZE chunk-based allocation 
  *     of fds to overcome nfds < 16390 descriptors limit (Tigran Aivazian).
+ *  June 2001
+ *    Added async_poll implementation. -bcrl
  */
 
 #include <linux/slab.h>
@@ -19,6 +21,8 @@
 #include <linux/poll.h>
 #include <linux/file.h>
 #include <linux/module.h>
+#include <linux/aio.h>
+#include <linux/init.h>
 #include <linux/personality.h>
 
 #include <asm/uaccess.h>
@@ -27,9 +31,10 @@
 #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
 
 struct poll_table_entry {
-	struct file * filp;
 	wait_queue_t wait;
 	wait_queue_head_t * wait_address;
+	struct file * filp;
+	poll_table * p;
 };
 
 struct poll_table_page {
@@ -41,6 +46,8 @@
 #define POLL_TABLE_FULL(table) \
 	((unsigned long)((table)->entry+1) > PAGE_SIZE + (unsigned long)(table))
 
+static kmem_cache_t *poll_table_cache;
+
 /*
  * Ok, Peter made a complicated, but straightforward multiple_wait() function.
  * I have rewritten this, taking some shortcuts: This code may not be easy to
@@ -73,6 +80,72 @@
 	}
 }
 
+void async_poll_complete(void *data)
+{
+	poll_table	*p = data, *pwait;
+	struct kiocb	*iocb = p->iocb;
+	unsigned int	mask;
+
+	pwait = p;
+	p->wake = 0;
+	wmb();
+	do {
+		mask = iocb->filp->f_op->poll(iocb->filp, p);
+		mask &= p->events | POLLERR | POLLHUP;
+		if (mask) {
+			poll_freewait(p);
+			aio_complete(iocb, mask, 0);
+			return;
+		}
+		p->sync = 0;
+		wmb();
+	} while (p->wake);
+
+}
+
+static void async_poll_waiter(wait_queue_t *wait)
+{
+	struct poll_table_entry *entry = (struct poll_table_entry *)wait;
+	poll_table *p = entry->p;
+
+	/* avoid writes to the cacheline if possible for SMP */
+	if (!p->wake) {
+		p->wake = 1;
+		/* ensure only one wake up queues the wtd */
+		if (!p->sync && !test_and_set_bit(0, &p->sync))
+			wtd_queue(&p->wtd);
+	}
+}
+
+int async_poll(struct kiocb *iocb, int events)
+{
+	unsigned int mask;
+	poll_table *p, *pwait;
+
+	p = kmem_cache_alloc(poll_table_cache, SLAB_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	poll_initwait(p);
+	wtd_set_action(&p->wtd, async_poll_complete, p);
+	p->iocb = iocb;
+	p->wake = 0;
+	p->sync = 0;
+	p->events = events;
+	pwait = p;
+
+	mask = DEFAULT_POLLMASK;
+	if (iocb->filp->f_op && iocb->filp->f_op->poll)
+		mask = iocb->filp->f_op->poll(iocb->filp, p);
+	mask &= events | POLLERR | POLLHUP;
+	if (mask) {
+		poll_freewait(p);
+		aio_complete(iocb, mask, 0);
+	}
+
+	return 0;
+}
+
 void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
 {
 	struct poll_table_page *table = p->table;
@@ -99,7 +172,11 @@
 	 	get_file(filp);
 	 	entry->filp = filp;
 		entry->wait_address = wait_address;
-		init_waitqueue_entry(&entry->wait, current);
+		entry->p = p;
+		if (p->iocb)
+			init_waitqueue_func_entry(&entry->wait, async_poll_waiter);
+		else
+			init_waitqueue_entry(&entry->wait, current);
 		add_wait_queue(wait_address,&entry->wait);
 	}
 }
@@ -495,3 +572,14 @@
 	poll_freewait(&table);
 	return err;
 }
+
+static int __init poll_init(void)
+{
+	poll_table_cache = kmem_cache_create("poll table",
+                        sizeof(poll_table), 0, 0, NULL, NULL);
+	if (!poll_table_cache)
+		panic("unable to alloc poll_table_cache");
+	return 0;
+}
+
+module_init(poll_init);
diff -urN linux.10/include/linux/poll.h linux.20/include/linux/poll.h
--- linux.10/include/linux/poll.h	Mon Jan 14 23:32:16 2002
+++ linux.20/include/linux/poll.h	Tue Jan 15 04:30:38 2002
@@ -7,14 +7,25 @@
 
 #include <linux/wait.h>
 #include <linux/string.h>
+#ifndef __LINUX__MM_H
 #include <linux/mm.h>
+#endif
 #include <asm/uaccess.h>
+#ifndef __LINUX__WORKTODO_H
+#include <linux/worktodo.h>
+#endif
 
 struct poll_table_page;
+struct kiocb;
 
 typedef struct poll_table_struct {
-	int error;
-	struct poll_table_page * table;
+	struct worktodo		wtd;
+	int			error;
+	struct poll_table_page	*table;
+	struct kiocb		*iocb;		/* iocb for async poll */
+	int			events;		/* event mask for async poll */
+	int			wake;
+	long			sync;
 } poll_table;
 
 extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p);
@@ -29,8 +40,11 @@
 {
 	pt->error = 0;
 	pt->table = NULL;
+	pt->iocb = NULL;
 }
+
 extern void poll_freewait(poll_table* pt);
+int async_poll(struct kiocb *iocb, int events);
 
 
 /*
