Skip to contentSkip to conversation

PATCH (2.4.5): /dev/poll support (3rd time lucky)

PATCH Zarjazz 1 participant 1 message Jun 27, 2001

Subsystems (6)
lore
Share & tools
lore

Zarjazz

author
#0 lore raw

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
diff -rNu linux.orig/drivers/char/Config.in linux/drivers/char/Config.in
@@ -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
diff -rNu linux.orig/drivers/char/Makefile linux/drivers/char/Makefile
@@ -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
diff -rNu linux.orig/fs/file_table.c linux/fs/file_table.c
@@ -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
diff -rNu linux.orig/fs/open.c linux/fs/open.c
@@ -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
diff -rNu linux.orig/include/asm-i386/poll.h linux/include/asm-i386/poll.h
@@ -15,6 +15,8 @@
 #define POLLWRNORM	0x0100
 #define POLLWRBAND	0x0200
 #define POLLMSG		0x0400
+#define POLLREMOVE	0x1000
+#define POLLHINT	0x2000
 
 struct pollfd {
 	int fd;
include/linux/devpoll.h +85 -0

85 lines not on this page · raw message

include/linux/fs.h +4 -0
diff -rNu linux.orig/include/linux/fs.h linux/include/linux/fs.h
@@ -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
diff -rNu linux.orig/include/net/sock.h linux/include/net/sock.h
@@ -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
diff -rNu linux.orig/net/core/datagram.c linux/net/core/datagram.c
@@ -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
diff -rNu linux.orig/net/core/sock.c linux/net/core/sock.c
@@ -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
diff -rNu linux.orig/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
@@ -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
diff -rNu linux.orig/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -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
diff -rNu linux.orig/net/unix/af_unix.c linux/net/unix/af_unix.c
@@ -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)