patch-2.3.29 linux/fs/pipe.c
Next file: linux/fs/proc/Makefile
Previous file: linux/fs/nfsd/stats.c
Back to the patch index
Back to the overall index
- Lines: 154
- Date:
Sun Nov 21 11:17:45 1999
- Orig file:
v2.3.28/linux/fs/pipe.c
- Orig date:
Fri Sep 10 23:57:36 1999
diff -u --recursive --new-file v2.3.28/linux/fs/pipe.c linux/fs/pipe.c
@@ -51,6 +51,7 @@
/* Seeks are not allowed on pipes. */
ret = -ESPIPE;
+ read = 0;
if (ppos != &filp->f_pos)
goto out_nolock;
@@ -65,6 +66,7 @@
goto out_nolock;
if (PIPE_EMPTY(*inode)) {
+do_more_read:
ret = 0;
if (!PIPE_WRITERS(*inode))
goto out;
@@ -74,7 +76,9 @@
goto out;
for (;;) {
+ PIPE_WAITING_READERS(*inode)++;
pipe_wait(inode);
+ PIPE_WAITING_READERS(*inode)--;
ret = -ERESTARTSYS;
if (signal_pending(current))
goto out_nolock;
@@ -90,7 +94,6 @@
/* Read what data is available. */
ret = -EFAULT;
- read = 0;
while (count > 0 && (size = PIPE_LEN(*inode))) {
char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode);
ssize_t chars = PIPE_MAX_RCHUNK(*inode);
@@ -115,16 +118,26 @@
if (!PIPE_LEN(*inode))
PIPE_START(*inode) = 0;
- /* Signal writers there is more room. */
+ if (count && PIPE_WAITING_WRITERS(*inode) && !(filp->f_flags & O_NONBLOCK)) {
+ /*
+ * We know that we are going to sleep: signal
+ * writers synchronously that there is more
+ * room.
+ */
+ wake_up_interruptible_sync(PIPE_WAIT(*inode));
+ if (!PIPE_EMPTY(*inode))
+ BUG();
+ goto do_more_read;
+ }
+ /* Signal writers asynchronously that there is more room. */
wake_up_interruptible(PIPE_WAIT(*inode));
- if (read)
- UPDATE_ATIME(inode);
ret = read;
-
out:
up(PIPE_SEM(*inode));
out_nolock:
+ if (read)
+ ret = read;
return ret;
}
@@ -136,6 +149,7 @@
/* Seeks are not allowed on pipes. */
ret = -ESPIPE;
+ written = 0;
if (ppos != &filp->f_pos)
goto out_nolock;
@@ -148,13 +162,13 @@
if (down_interruptible(PIPE_SEM(*inode)))
goto out_nolock;
+do_more_write:
/* No readers yields SIGPIPE. */
if (!PIPE_READERS(*inode))
goto sigpipe;
/* If count <= PIPE_BUF, we have to make it atomic. */
free = (count <= PIPE_BUF ? count : 1);
- written = 0;
/* Wait, or check for, available space. */
if (filp->f_flags & O_NONBLOCK) {
@@ -163,7 +177,9 @@
goto out;
} else {
while (PIPE_FREE(*inode) < free) {
+ PIPE_WAITING_WRITERS(*inode)++;
pipe_wait(inode);
+ PIPE_WAITING_WRITERS(*inode)--;
ret = -ERESTARTSYS;
if (signal_pending(current))
goto out_nolock;
@@ -204,9 +220,15 @@
break;
do {
- /* This should be a synchronous wake-up: don't do idle reschedules! */
- wake_up_interruptible(PIPE_WAIT(*inode));
+ /*
+ * Synchronous wake-up: it knows that this process
+ * is going to give up this CPU, so it doesnt have
+ * to do idle reschedules.
+ */
+ wake_up_interruptible_sync(PIPE_WAIT(*inode));
+ PIPE_WAITING_WRITERS(*inode)++;
pipe_wait(inode);
+ PIPE_WAITING_WRITERS(*inode)--;
if (signal_pending(current))
goto out_nolock;
if (down_interruptible(PIPE_SEM(*inode)))
@@ -217,19 +239,27 @@
ret = -EFAULT;
}
- /* Signal readers there is more data. */
+ if (count && PIPE_WAITING_READERS(*inode) &&
+ !(filp->f_flags & O_NONBLOCK)) {
+ wake_up_interruptible_sync(PIPE_WAIT(*inode));
+ goto do_more_write;
+ }
+ /* Signal readers asynchronously that there is more data. */
wake_up_interruptible(PIPE_WAIT(*inode));
- ret = (written ? written : -EAGAIN);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
mark_inode_dirty(inode);
out:
up(PIPE_SEM(*inode));
out_nolock:
+ if (written)
+ ret = written;
return ret;
sigpipe:
+ if (written)
+ goto out;
up(PIPE_SEM(*inode));
send_sig(SIGPIPE, current, 0);
return -EPIPE;
@@ -552,6 +582,7 @@
PIPE_BASE(*inode) = (char *) page;
PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+ PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0;
/*
* Mark the inode dirty from the very beginning,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)