diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/arch/i386/config.in linux-2.4.3+fd_events/arch/i386/config.in --- linux-2.4.3/arch/i386/config.in Mon Jan 8 16:27:56 2001 +++ linux-2.4.3+fd_events/arch/i386/config.in Fri Apr 6 15:58:28 2001 @@ -227,6 +227,13 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'File Events Interface (EXPERIMENTAL)' CONFIG_FILE_EVENTS + + dep_mbool ' File Events Debugging' CONFIG_DEBUG_FILE_EVENTS $CONFIG_FILE_EVENTS + +fi + bool 'Power Management support' CONFIG_PM if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/arch/i386/kernel/entry.S linux-2.4.3+fd_events/arch/i386/kernel/entry.S --- linux-2.4.3/arch/i386/kernel/entry.S Wed Nov 8 20:09:50 2000 +++ linux-2.4.3+fd_events/arch/i386/kernel/entry.S Fri Apr 6 15:58:28 2001 @@ -645,6 +645,8 @@ .long SYMBOL_NAME(sys_madvise) .long SYMBOL_NAME(sys_getdents64) /* 220 */ .long SYMBOL_NAME(sys_fcntl64) + .long SYMBOL_NAME(sys_bind_event) + .long SYMBOL_NAME(sys_get_events) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ /* @@ -653,6 +655,6 @@ * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ - .rept NR_syscalls-221 + .rept NR_syscalls-223 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/fs/select.c linux-2.4.3+fd_events/fs/select.c --- linux-2.4.3/fs/select.c Fri Feb 9 14:29:44 2001 +++ linux-2.4.3+fd_events/fs/select.c Sun Apr 15 00:46:37 2001 @@ -12,13 +12,19 @@ * 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). + * + * 6 April 2001 + * Addition of sys_bind_event()/sys_get_events() to speed up event processing + * for a large number of file descriptors. (Bart Trojanowski ) */ #include #include #include #include +#include +#include /* for spinlocks to work */ #include #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) @@ -491,3 +497,346 @@ poll_freewait(&table); return err; } + +#ifdef CONFIG_FILE_EVENTS + +/* sets the file to default state by using the op->poll fn*/ +static inline unsigned long +current_file_events(struct file *file) +{ + unsigned long mask = 0; + if ( !file->f_op) goto out; + if ( !file->f_op->poll) goto out; + mask = file->f_op->poll(file, NULL); + out: + return mask; +} + +/* Marks a file for current task with the given criteria + * returns 1 on success, 0 on failure */ +static inline int +do_bind_event(struct file *file, struct fdevent *ev) +{ + register int ret=1;/* assume success */ + + /* set the static fields */ + file->f_event.event = *ev; + file->f_event_mask = ev->mask; + file->f_event.event.mask = 0; + + /* check for current events - but don't wait for them */ + deliver_file_event(file, current_file_events(file)); + + return ret; +} + +/* Takes an event and registers current->files->fd[fd] to watch for + * ev->mask on ev->fd; when something happens the event structure gets + * queued on current->files->file_event_head; this queue is returned + * to the user when sys_get_events is called + * sys_bind_event returns # of files bound to, or negative on error + */ +asmlinkage long sys_bind_event(struct fdevent *uev) +{ + struct fdevent *ev; + long ret; + + FEDBG("sys_bind_event( %p )",uev); + + ret = -ENOMEM; + if( !(ev = kmalloc(sizeof(struct fdevent), GFP_KERNEL)) ) { + FEDBG(" kmalloc( %d, GFP_KERNEL ) failed", sizeof(struct fdevent)); + goto out; + } + + ret = -EFAULT; + if( copy_from_user(ev, uev, sizeof(struct fdevent)) ) { + FEDBG(" copy_from_user( %p, %p, %d ) failed", + ev, uev, sizeof(struct fdevent)); + goto out_ev; + } + + FEDBG(" ev->mask = %lx", ev->mask ); + + /* before we start we have to make sure that the queue list for this + * task is properly initialized; considre this a delayed initialization + * as we know that not all tasks will want to use this interface */ + spin_lock(¤t->files->file_event_list.lock); + if( ! current->files->file_event_list.head ) { + /* this is a hack to catch any tasks we have not yet inited */ + /* TODO: this should go away, just init it when the task is created */ + FEDBG(" doing delayed initialization of files_struct!!!"); + INIT_FILE_EVENT_LIST(&(current->files->file_event_list)); + init_waitqueue_head(&(current->files->file_event_wait)); + } + spin_unlock(¤t->files->file_event_list.lock); + + /* now execute the desired command */ + switch( ev->fd ) { + int i, tot; + struct file *file; + + case FDEVENT_FD_EXISTING: + FEDBG(" ev->fd = FDEVENT_FD_EXISTING" ); + + /* set the ev->mask on each existing current->files->fd[*] */ + tot = ret = 0; + for(i=0;ifiles->max_fds;i++) { + file = fget(i); + if( file ) { + tot ++; + ret += do_bind_event(file,ev); + fput(file); + } + } + /* if there are no files then just return a ZERO */ + if( !tot ) break; + /* if we have counted a bind in any fd's above then + * return that number */ + if( ret ) break; + /* this means that there were files but they were + * already bound by some other task (parent/sibling) */ + ret=-EBUSY; + break; + + case FDEVENT_FD_DEFAULT: + FEDBG(" ev->fd = FDEVENT_FD_DEFAULT" ); + + /* set the default mask for new fd to ev->mask */ + current->files->default_file_event = *ev; + ret = 0; + break; + + default: + FEDBG(" ev->fd = %d", ev->fd ); + + /* set the ev->mask on the specified ev->fd */ + file = fget(ev->fd); + if (!file) { + ret = -EBADF; + goto out_ev; + } + ret = do_bind_event(file,ev); + fput(file); + if( ret ) break; + ret = -EBUSY; + break; + } + +out_ev: + kfree(ev); +out: + FEDBG(" files->file_event_list; + unsigned long timeout_jiffies = jiffies; + DECLARE_WAITQUEUE(wait, current); + + FEDBG("sys_get_events( %p, %u, %lu )", uevs, nevs, timeout); + + /* calculate number of jiffies needed to wait; this here part is stolen from + * sys_poll above */ + if (timeout) { + /* Careful about overflow in the intermediate values */ + if ((unsigned long) timeout < MAX_SCHEDULE_TIMEOUT / HZ) { + timeout = (unsigned long)(timeout*HZ+999)/1000+1; + timeout_jiffies += timeout; + } else /* Negative or overflow */ + timeout_jiffies = 0; /* MAX_SCHEDULE_TIMEOUT; */ + } + + + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&(current->files->file_event_wait), &wait); + { + wait_queue_head_t *queue = + &(current->files->file_event_wait); + FEDBG(" sleeping on wait queue, element %p", &wait); + FEDBG(" wqh = %p", queue); + FEDBG(" wqh->prev = %p", queue->task_list.prev); + FEDBG(" wqh->next = %p", queue->task_list.next); + } + for(;;) { + + spin_lock_bh(&list->lock); + + ev = list->head; + while( ev != (file_event_t*)list ) { + int err = copy_to_user( uev, &ev->event, sizeof(*uev) ); + struct file *file; + unsigned long nmask; + + if( signal_pending(current) ) { + if ( !ret ) + ret = -EINTR; + goto out; + } + if( err ) { + if( !ret ) + ret = -EFAULT; + goto out; + } + + FEDBG(" copied ev (fd=%d,mk=%lx,cb=%p,dt=%p) to user space", + ev->event.fd, ev->event.mask, + ev->event.fn, ev->event.data); + + nev = ev->next; + nmask = 0; + file = fget(ev->event.fd); + if( file ) { + nmask = current_file_events(file); + fput(file); + } + if( !nmask || nmask == ev->event.mask ) { + nmask = 0; + file_event_list_del(ev); + } + ev->event.mask = nmask; + ev = nev; + + uev++; + ret++; + if( ret==nevs ) + goto out; + } + + spin_unlock_bh(&list->lock); + + /* if we got something or there was no timeout specified then bail */ + if ( ret || !timeout ) + break; + + if( signal_pending(current) ) { + ret = -EINTR; + goto out; + } + + /* if we were unable to fill the request then wait */ + set_current_state(TASK_INTERRUPTIBLE); + if ( timeout_jiffies ) { + long delta = timeout_jiffies - jiffies; + if( delta < 0 ) goto out; + if( delta > HZ ) delta = HZ; + schedule_timeout( delta ); + } else { + schedule(); /* no timeout */ + /* schedule_timeout( HZ ); */ + } + } + out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&(current->files->file_event_wait), &wait); + current->state = TASK_RUNNING; + + FEDBG(" f_event ); + + /* bind according to default policy */ + do_bind_event( file, &files->default_file_event ); + + /* attach list and wait to the owning task */ + file->f_event_list = &files->file_event_list; + file->f_event_wait = &files->file_event_wait; + } + return 0; +} + +/* releases any bindings the file has with the event list for it's task */ +int file_event_release( struct file *file ) +{ + if( file && file->f_event_list ) { + int flags; + file_event_list_t *list = file->f_event_list; + + spin_lock_irqsave(&list->lock,flags); + if( file->f_event.event.mask ) { + FEDBG("file_event_release( %p ): removing from list", file); + file_event_list_del( &file->f_event ); + } + file->f_event_mask = 0; + spin_unlock_irqrestore(&list->lock,flags); + } + return 0; +} + +/* deliver an event + * file - file pointer, properly locked a la get_file + * mask - what event fired (see fdevent.h) + */ +int deliver_file_event(struct file *file, unsigned long mask) +{ + if( file && (file->f_event_mask & mask) ) { + file_event_list_t *list = file->f_event_list; + file_event_t *ev = &file->f_event; + + int pr = net_ratelimit(); + + if( pr ) + FEDBG("deliver_file_event( %p, %lx ) " + "passes mask (%lx) checks", + file, mask, file->f_event_mask); + + if( list ) { + + spin_lock_bh(&list->lock); + + if( ! ev->event.mask ) { + if( pr ) + FEDBG(" appending event (%p) to list (%p)", + ev, list ); + file_event_list_add_tail( ev, list ); + } + + if( pr ) + FEDBG(" event state moved from %lx to %lx", + ev->event.mask, ev->event.mask|mask); + ev->event.mask |= mask; + + spin_unlock_bh(&list->lock); + + wake_up_interruptible( file->f_event_wait ); + + } + + if( pr ) + FEDBG(" , Chrysalis-ITS */ + +/* This interface is exported by using the bind_event()/get_events() + * systemcall pair; docs are on the web (jukie.net/~bart/kernel/fdevent) + */ +#ifndef __i386_FDEVENT_H +#define __i386_FDEVENT_H + +#include + +/* Event types are borowed from poll.h; + * NOTE that while the current implementation shares the flags of poll() + * this cannot be taken as a rule + */ +#define FDEVENT_IN POLLIN /* 0x0001 */ +#define FDEVENT_PRI POLLPRI /* 0x0002 */ +#define FDEVENT_OUT POLLOUT /* 0x0004 */ +#define FDEVENT_ERR POLLERR /* 0x0008 */ +#define FDEVENT_HUP POLLHUP /* 0x0010 */ +#define FDEVENT_NVAL POLLNVLA /* 0x0020 */ + +/* non standard, sais poll.h */ +#define FDEVENT_RDNORM POLLRDNORM /* 0x0040 */ +#define FDEVENT_RDBAND POLLRDBAND /* 0x0080 */ +#define FDEVENT_WRNORM POLLWRNORM /* 0x0100 */ +#define FDEVENT_WRBAND POLLWRBAND /* 0x0200 */ +#define FDEVENT_MSG POLLMSG /* 0x0400 */ + +struct fdevent; + +typedef void (fdevent_fn)(struct fdevent*); + +struct fdevent { + int fd; + unsigned long mask; + void *data; + fdevent_fn *fn; +}; + +#define FDEVENT_INIT { 0, 0, NULL, NULL } +#define INIT_FDEVENT(ptr) do { \ + (ptr)->fd = 0; (ptr)->mask = 0; \ + (ptr)->data = 0; (ptr)->fn = 0; \ +} while (0) + + +/* wildcards for fdevent.fd */ +#define FDEVENT_FD_EXISTING -1 +#define FDEVENT_FD_DEFAULT -2 + +#ifndef __KERNEL__ +_syscall1( long, bind_event, struct fdevent*, uev ); +_syscall3( long, get_events, struct fdevent*, uevs, + unsigned int, nevs, long, timeout ); +#endif /* __KERNEL__ */ + +#endif diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/include/asm-i386/unistd.h linux-2.4.3+fd_events/include/asm-i386/unistd.h --- linux-2.4.3/include/asm-i386/unistd.h Fri Aug 11 17:39:23 2000 +++ linux-2.4.3+fd_events/include/asm-i386/unistd.h Fri Apr 6 16:28:41 2001 @@ -227,6 +227,8 @@ #define __NR_madvise1 219 /* delete when C lib stub is removed */ #define __NR_getdents64 220 #define __NR_fcntl64 221 +#define __NR_bind_event 222 +#define __NR_get_events 223 /* user-visible error numbers are in the range -1 - -124: see */ diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/include/linux/fdevent.h linux-2.4.3+fd_events/include/linux/fdevent.h --- linux-2.4.3/include/linux/fdevent.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.3+fd_events/include/linux/fdevent.h Sat Apr 14 22:17:10 2001 @@ -0,0 +1,97 @@ +/* fdevent.h - internal definitions of file events interface */ + +/* Written 2001 by Bart Trojanowski , Chrysalis-ITS */ + +/* This interface is exported by using the bind_event()/get_events() + * systemcall pair; docs are on the web (jukie.net/~bart/kernel/fdevent) + */ +#ifndef _LINUX_FDEVENT_H +#define _LINUX_FDEVENT_H + +#ifdef __KERNEL__ + +#include +#include + +#ifdef CONFIG_FILE_EVENTS + +#include +#include +#include + +/* debug macros */ +#ifdef CONFIG_DEBUG_FILE_EVENTS +#define FEDBG(format, arg...) printk(KERN_ERR __FILE__ ":%d: " \ + format "\n" , __LINE__ , ## arg) +#else +#define FEDBG(format, arg...) do{/*nothing*/}while(0) +#endif + +typedef struct file_event_s { + struct file_event_s *next, *prev; /* queue stored in files_struct */ + struct fdevent event; + +} file_event_t; + +typedef struct file_event_list_s { + struct file_event_s *head, *tail; /* just like next/prev above */ + spinlock_t lock; +} file_event_list_t; + +#define FILE_EVENT_INIT { NULL, NULL, FDEVENT_INIT } +#define INIT_FILE_EVENT(ptr) do { \ + (ptr)->next = ptr; (ptr)->prev = ptr; \ + INIT_FDEVENT( &(ptr)->event ); \ +} while (0) + +#define FILE_EVENT_LIST_INIT { NULL, NULL, SPIN_LOCK_UNLOCKED } +#define INIT_FILE_EVENT_LIST(ptr) do { \ + (ptr)->head = (void*)ptr; (ptr)->tail = (void*)ptr; \ + spin_lock_init( &(ptr)->lock ); \ +} while (0) + + +/* + * these are some wrappers for the functions we are interested in + * ... no point in reinventing the wheel. + */ + +static inline void +file_event_list_add_tail( file_event_t *ev, file_event_list_t *list ) +{ + list_add_tail( (struct list_head*)ev, (struct list_head*)list ); +} + +static inline void +file_event_list_del( file_event_t *ev ) +{ + list_del_init( (struct list_head*)ev ); +} + +/* forward declarations */ +struct file; +struct files_struct; + +/* enqueue the event */ +extern int +deliver_file_event(struct file *file, unsigned long mask); + +/* initialize links between the file and the task's files_struct */ +extern int +file_event_init( struct file *file, struct files_struct *files ); + +/* clean up links and remove file from any link list */ +extern int +file_event_release( struct file *file ); + +#define DELIVER_FILE_EVENT(filp,mask) deliver_file_event(filp, mask); + +#else /* CONFIG_FILE_EVENTS */ + +#define DELIVER_FILE_EVENT(filp,mask) do{ /*nothing*/ }while(0) + +#endif /* CONFIG_FILE_EVENTS */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_FDEVENT_H */ diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/include/linux/fs.h linux-2.4.3+fd_events/include/linux/fs.h --- linux-2.4.3/include/linux/fs.h Mon Mar 26 18:48:11 2001 +++ linux-2.4.3+fd_events/include/linux/fs.h Sat Apr 14 22:29:39 2001 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -495,6 +496,13 @@ /* needed for tty driver, and maybe others */ void *private_data; + +#ifdef CONFIG_FILE_EVENTS + unsigned long f_event_mask; /* event mask the user wants to watch for */ + file_event_t f_event; /* dangling link which becomes a part... */ + file_event_list_t *f_event_list;/* ... of this list on files_struct of a task */ + wait_queue_head_t *f_event_wait;/* wake up queue after delivering an event */ +#endif }; extern spinlock_t files_lock; #define file_list_lock() spin_lock(&files_lock); diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/include/linux/sched.h linux-2.4.3+fd_events/include/linux/sched.h --- linux-2.4.3/include/linux/sched.h Mon Mar 26 18:48:11 2001 +++ linux-2.4.3+fd_events/include/linux/sched.h Sat Apr 14 22:29:40 2001 @@ -26,6 +26,7 @@ #include #include #include +#include /* * cloning flags: @@ -177,8 +178,27 @@ fd_set close_on_exec_init; fd_set open_fds_init; struct file * fd_array[NR_OPEN_DEFAULT]; +#ifdef CONFIG_FILE_EVENTS + struct fdevent default_file_event; /* used to initialize files of this struct */ + file_event_list_t file_event_list; /* keep the queue of new events */ + wait_queue_head_t file_event_wait; /* used to wake up sys_get_events caller */ +#endif }; +/* if compiled in then need to initialize the file events part of the files_struct */ +#ifdef CONFIG_FILE_EVENTS +#define INIT_FILES_STRUCT_EVENTS , \ + default_file_event: FDEVENT_INIT, \ + file_event_list: FILE_EVENT_LIST_INIT,\ + file_event_wait: { \ + lock: WAITQUEUE_RW_LOCK_UNLOCKED,\ + task_list: { NULL, NULL } \ + } \ + +#else +#define INIT_FILES_STRUCT_EVENTS /* nothing */ +#endif + #define INIT_FILES \ { \ count: ATOMIC_INIT(1), \ @@ -192,6 +212,7 @@ close_on_exec_init: { { 0, } }, \ open_fds_init: { { 0, } }, \ fd_array: { NULL, } \ + INIT_FILES_STRUCT_EVENTS \ } /* Maximum number of active map areas.. This is a random (large) number */ diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/kernel/fork.c linux-2.4.3+fd_events/kernel/fork.c --- linux-2.4.3/kernel/fork.c Mon Mar 19 15:35:08 2001 +++ linux-2.4.3+fd_events/kernel/fork.c Fri Apr 6 21:27:03 2001 @@ -18,6 +18,7 @@ #include #include #include +#include /* file events interface */ #include #include @@ -440,6 +441,14 @@ newf->close_on_exec = &newf->close_on_exec_init; newf->open_fds = &newf->open_fds_init; newf->fd = &newf->fd_array[0]; + +#ifdef CONFIG_FILE_EVENTS + /* support for file_events on this task */ + INIT_FDEVENT( &newf->default_file_event ); + INIT_FILE_EVENT_LIST( &newf->file_event_list ); + init_waitqueue_head( &newf->file_event_wait ); + /* TODO: I should inherit the events of the parent process */ +#endif /* We don't yet have the oldf readlock, but even if the old fdset gets grown now, we'll only copy up to "size" fds */ @@ -485,6 +494,9 @@ if (f) get_file(f); *new_fds++ = f; +#ifdef CONFIG_FILE_EVENTS + /* TODO: I should inherit the links list of events from the parent process */ +#endif } read_unlock(&oldf->file_lock); diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/net/core/sock.c linux-2.4.3+fd_events/net/core/sock.c --- linux-2.4.3/net/core/sock.c Sat Feb 3 14:26:44 2001 +++ linux-2.4.3+fd_events/net/core/sock.c Fri Apr 6 22:38:39 2001 @@ -79,6 +79,7 @@ * Jay Schulist : Added SO_ATTACH_FILTER and SO_DETACH_FILTER. * Andi Kleen : Add sock_kmalloc()/sock_kfree_s() * Andi Kleen : Fix write_space callback + * Bart Trojanowski: Added file_event support * * To Fix: * @@ -107,6 +108,7 @@ #include #include #include +#include #include #include @@ -1084,6 +1086,8 @@ if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); sk_wake_async(sk,0,POLL_ERR); + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_ERR); read_unlock(&sk->callback_lock); } @@ -1093,6 +1097,8 @@ if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); sk_wake_async(sk,1,POLL_IN); + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_IN); read_unlock(&sk->callback_lock); } @@ -1108,8 +1114,11 @@ wake_up_interruptible(sk->sleep); /* Should agree with poll, otherwise some programs break */ - if (sock_writeable(sk)) + if (sock_writeable(sk)) { sk_wake_async(sk, 2, POLL_OUT); + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_OUT); + } } read_unlock(&sk->callback_lock); diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/net/ipv4/tcp_input.c linux-2.4.3+fd_events/net/ipv4/tcp_input.c --- linux-2.4.3/net/ipv4/tcp_input.c Fri Feb 9 14:34:13 2001 +++ linux-2.4.3+fd_events/net/ipv4/tcp_input.c Fri Apr 6 22:40:04 2001 @@ -60,6 +60,7 @@ * Pasi Sarolahti, * Panu Kuhlberg: Experimental audit of TCP (re)transmission * engine. Lots of bugs are found. + * Bart Trojanowski: Added file_event support */ #include @@ -68,7 +69,7 @@ #include #include #include - +#include /* These are on by default so the code paths get tested. * For the final 2.2 this may be undone at our discretion. -DaveM @@ -2281,10 +2282,15 @@ sk->state_change(sk); /* Do not send POLL_HUP for half duplex close. */ - if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE) + if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE) { sk_wake_async(sk, 1, POLL_HUP); - else + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_HUP); + } else { sk_wake_async(sk, 1, POLL_IN); + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_IN); + } } } @@ -2911,8 +2917,10 @@ if (sk->sleep && waitqueue_active(sk->sleep)) wake_up_interruptible(sk->sleep); - if (sock->fasync_list && !(sk->shutdown&SEND_SHUTDOWN)) + if (sock->fasync_list && !(sk->shutdown&SEND_SHUTDOWN)) { sock_wake_async(sock, 2, POLL_OUT); + DELIVER_FILE_EVENT(sock->file, FDEVENT_OUT); + } /* Satisfy those who hook write_space() callback. */ if (sk->write_space != tcp_write_space) @@ -3020,6 +3028,8 @@ else kill_pg(-sk->proc, SIGURG, 1); sk_wake_async(sk, 3, POLL_PRI); + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_PRI); } /* We may be adding urgent data when the last byte read was @@ -3496,6 +3506,8 @@ if(!sk->dead) { sk->state_change(sk); sk_wake_async(sk, 0, POLL_OUT); + if( sk->socket ) + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_OUT); } if (tp->write_pending || tp->defer_accept) { @@ -3722,6 +3734,7 @@ if (sk->socket) { sk->state_change(sk); sk_wake_async(sk,0,POLL_OUT); + DELIVER_FILE_EVENT(sk->socket->file, FDEVENT_OUT); } tp->snd_una = TCP_SKB_CB(skb)->ack_seq; diff -ruN --exclude-from=_diff_exclude_file linux-2.4.3/net/socket.c linux-2.4.3+fd_events/net/socket.c --- linux-2.4.3/net/socket.c Fri Nov 17 14:36:27 2000 +++ linux-2.4.3+fd_events/net/socket.c Fri Apr 6 16:46:55 2001 @@ -44,6 +44,7 @@ * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0) * Tigran Aivazian : Made listen(2) backlog sanity checks * protocol-independent + * Bart Trojanowsi : Added support for file_event on sockets * * * This program is free software; you can redistribute it and/or @@ -484,6 +485,10 @@ void sock_release(struct socket *sock) { +#ifdef CONFIG_FILE_EVENTS + (void)file_event_release( sock->file ); +#endif + if (sock->ops) sock->ops->release(sock); @@ -898,7 +903,11 @@ retval = sock_map_fd(sock); if (retval < 0) goto out_release; - + +#ifdef CONFIG_FILE_EVENTS + (void)file_event_init( sock->file, current->files ); +#endif + out: /* It may be already another descriptor 8) Not kernel problem. */ return retval; @@ -953,8 +962,13 @@ err = put_user(fd1, &usockvec[0]); if (!err) err = put_user(fd2, &usockvec[1]); - if (!err) + if (!err) { +#ifdef CONFIG_FILE_EVENTS + (void)file_event_init( sock1->file, current->files ); + (void)file_event_init( sock2->file, current->files ); +#endif return 0; + } sys_close(fd2); sys_close(fd1); @@ -1066,6 +1080,10 @@ if ((err = sock_map_fd(newsock)) < 0) goto out_release; + +#ifdef CONFIG_FILE_EVENTS + (void)file_event_init( newsock->file, current->files ); +#endif out_put: sockfd_put(sock);