Subject: Re: signal(SIGSEGV, SIG_IGN) -> 100% CPU
To: None <tech-kern@netbsd.org>
From: Greg A. Woods <woods@most.weird.com>
List: tech-kern
Date: 06/10/1999 22:48:49
I remember way back in the V7 days wondering why pipe(2) was such a
qirky system call (this was because I was actually writing PDP11
assembler programs under V7). To me it seemed as though pipe(2) managed
its function arguments differently than some other system calls I was
experimenting with. This is because of course in V6 and V7 on the PDP11
family the pipe() system call returned the two file descriptors it had
allocated in R0 and R1 (i.e. in the CPU registers). Even back then
before I was so pedantic about writing safe code it seemed strange to be
hacking such an almost zero-gain optimisation into what would otherwise
be a straight forward system call with a pointer argument.
Looking at all the libc/arch/*/sys/pipe.S implementations in NetBSD
shows that nothing has changed -- the magic still happens.
(BTW, reading sys_pipe() in NetBSD's sys/kern/uipc_syscalls.c makes me
long for the clean and easy-to-read code in V6! Goto's suck, especially
for the purpose they're put to in that code -- even nesting it would be
immensely better.)
IMNSHO the pipe(2) manual page in NetBSD is "correct" for modern Unix
implementations though (i.e. pipe(2) should return EFAULT if an invalid
pointer is handed to it). The kernel should implement pipe(2) in just
the same way as it implements socketpair(2). The extra overhead of a
consistent implementation is of little consequence here -- I don't think
anyone really needs to call pipe() in a tight loop, and I don't think we
need to worry about the tiny optimization gained by returning pairs of
'int' variables in CPU registers, at least not in this case. The
elimination of libc/arch/*/sys/pipe.S would be nice to see too! The
only "sad" thing about it would be the loss of a bit of history and the
removal of some fine examples of how to squeeze two syscall return
values into CPU registers on several platforms.
Besides, just exactly how is a function in a user process supposed to
figure out if some pointer it's handed is legal? The only hacks I can
think of are far more intrusive than simply "fixing" the system call and
letting the kernel detect the EFAULT where it's easy to do so
transparently.
--
Greg A. Woods
+1 416 218-0098 VE3TCP <gwoods@acm.org> <robohack!woods>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>