On a SMP system, contention of PIPE_SEM leads to unnecessary scheduling.
Using "adaptive semaphores" (from my previous post to this list), this
problem is easily solved.
I originally tried to do this replacing PIPE_SEM with a spinlock, but
this
is a cleaner way and it should not deadlock when copy_from_user
pagefaults
(Thanks to Manfred Spraul for pointing out this problem).
Hope this patch is useful,
Martin
PS: a good example to show the performance problem of stock SMP 2.3.*
kernels is the "pipedis" benchmark program in the IX_SSBA benchmark
suite
(basically it's just one process writing into a pipe and another reading
from it).
Under 2.2.14. "pipedis 500000 1" takes about 2 seconds, under 2.3.47
almost 6 seconds - using this patch the time is back to a bit more than
2 seconds. [under 2.2.14 the access to pipe_read/pipe_write was
protected
by the kernel lock instead of the semaphore]
--- /home/martin/linuxelf-2.3.orig/fs/pipe.c Fri Feb 11 20:02:05 2000
+++ pipe.c Sun Feb 27 16:34:33 2000
@@ -62,9 +62,9 @@
/* Get the pipe semaphore */
ret = -ERESTARTSYS;
- if (down_interruptible(PIPE_SEM(*inode)))
- goto out_nolock;
+ /* try to spin first, interruptible is not necessary */
+ down_adapt(PIPE_SEM(*inode));
if (PIPE_EMPTY(*inode)) {
do_more_read:
ret = 0;
@@ -82,8 +82,7 @@
ret = -ERESTARTSYS;
if (signal_pending(current))
goto out_nolock;
- if (down_interruptible(PIPE_SEM(*inode)))
- goto out_nolock;
+ down_adapt(PIPE_SEM(*inode));
ret = 0;
if (!PIPE_EMPTY(*inode))
break;
@@ -159,9 +158,7 @@
goto out_nolock;
ret = -ERESTARTSYS;
- if (down_interruptible(PIPE_SEM(*inode)))
- goto out_nolock;
-
+ down_adapt(PIPE_SEM(*inode));
do_more_write:
/* No readers yields SIGPIPE. */
if (!PIPE_READERS(*inode))
@@ -183,9 +180,7 @@
ret = -ERESTARTSYS;
if (signal_pending(current))
goto out_nolock;
- if (down_interruptible(PIPE_SEM(*inode)))
- goto out_nolock;
-
+ down_adapt(PIPE_SEM(*inode));
if (!PIPE_READERS(*inode))
goto sigpipe;
}
@@ -231,8 +226,7 @@
PIPE_WAITING_WRITERS(*inode)--;
if (signal_pending(current))
goto out_nolock;
- if (down_interruptible(PIPE_SEM(*inode)))
- goto out_nolock;
+ down_adapt(PIPE_SEM(*inode));
if (!PIPE_READERS(*inode))
goto sigpipe;
} while (!PIPE_FREE(*inode));
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Tue Feb 29 2000 - 21:00:17 EST