Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jan 1997 09:37:18 -0500 (EST)
From:      "Ron G. Minnich" <rminnich@Sarnoff.COM>
To:        freebsd-hackers@freebsd.org
Subject:   Re: Using rfork() / threads
Message-ID:  <Pine.SUN.3.91.970131091212.16303A-100000@terra>
In-Reply-To: <199701310201.SAA00278@bubba.whistle.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 30 Jan 1997, Archie Cobbs wrote:
> > > Could you explain a bit more. What exactly is the difference between
> > > VM space sharing and shared data areas from the process' and the
> > > kernel perspective?
> What about the heap... is it shared? What about shared libraries?
> I assume stack regions are not shared...

well let's talk about fork, the vm part anyway. These comments apply to 
freebsd only -- systems such as irix are a bit different, esp. if you use 
sproc(). 

When you fork, there is a vm space that needs to be copied so that the 
new process has its own distinct address space. So a new vm space is 
created and populated with new objects. Each object has a set of flags 
that indicates what should happen when the vmspace_fork is done. These are:

#define VM_INHERIT_SHARE    ((vm_inherit_t) 0)      /* share with child */
#define VM_INHERIT_COPY     ((vm_inherit_t) 1)      /* copy into child */
#define VM_INHERIT_NONE     ((vm_inherit_t) 2)      /* absent from child */
#define VM_INHERIT_DONATE_COPY  ((vm_inherit_t) 3)  /* copy and delete */

Segments for shared library code, text (code), shared mapped files, and
read-only segments are typically VM_INHERIT_SHARE. Segments which are data
(bss, stack, your initial data area, etc). are typically VM_INHERIT_COPY,
which means that they get copy-on-write semantics. 

[[ for an interesting discussion on the (de-)merits of copy-on-write,
look in the usenix archives for the keyword "bovaphobic".]]

So what I did for rfork, v1: 
1) modified /proc so that any process could read the file /seglist
   and determine what segments were part of its address space, and
   what the inherit attributes of those segments were. As an aside, 
   the number of one and two-page length objects is interesting and
   at times depressing. 
   (this (trivial) set of changes was offered to freebsd many times,
    but never picked up. Memo to ron: could openbsd use it? )
   seglist was read-write: you could modify your segments attributes
   by writing to it. Of course normal file permissions apply: you can't 
   sabotage other people's segment attributes!
2) Added a system call (minherit) that let users modify the segment
   inheritance more efficiently. Offered to freebsd, results as above. 
3) added rfork, which had user-mode work and kernel-mode work. 
   rfork user-mode simply set the inherit attributes of everything 
   past _end up to the end of bss (break(0)) to VM_INHERIT_SHARE. 
   so your data areas, but not your stack, ended up shared. 
   rfork kernel simply forked, but also allowed fd table sharing. 

so to sum up: 
1) data areas end up shared
2) stack is not shared
3) in my original version you had a great deal of flexibility as to what
   is shared.

What's not shared is the address space itself, unlike e.g. Irix. So if 
the processes make mods to the address space after the rfork, they are 
not visible to each other. Why's this matter? well, if you're doing a 
user-mode distributed shared memory it matters in some cases, but I've 
written enough here ... 

See openbsd for a different and in many ways better, but less flexible,
version of rfork. in particular, the flexibility of inheritance is not as 
good, but at least you don't have to figure out in user mode what 
inheritance to set. As i understand TDRs implementation of rfork was the 
one that finally made it (albeit with modifications) into freebsd. 

ron



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.SUN.3.91.970131091212.16303A-100000>