]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Deliver SIGIO to FIFO and pipe devices
authorDave Jones <davej@suse.de>
Fri, 31 May 2002 03:47:35 +0000 (20:47 -0700)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Fri, 31 May 2002 03:47:35 +0000 (20:47 -0700)
Originally from: Jeremy Elson <jelson@circlemud.org>

fs/pipe.c
include/linux/pipe_fs_i.h

index 4d96daf42bb208985422c55612a41b60c745feb6..4a6a5682de1ac43f28fc571ee59fa2dc3843704d 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -22,6 +22,9 @@
  * 
  * Reads with count = 0 should always return 0.
  * -- Julian Bradfield 1999-06-07.
+ *
+ * FIFOs and Pipes now generate SIGIO for both readers and writers.
+ * -- Jeremy Elson <jelson@circlemud.org> 2001-08-16
  */
 
 /* Drop the inode semaphore and wait for a pipe event, atomically */
@@ -117,12 +120,14 @@ do_more_read:
                 * room.
                 */
                wake_up_interruptible(PIPE_WAIT(*inode));
+               kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
                if (!PIPE_EMPTY(*inode))
                        BUG();
                goto do_more_read;
        }
        /* Signal writers asynchronously that there is more room.  */
        wake_up_interruptible(PIPE_WAIT(*inode));
+       kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
 
        ret = read;
 out:
@@ -215,6 +220,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
                         * to do idle reschedules.
                         */
                        wake_up_interruptible(PIPE_WAIT(*inode));
+                       kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
                        PIPE_WAITING_WRITERS(*inode)++;
                        pipe_wait(inode);
                        PIPE_WAITING_WRITERS(*inode)--;
@@ -228,6 +234,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
 
        /* Signal readers asynchronously that there is more data.  */
        wake_up_interruptible(PIPE_WAIT(*inode));
+       kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
 
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
        mark_inode_dirty(inode);
@@ -308,21 +315,81 @@ pipe_release(struct inode *inode, int decr, int decw)
                kfree(info);
        } else {
                wake_up_interruptible(PIPE_WAIT(*inode));
+               kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
+               kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
        }
        up(PIPE_SEM(*inode));
 
        return 0;
 }
 
+static int
+pipe_read_fasync(int fd, struct file *filp, int on)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       int retval;
+
+       down(PIPE_SEM(*inode));
+       retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
+       up(PIPE_SEM(*inode));
+
+       if (retval < 0)
+               return retval;
+
+       return 0;
+}
+
+
+static int
+pipe_write_fasync(int fd, struct file *filp, int on)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       int retval;
+
+       down(PIPE_SEM(*inode));
+       retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
+       up(PIPE_SEM(*inode));
+
+       if (retval < 0)
+               return retval;
+
+       return 0;
+}
+
+
+static int
+pipe_rdwr_fasync(int fd, struct file *filp, int on)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       int retval;
+
+       down(PIPE_SEM(*inode));
+
+       retval = fasync_helper(fd, filp, on, PIPE_FASYNC_READERS(*inode));
+
+       if (retval >= 0)
+               retval = fasync_helper(fd, filp, on, PIPE_FASYNC_WRITERS(*inode));
+
+       up(PIPE_SEM(*inode));
+
+       if (retval < 0)
+               return retval;
+
+       return 0;
+}
+
+
 static int
 pipe_read_release(struct inode *inode, struct file *filp)
 {
+       pipe_read_fasync(-1, filp, 0);
        return pipe_release(inode, 1, 0);
 }
 
 static int
 pipe_write_release(struct inode *inode, struct file *filp)
 {
+       pipe_write_fasync(-1, filp, 0);
        return pipe_release(inode, 0, 1);
 }
 
@@ -331,6 +398,7 @@ pipe_rdwr_release(struct inode *inode, struct file *filp)
 {
        int decr, decw;
 
+       pipe_rdwr_fasync(-1, filp, 0);
        decr = (filp->f_mode & FMODE_READ) != 0;
        decw = (filp->f_mode & FMODE_WRITE) != 0;
        return pipe_release(inode, decr, decw);
@@ -383,6 +451,7 @@ struct file_operations read_fifo_fops = {
        ioctl:          pipe_ioctl,
        open:           pipe_read_open,
        release:        pipe_read_release,
+       fasync:         pipe_read_fasync,
 };
 
 struct file_operations write_fifo_fops = {
@@ -393,6 +462,7 @@ struct file_operations write_fifo_fops = {
        ioctl:          pipe_ioctl,
        open:           pipe_write_open,
        release:        pipe_write_release,
+       fasync:         pipe_write_fasync,
 };
 
 struct file_operations rdwr_fifo_fops = {
@@ -403,6 +473,7 @@ struct file_operations rdwr_fifo_fops = {
        ioctl:          pipe_ioctl,
        open:           pipe_rdwr_open,
        release:        pipe_rdwr_release,
+       fasync:         pipe_rdwr_fasync,
 };
 
 struct file_operations read_pipe_fops = {
@@ -413,6 +484,7 @@ struct file_operations read_pipe_fops = {
        ioctl:          pipe_ioctl,
        open:           pipe_read_open,
        release:        pipe_read_release,
+       fasync:         pipe_read_fasync,
 };
 
 struct file_operations write_pipe_fops = {
@@ -423,6 +495,7 @@ struct file_operations write_pipe_fops = {
        ioctl:          pipe_ioctl,
        open:           pipe_write_open,
        release:        pipe_write_release,
+       fasync:         pipe_write_fasync,
 };
 
 struct file_operations rdwr_pipe_fops = {
@@ -433,6 +506,7 @@ struct file_operations rdwr_pipe_fops = {
        ioctl:          pipe_ioctl,
        open:           pipe_rdwr_open,
        release:        pipe_rdwr_release,
+       fasync:         pipe_rdwr_fasync,
 };
 
 struct inode* pipe_new(struct inode* inode)
@@ -453,6 +527,7 @@ struct inode* pipe_new(struct inode* inode)
        PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
        PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0;
        PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
+       *PIPE_FASYNC_READERS(*inode) = *PIPE_FASYNC_WRITERS(*inode) = NULL;
 
        return inode;
 fail_page:
index 16fadad4d92ff9bad983c6deb68c2c75ee670007..d6a7928a2866fae523b8eedf45adf2048a8b1179 100644 (file)
@@ -13,6 +13,8 @@ struct pipe_inode_info {
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
+       struct fasync_struct *fasync_readers;
+       struct fasync_struct *fasync_writers;
 };
 
 /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
@@ -30,6 +32,8 @@ struct pipe_inode_info {
 #define PIPE_WAITING_WRITERS(inode)    ((inode).i_pipe->waiting_writers)
 #define PIPE_RCOUNTER(inode)   ((inode).i_pipe->r_counter)
 #define PIPE_WCOUNTER(inode)   ((inode).i_pipe->w_counter)
+#define PIPE_FASYNC_READERS(inode)     (&((inode).i_pipe->fasync_readers))
+#define PIPE_FASYNC_WRITERS(inode)     (&((inode).i_pipe->fasync_writers))
 
 #define PIPE_EMPTY(inode)      (PIPE_LEN(inode) == 0)
 #define PIPE_FULL(inode)       (PIPE_LEN(inode) == PIPE_SIZE)