Subject: new vfork(2) implementation
To: None <current-users@NetBSD.ORG>
From: Jason Thorpe <>
List: current-users
Date: 01/03/1998 13:21:56
Hi folks,

Well, with NetBSD 1.3 almost out the door (the announcement should be
any time now..), it's time to start thinking about running -current again
(well, for some of us :-)

For those of you who will be running NetBSD-current, this is a heads-up.
Later on today, I will be committing my new vfork(2) implementation (well,
the last bits of it; the pmap and vm changes I've committed over the last
few days are directly related).  This new implementation will have the
original 3BSD vfork semantics: a completely shared address space as well
as parent blocks for child exit (contrast that to the current NetBSD vfork
that came from 4.4BSD, which simply blocks the parent).

Orignally, vfork was implemented because the address space was copied at
fork time.  This was a time consuming process, and a real waste if the
program were to immediately exec (which would then unmap the address space
so painstakenly copied just moments ago).  When copy-on-write was added
to BSD (when it got the Mach VM system), the address space was no longer
copied.  Instead, the VM map entries were copied, and the pages set for
COW (by calling into the pmap layer to write-protect the pages).  This
greatly lessened the need for vfork(2), and vfork(2) was changed to merely
perserve the previous synchronization semantics.

However, copying the VM map entries, and invoking the pmap to set the
pages for COW is still somewhat expensive, especially for large processes
(which have many VM map entries, and physical pages to protect).  Also,
the previous shared-memory semantics were lost (which were less important,
since not very many programs relied on this feature).

So, I have implemented a Real vfork(2), which has the pre-4.4BSD vfork
semantics.  On a simple test ("make obj" from /usr/src, on my PPro 200,
source and objs on different local disks), this is the speed improvement
I've seen:

4.4BSD vfork:
	194.23 real        55.24 user        51.74 sys

New vfork:
	167.14 real        53.12 user        42.75 sys

The effect can be more or less pronounced depending on a number of variables,
but it's an improvement nontheless :-)

I will be allocating a new system call number and using function versioning
to add this call, so that old binaries that don't follow the vfork rules
will continue to work.  Those rules, for those who don't know, are:

	(1) Must be very careful with local variables, since the child
	    and the parent may end up sharing them.

	(2) In the child, never call "return" from the context where the
	    vfork occured.  It will trash the parent's stack.

	(3) In the child, never call exit(3) (or anything that calls exit(3)),
	    because it will run the parent's exit-time cleanup functions,
	    modifying the parent's address space.  Use _exit(2) instead.

Anyhow, this is a heads-up... it will be just a little while yet before
the NetBSD-current sources switch back to the trunk.

Jason R. Thorpe                             
NASA Ames Research Center                            Home: +1 408 866 1912
NAS: M/S 258-6                                       Work: +1 650 604 0935
Moffett Field, CA 94035                             Pager: +1 415 428 6939