Commit 1b3c4f5a authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] Deliver SIGIO to FIFO and pipe devices

Originally from: Jeremy Elson <jelson@circlemud.org>
parent 6e81e748
...@@ -22,6 +22,9 @@ ...@@ -22,6 +22,9 @@
* *
* Reads with count = 0 should always return 0. * Reads with count = 0 should always return 0.
* -- Julian Bradfield 1999-06-07. * -- 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 */ /* Drop the inode semaphore and wait for a pipe event, atomically */
...@@ -117,12 +120,14 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos) ...@@ -117,12 +120,14 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
* room. * room.
*/ */
wake_up_interruptible(PIPE_WAIT(*inode)); wake_up_interruptible(PIPE_WAIT(*inode));
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
if (!PIPE_EMPTY(*inode)) if (!PIPE_EMPTY(*inode))
BUG(); BUG();
goto do_more_read; goto do_more_read;
} }
/* Signal writers asynchronously that there is more room. */ /* Signal writers asynchronously that there is more room. */
wake_up_interruptible(PIPE_WAIT(*inode)); wake_up_interruptible(PIPE_WAIT(*inode));
kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT);
ret = read; ret = read;
out: out:
...@@ -215,6 +220,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) ...@@ -215,6 +220,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
* to do idle reschedules. * to do idle reschedules.
*/ */
wake_up_interruptible(PIPE_WAIT(*inode)); wake_up_interruptible(PIPE_WAIT(*inode));
kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
PIPE_WAITING_WRITERS(*inode)++; PIPE_WAITING_WRITERS(*inode)++;
pipe_wait(inode); pipe_wait(inode);
PIPE_WAITING_WRITERS(*inode)--; PIPE_WAITING_WRITERS(*inode)--;
...@@ -228,6 +234,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) ...@@ -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. */ /* Signal readers asynchronously that there is more data. */
wake_up_interruptible(PIPE_WAIT(*inode)); wake_up_interruptible(PIPE_WAIT(*inode));
kill_fasync(PIPE_FASYNC_READERS(*inode), SIGIO, POLL_IN);
inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_ctime = inode->i_mtime = CURRENT_TIME;
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -308,21 +315,81 @@ pipe_release(struct inode *inode, int decr, int decw) ...@@ -308,21 +315,81 @@ pipe_release(struct inode *inode, int decr, int decw)
kfree(info); kfree(info);
} else { } else {
wake_up_interruptible(PIPE_WAIT(*inode)); 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)); up(PIPE_SEM(*inode));
return 0; 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 static int
pipe_read_release(struct inode *inode, struct file *filp) pipe_read_release(struct inode *inode, struct file *filp)
{ {
pipe_read_fasync(-1, filp, 0);
return pipe_release(inode, 1, 0); return pipe_release(inode, 1, 0);
} }
static int static int
pipe_write_release(struct inode *inode, struct file *filp) pipe_write_release(struct inode *inode, struct file *filp)
{ {
pipe_write_fasync(-1, filp, 0);
return pipe_release(inode, 0, 1); return pipe_release(inode, 0, 1);
} }
...@@ -331,6 +398,7 @@ pipe_rdwr_release(struct inode *inode, struct file *filp) ...@@ -331,6 +398,7 @@ pipe_rdwr_release(struct inode *inode, struct file *filp)
{ {
int decr, decw; int decr, decw;
pipe_rdwr_fasync(-1, filp, 0);
decr = (filp->f_mode & FMODE_READ) != 0; decr = (filp->f_mode & FMODE_READ) != 0;
decw = (filp->f_mode & FMODE_WRITE) != 0; decw = (filp->f_mode & FMODE_WRITE) != 0;
return pipe_release(inode, decr, decw); return pipe_release(inode, decr, decw);
...@@ -383,6 +451,7 @@ struct file_operations read_fifo_fops = { ...@@ -383,6 +451,7 @@ struct file_operations read_fifo_fops = {
ioctl: pipe_ioctl, ioctl: pipe_ioctl,
open: pipe_read_open, open: pipe_read_open,
release: pipe_read_release, release: pipe_read_release,
fasync: pipe_read_fasync,
}; };
struct file_operations write_fifo_fops = { struct file_operations write_fifo_fops = {
...@@ -393,6 +462,7 @@ struct file_operations write_fifo_fops = { ...@@ -393,6 +462,7 @@ struct file_operations write_fifo_fops = {
ioctl: pipe_ioctl, ioctl: pipe_ioctl,
open: pipe_write_open, open: pipe_write_open,
release: pipe_write_release, release: pipe_write_release,
fasync: pipe_write_fasync,
}; };
struct file_operations rdwr_fifo_fops = { struct file_operations rdwr_fifo_fops = {
...@@ -403,6 +473,7 @@ struct file_operations rdwr_fifo_fops = { ...@@ -403,6 +473,7 @@ struct file_operations rdwr_fifo_fops = {
ioctl: pipe_ioctl, ioctl: pipe_ioctl,
open: pipe_rdwr_open, open: pipe_rdwr_open,
release: pipe_rdwr_release, release: pipe_rdwr_release,
fasync: pipe_rdwr_fasync,
}; };
struct file_operations read_pipe_fops = { struct file_operations read_pipe_fops = {
...@@ -413,6 +484,7 @@ struct file_operations read_pipe_fops = { ...@@ -413,6 +484,7 @@ struct file_operations read_pipe_fops = {
ioctl: pipe_ioctl, ioctl: pipe_ioctl,
open: pipe_read_open, open: pipe_read_open,
release: pipe_read_release, release: pipe_read_release,
fasync: pipe_read_fasync,
}; };
struct file_operations write_pipe_fops = { struct file_operations write_pipe_fops = {
...@@ -423,6 +495,7 @@ struct file_operations write_pipe_fops = { ...@@ -423,6 +495,7 @@ struct file_operations write_pipe_fops = {
ioctl: pipe_ioctl, ioctl: pipe_ioctl,
open: pipe_write_open, open: pipe_write_open,
release: pipe_write_release, release: pipe_write_release,
fasync: pipe_write_fasync,
}; };
struct file_operations rdwr_pipe_fops = { struct file_operations rdwr_pipe_fops = {
...@@ -433,6 +506,7 @@ struct file_operations rdwr_pipe_fops = { ...@@ -433,6 +506,7 @@ struct file_operations rdwr_pipe_fops = {
ioctl: pipe_ioctl, ioctl: pipe_ioctl,
open: pipe_rdwr_open, open: pipe_rdwr_open,
release: pipe_rdwr_release, release: pipe_rdwr_release,
fasync: pipe_rdwr_fasync,
}; };
struct inode* pipe_new(struct inode* inode) struct inode* pipe_new(struct inode* inode)
...@@ -453,6 +527,7 @@ 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_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0; PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0;
PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1; PIPE_RCOUNTER(*inode) = PIPE_WCOUNTER(*inode) = 1;
*PIPE_FASYNC_READERS(*inode) = *PIPE_FASYNC_WRITERS(*inode) = NULL;
return inode; return inode;
fail_page: fail_page:
......
...@@ -13,6 +13,8 @@ struct pipe_inode_info { ...@@ -13,6 +13,8 @@ struct pipe_inode_info {
unsigned int waiting_writers; unsigned int waiting_writers;
unsigned int r_counter; unsigned int r_counter;
unsigned int w_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 /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
...@@ -30,6 +32,8 @@ struct pipe_inode_info { ...@@ -30,6 +32,8 @@ struct pipe_inode_info {
#define PIPE_WAITING_WRITERS(inode) ((inode).i_pipe->waiting_writers) #define PIPE_WAITING_WRITERS(inode) ((inode).i_pipe->waiting_writers)
#define PIPE_RCOUNTER(inode) ((inode).i_pipe->r_counter) #define PIPE_RCOUNTER(inode) ((inode).i_pipe->r_counter)
#define PIPE_WCOUNTER(inode) ((inode).i_pipe->w_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_EMPTY(inode) (PIPE_LEN(inode) == 0)
#define PIPE_FULL(inode) (PIPE_LEN(inode) == PIPE_SIZE) #define PIPE_FULL(inode) (PIPE_LEN(inode) == PIPE_SIZE)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment