Subject: new vfork(2) implementation
To: None <current-users@NetBSD.ORG>
From: Jason Thorpe <firstname.lastname@example.org>
Date: 01/03/1998 13:21:56
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
194.23 real 55.24 user 51.74 sys
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 email@example.com
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