diff -ruN --exclude-from=_diff_exclude_from_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 Sun Apr 1 16:07:30 2001 @@ -227,6 +227,10 @@ 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 Descriptor Events Interface (EXPERIMENTAL)' CONFIG_FILE_EVENTS +fi + bool 'Power Management support' CONFIG_PM if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then diff -ruN --exclude-from=_diff_exclude_from_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 1 18:42:40 2001 @@ -491,3 +491,91 @@ poll_freewait(&table); return err; } + +#ifdef CONFIG_FILE_EVENTS +/* 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 + */ +asmlinkage long sys_bind_event(struct fdevent *uev) +{ + struct fdevent *ev; + int err=0; + + if( (ev = kmalloc(sizeof(struct fdevent))) ) { + err = -ENOMEM; + goto out; + } + + if( copy_from_user(ev, uev, sizeof(struct fdevent)) ) { + err = -EFAULT; + goto out_ev; + } + + switch( ev->fd ) { + int i; + struct file *file; + + case FDEVENT_FD_EXISTING: + /* set the ev->mask on each existing current->files->fd[*] */ + for(i=0;ifiles->max_fds;i++) { + file = fget(i); + if( file ) { + file->f_event_mask = ev->mask; + fput(file); + } + } + break; + + case FDEVENT_FD_DEFAULT: + /* set the default mask for new fd to ev->mask */ + current->file_event_default_mask = ev->mask; + break; + + default: + /* set the ev->mask on the specified ev->fd */ + file = fget(i); + if (!file) { + err = -EBADF; + goto out_ev; + } + file->f_event_mask = ev->mask; + fput(file); + } + +out_ev: + kfree(ev); +out: + return err; +} + +/* see sys_bind_event */ +asmlinkage long sys_get_events(struct fdevent *uevs, unsigned int nevs, long timeout) +{ + int ret=0; + register file_event_t *ev; + register fdevent *uev = uevs; + file_event_list_t *list = ¤t->files->file_event_list; + + spinlock_bh(list->lock); + + ev = list->head; + while( ev ) { + if( copy_to_user( uev, ev->event, sizeof(fdevent) ) ) { + if( !ret ) + ret = -EFAULT; + break; + } + ev++; + uev++; + ret++; + if( ret==nevs ) + break; + } + + spinlock_bh(list->lock); + + return ret; +} +#endif diff -ruN --exclude-from=_diff_exclude_from_file linux-2.4.3/include/asm-i386/fdevent.h linux-2.4.3+fd_events/include/asm-i386/fdevent.h --- linux-2.4.3/include/asm-i386/fdevent.h Wed Dec 31 19:00:00 1969 +++ linux-2.4.3+fd_events/include/asm-i386/fdevent.h Sun Apr 1 18:34:33 2001 @@ -0,0 +1,36 @@ +#ifndef __i386_FDEVENT_H +#define __i386_FDEVENT_H + +/* Event types are borowed from poll.h */ +#define FDEVENT_IN 0x0001 +#define FDEVENT_PRI 0x0002 +#define FDEVENT_OUT 0x0004 +#define FDEVENT_ERR 0x0008 +#define FDEVENT_HUP 0x0010 +#define FDEVENT_NVAL 0x0020 + +/* non standard, sais poll.h */ +#define FDEVENT_RDNORM 0x0040 +#define FDEVENT_RDBAND 0x0080 +#define FDEVENT_WRNORM 0x0100 +#define FDEVENT_WRBAND 0x0200 +#define FDEVENT_MSG 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 } + +/* wildcards for fdevent.fd */ +#define FDEVENT_FD_EXISTING -1 +#define FDEVENT_FD_DEFAULT -2 + +#endif diff -ruN --exclude-from=_diff_exclude_from_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 Sun Apr 1 18:34:36 2001 @@ -471,6 +471,25 @@ } u; }; +#ifdef CONFIG_FILE_EVENTS + +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 FILE_EVENT_LIST_INIT { NULL, NULL, SPIN_LOCK_UNLOCKED } + +#endif + + struct fown_struct { int pid; /* pid or -pgrp where SIGIO should be sent */ uid_t uid, euid; /* uid/euid of process setting the owner */ @@ -495,6 +514,10 @@ /* needed for tty driver, and maybe others */ void *private_data; +#ifdef CONFIG_FILE_EVENTS + file_event_t f_event; + unsigned long f_event_mask; +#endif }; extern spinlock_t files_lock; #define file_list_lock() spin_lock(&files_lock); diff -ruN --exclude-from=_diff_exclude_from_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 Sun Apr 1 18:33:00 2001 @@ -177,6 +177,11 @@ fd_set close_on_exec_init; fd_set open_fds_init; struct file * fd_array[NR_OPEN_DEFAULT]; +#ifdef CONFIG_FILE_EVENTS + unsigned long file_event_mask; + unsigned long file_event_default_mask; + file_event_list_t *file_event_list; +#endif }; #define INIT_FILES \ Binary files linux-2.4.3/vmlinux and linux-2.4.3+fd_events/vmlinux differ