[PATCH] fix test for vfork function

Rich Felker dalias at aerifal.cx
Fri Apr 27 05:07:42 UTC 2012


On Fri, Apr 27, 2012 at 12:58:33AM -0400, Mike Frysinger wrote:
> On Thursday 26 April 2012 23:08:36 Rich Felker wrote:
> > On Thu, Apr 26, 2012 at 10:50:57PM -0400, Mike Frysinger wrote:
> > > > This patch adds a test for __UCLIBC_VFORK_USES_CLONE__ feature
> > > > definition which an architecture may define if vfork is implemented
> > > > using clone.
> > > 
> > > err, if your kernel arch doesn't have vfork, why is it defining
> > > __NR_vfork ? i.e. the uClibc logic should not require
> > > __UCLIBC_VFORK_USES_CLONE__.  it can deduce that itself by saying "if
> > > !vfork && !fork && clone".
> > 
> > I don't think !fork belongs in the test. Implementing vfork with clone
> > is better than implementing it as just a duplicate of fork. But I'm
> > not sure how having macros for this can be useful at all since,
> > whatever syscall is used to implement vfork, it has to be written in
> > asm unless it's just a duplicate of fork.
> 
> if we've got a C-callable clone(), i think we can implement a C vfork() on top 
> of that.  it'd be a tail call, so the semantics of parallel stack usage should 
> be the same.
> 
> i know ia64 implements vfork() with clone(), but it does it in asm, so that 
> doesn't make my case :p.

The standard libc wrapper API for the clone syscall does not return
twice. It calls a function (function pointer argument) in the new
thread/process. This makes it useless for implementing vfork. In
theory it could be designed to return in the child as well if the
called function returns, but I think the usual behavior is for it to
call SYS_exit (exit thread) in that case..

> > (Providing returns-twice
> > semantics in the same memory space is not possible without asm, except
> > perhaps on some oddball architectures where the return address is
> > stored in a register
> 
> i don't think storing the return address in a register is that odd.  a CALL in 
> the Blackfin ISA stores the return address in the RETS register (return from 
> subroutine) and it's up to the callee to save it if need be (via manual stack 
> push or the LINK insn).  makes leaf functions faster since there's no touching 
> of the stack at all (assuming the code can fit in the scratch registers).

It's not odd in itself; it's combining it with the latter that's odd.

> > and the compiler chooses not to use the stack to
> > store anything in the syscall wrapper function...
> 
> i think that's the point of INLINE_SYSCALL() vs INTERNAL_SYSCALL().  the 
> latter expands into inline asm that only does the syscall and doesn't touch 
> the stack.

Still the surrounding function could have touched the stack. For
instance, even if the return address is stored in a register, the
compiler might decide to save that on the stack, use the return
address register for whatever random use it wants, and then restore it
from the stack later.

This *probably* won't happen as long as the function is a leaf
function, but the compiler is free to do crazy things. With -Os it
might even (in the future) combine common code (e.g. syscall setup
code) in two separate functions into code that's called from both.

> > and relying on that
> > is very unsafe since the compiler's behavior could change.)
> 
> pray you don't look at _fork_parent() in libc/unistd/daemon.c then :p

Is that a dare? :-)

Rich


More information about the uClibc mailing list