Stage 1 patch for faster polling

Richard Gooch (rgooch@atnf.CSIRO.AU)
Wed, 27 Aug 1997 14:44:45 +1000


Hi, all. Included is a patch which adds two new fields to struct
file: "poll_events" and "poll_queue", modifies get_empty_filp() to
initialise correctly, and modifies do_select() and do_poll() to make
use of these new fields.
The cost is about 60 microseconds per 1000 fds on a Pentium 100
(that's 60 microseconds out of 2 milliseconds, so it's real cheap). If
a driver maintains the "poll_events" field (i.e. clears the POLLNVAL
bit), then those 2 milliseconds are gained.
This patch allows driver writers to migrate to the new scheme without
breaking existing drivers (so it doesn't force anyone to do
anything). But think of the glory in yours being the first driver to
cream those 2 milliseconds! :-)

Regards,

Richard....

diff -urN linux-2.1.51/fs/file_table.c linux/fs/file_table.c
--- linux-2.1.51/fs/file_table.c Sat Aug 9 12:31:00 1997
+++ linux/fs/file_table.c Wed Aug 27 14:31:49 1997
@@ -13,6 +13,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/poll.h>

/* SLAB cache for filp's. */
static kmem_cache_t *filp_cache;
@@ -84,6 +85,7 @@
if((f = free_filps) != NULL) {
remove_filp(f);
memset(f, 0, sizeof(*f));
+ f->poll_events = POLLNVAL;
f->f_count = 1;
f->f_version = ++event;
put_inuse(f);
diff -urN linux-2.1.51/fs/select.c linux/fs/select.c
--- linux-2.1.51/fs/select.c Wed Aug 27 14:14:13 1997
+++ linux/fs/select.c Wed Aug 27 09:43:00 1997
@@ -162,9 +162,14 @@
struct file * file = *fd;
unsigned int mask = POLLNVAL;
if (file) {
- mask = DEFAULT_POLLMASK;
- if (file->f_op && file->f_op->poll)
- mask = file->f_op->poll(file, wait);
+ mask = file->poll_events;
+ if (!(mask & POLLNVAL))
+ poll_wait(&file->poll_queue, wait);
+ else {
+ mask = DEFAULT_POLLMASK;
+ if (file->f_op && file->f_op->poll)
+ mask = file->f_op->poll(file, wait);
+ }
}
if ((mask & POLLIN_SET) && ISSET(bit, __IN(in))) {
SET(bit, __RES_IN(in));
@@ -368,10 +373,15 @@
mask = POLLNVAL;
i = fdpnt->fd;
if (i < NR_OPEN && (file = fd[i]) != NULL) {
- mask = DEFAULT_POLLMASK;
- if (file->f_op && file->f_op->poll)
- mask = file->f_op->poll(file, wait);
- mask &= fdpnt->events | POLLERR | POLLHUP;
+ mask = file->poll_events;
+ if (!(mask & POLLNVAL))
+ poll_wait(&file->poll_queue, wait);
+ else {
+ mask = DEFAULT_POLLMASK;
+ if (file->f_op && file->f_op->poll)
+ mask = file->f_op->poll(file, wait);
+ mask &= fdpnt->events|POLLERR|POLLHUP;
+ }
}
if (mask) {
wait = NULL;
diff -urN linux-2.1.51/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.1.51/include/linux/fs.h Wed Aug 27 14:13:52 1997
+++ linux/include/linux/fs.h Wed Aug 27 14:31:46 1997
@@ -372,9 +372,11 @@
struct dentry *f_dentry;
struct file_operations *f_op;
mode_t f_mode;
+ short poll_events; /* Initialise to POLLNVAL */
loff_t f_pos;
unsigned short f_count, f_flags;
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
+ struct wait_queue *poll_queue; /* Initialise to NULL */

/* pid or -pgrp where SIGIO should be sent */
int f_owner;