PATCH (2.4.5): /dev/poll support (3rd time lucky)
Subsystems (6)
Not my day it seems ! Hopefully I remembered to attach the file this time :)
--
Hi,
this patch adds Solaris 7/8 like /dev/poll support to the kernel.
I can claim no real credit for this as basically this is a fixed version of a patch available from http://www.citi.umich.edu/projects/linux-scalability/
to compile correctly with 2.4.5 that only seemed to work with the 2.3.x devel branch. The reason for this is so I can compile & test an application on my home linux pc when I'm not around my nice work Solaris boxes :)
Please note, I have not got the knowledge of kernel development to know if this patch is broken or badly written. It may be bugged and/or worse than the standard poll() call but my application works so I'll leave profiling etc to people more knowledgable than me.
Vince.
drivers/char/Config.in +1 -0
@@ -158,6 +158,7 @@ dep_tristate 'Intel i8x0 Random Number Generator support' CONFIG_INTEL_RNG $CONFIG_PCI tristate '/dev/nvram support' CONFIG_NVRAM +tristate '/dev/poll support' CONFIG_DEVPOLL tristate 'Enhanced Real Time Clock Support' CONFIG_RTC if [ "$CONFIG_IA64" = "y" ]; then bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC
drivers/char/Makefile +1 -0
@@ -170,6 +170,7 @@ obj-$(CONFIG_PC110_PAD) += pc110pad.o obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o +obj-$(CONFIG_DEVPOLL) += devpoll.o ifeq ($(CONFIG_PPC),) obj-$(CONFIG_NVRAM) += nvram.o endif
drivers/char/devpoll.c +756 -0
756 lines not on this page · raw message
fs/file_table.c +2 -0
@@ -11,6 +11,7 @@#include <linux/init.h> #include <linux/module.h> #include <linux/smp_lock.h> +#include <linux/spinlock.h> /* sysctl tunables... */ struct files_stat_struct files_stat = {0 ,0 ,NR_FILE };
@@ -45,6 +46,7 @@ f->f_version = ++event; f->f_uid = current->fsuid; f->f_gid = current->fsgid; +rwlock_init (&f->f_dplock);list_add (&f->f_list, &anon_list);file_list_unlock ();return f;
fs/open.c +18 -0
@@ -14,6 +14,8 @@#include <linux/module.h> #include <linux/slab.h> #include <linux/tty.h> +#include <linux/poll.h> +#include <linux/devpoll.h> #include <asm/uaccess.h>
@@ -802,6 +805,14 @@ retval = filp->f_op->flush (filp);unlock_kernel (); } + +if (filp->f_backmap) { +unsigned long flags; +write_lock_irqsave (&filp->f_dplock,flags); +poll_clean_backmap (&filp->f_backmap); +write_unlock_irqrestore (&filp->f_dplock,flags); + } +fcntl_dirnotify (0 , filp,0 );locks_remove_posix (filp, id);fput (filp);
@@ -828,6 +839,14 @@FD_CLR (fd, files->close_on_exec);__put_unused_fd (files, fd);write_unlock (&files->file_lock); + +if (filp->f_backmap) { +unsigned long flags; +write_lock_irqsave (&filp->f_dplock,flags); +poll_remove_backmap (&filp->f_backmap,fd, files); +write_unlock_irqrestore (&filp->f_dplock,flags); + } +return filp_close (filp, files); out_unlock:
include/asm-i386/poll.h +2 -0
@@ -15,6 +15,8 @@#define POLLWRNORM 0x0100#define POLLWRBAND 0x0200#define POLLMSG 0x0400 +#define POLLREMOVE 0x1000 +#define POLLHINT 0x2000struct pollfd {int fd;
include/linux/devpoll.h +85 -0
85 lines not on this page · raw message
include/linux/fs.h +4 -0
@@ -502,6 +502,10 @@int f_error;unsigned long f_version; + +/* used by /dev/poll hinting */ +struct poll_backmap *f_backmap; +rwlock_t f_dplock;/* needed for tty driver, and maybe others */ void *private_data;
include/linux/poll.h +89 -0
106 lines not on this page · raw message
include/net/sock.h +4 -0
@@ -666,6 +666,10 @@/* Identd and reporting IO signals */ struct socket *socket; +/* For Poll hinting */ +void *backmap; +void *dplock; +/* RPC layer private data */ void *user_data;
net/core/datagram.c +4 -3
@@ -402,8 +402,6 @@return -EFAULT ; } - -/* * Datagram poll: Again totally generic. This also handles * sequenced packet sockets providing the socket receive queue
@@ -420,7 +418,10 @@unsigned int mask;poll_wait (file, sk->sleep, wait); - mask =0 ; + mask =POLLHINT ; + + sk->backmap = &file->f_backmap; + sk->dplock = &file->f_dplock;/* exceptional events? */ if (sk->err || !skb_queue_empty (&sk->error_queue))
net/core/sock.c +16 -4
@@ -108,6 +108,7 @@#include <linux/interrupt.h> #include <linux/poll.h> #include <linux/init.h> +#include <linux/devpoll.h> #include <asm/uaccess.h> #include <asm/system.h>
@@ -1100,16 +1101,20 @@void sock_def_wakeup (struct sock *sk) {read_lock (&sk->callback_lock); -if (sk->sleep &&waitqueue_active (sk->sleep)) +if (sk->sleep &&waitqueue_active (sk->sleep)) { +dp_add_hint (sk->backmap, sk->dplock);wake_up_interruptible_all (sk->sleep); + }read_unlock (&sk->callback_lock); }void sock_def_error_report (struct sock *sk) {read_lock (&sk->callback_lock); -if (sk->sleep &&waitqueue_active (sk->sleep)) +if (sk->sleep &&waitqueue_active (sk->sleep)) { +dp_add_hint (sk->backmap, sk->dplock);wake_up_interruptible (sk->sleep); + }sk_wake_async (sk,0 ,POLL_ERR );read_unlock (&sk->callback_lock); }
@@ -1117,8 +1122,10 @@void sock_def_readable (struct sock *sk,int len) {read_lock (&sk->callback_lock); -if (sk->sleep &&waitqueue_active (sk->sleep)) +if (sk->sleep &&waitqueue_active (sk->sleep)) { +dp_add_hint (sk->backmap, sk->dplock);wake_up_interruptible (sk->sleep); + }sk_wake_async (sk,1 ,POLL_IN );read_unlock (&sk->callback_lock); }
@@ -1131,8 +1138,10 @@* progress. --DaveM */ if ((atomic_read (&sk->wmem_alloc) <<1 ) <= sk->sndbuf) { -if (sk->sleep &&waitqueue_active (sk->sleep)) +if (sk->sleep &&waitqueue_active (sk->sleep)) { +dp_add_hint (sk->backmap, sk->dplock);wake_up_interruptible (sk->sleep); + }/* Should agree with poll, otherwise some programs break */ if (sock_writeable (sk))
@@ -1163,6 +1172,9 @@ sk->zapped =1 ; sk->socket = sock; + sk->backmap =NULL ; + sk->dplock =NULL ; +if (sock) { sk->type = sock->type;
net/ipv4/af_inet.c +1 -0
@@ -444,6 +444,7 @@if (sk->linger && !(current->flags &PF_EXITING )) timeout = sk->lingertime; sock->sk =NULL ; + sk->backmap =NULL ; sk->prot->close (sk, timeout); }return (0 );
net/ipv4/tcp.c +10 -3
@@ -249,6 +249,7 @@#include <linux/types.h> #include <linux/fcntl.h> #include <linux/poll.h> +#include <linux/devpoll.h> #include <linux/init.h> #include <linux/smp_lock.h>
@@ -380,8 +381,12 @@struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);poll_wait (file, sk->sleep, wait); + + sk->backmap = &file->f_backmap; + sk->dplock = &file->f_dplock; +if (sk->state ==TCP_LISTEN ) -return tcp_listen_poll (sk, wait); +return tcp_listen_poll (sk, wait) |POLLHINT ;/* Socket is not locked. We are protected from async events by poll logic and correct handling of state changes
@@ -454,7 +459,7 @@if (tp->urg_data &TCP_URG_VALID ) mask |=POLLPRI ; } -return mask; +return mask |POLLHINT ; }/*
@@ -467,8 +472,10 @@if (tcp_wspace (sk) >=tcp_min_write_space (sk) && sock) {clear_bit (SOCK_NOSPACE , &sock->flags); -if (sk->sleep &&waitqueue_active (sk->sleep)) +if (sk->sleep &&waitqueue_active (sk->sleep)) { +dp_add_hint (sk->backmap, sk->dplock);wake_up_interruptible (sk->sleep); + }if (sock->fasync_list && !(sk->shutdown&SEND_SHUTDOWN ))sock_wake_async (sock,2 ,POLL_OUT );
net/unix/af_unix.c +8 -2
@@ -107,6 +107,7 @@#include <net/scm.h> #include <linux/init.h> #include <linux/poll.h> +#include <linux/devpoll.h> #include <linux/smp_lock.h> #include <asm/checksum.h>
@@ -299,8 +300,10 @@ {read_lock (&sk->callback_lock);if (unix_writable (sk)) { -if (sk->sleep &&waitqueue_active (sk->sleep)) +if (sk->sleep &&waitqueue_active (sk->sleep)) { +dp_add_hint (sk->backmap,sk->dplock);wake_up_interruptible (sk->sleep); + }sk_wake_async (sk,2 ,POLL_OUT ); }read_unlock (&sk->callback_lock);
@@ -1698,7 +1701,10 @@unsigned int mask;poll_wait (file, sk->sleep, wait); - mask =0 ; + mask =POLLHINT ; + + sk->backmap = &file->f_backmap; + sk->dplock = &file->f_dplock;/* exceptional events? */ if (sk->err)