From owner-freebsd-current Fri Sep 19 07:18:09 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id HAA14594 for current-outgoing; Fri, 19 Sep 1997 07:18:09 -0700 (PDT) Received: from khavrinen.lcs.mit.edu (khavrinen.lcs.mit.edu [18.24.4.193]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id HAA14587 for ; Fri, 19 Sep 1997 07:18:03 -0700 (PDT) Received: (from wollman@localhost) by khavrinen.lcs.mit.edu (8.8.5/8.8.5) id KAA28139; Fri, 19 Sep 1997 10:17:57 -0400 (EDT) Date: Fri, 19 Sep 1997 10:17:57 -0400 (EDT) From: Garrett Wollman Message-Id: <199709191417.KAA28139@khavrinen.lcs.mit.edu> To: "John S. Dyson" Cc: current@FreeBSD.ORG Subject: Re: FYI: regarding our rfork(2) In-Reply-To: <199709190119.UAA00556@dyson.iquest.net> References: <199709190012.CAA11932@ocean.campus.luth.se> <199709190119.UAA00556@dyson.iquest.net> Sender: owner-freebsd-current@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk < said: > We are actually doing a pure memory sharing operation. We will be sharing > everything, plan 9 doesn't appear to share the stack. In order to support > pthreads, (and most thread schemes that I have seen), it is best to allow > full access to all of the thread stacks. The 'full sharing' scheme is very > fast. We ought to emulate SGI's sproc(2) system call as well, which does essentially the same thing. It has the useful feature that it takes as an argument the address of a function to call, and does all the stack creation magic internally before calling same. So, the inner loop of a program I wrote a long time ago on an SGI looks like this: void do_sproc(volatile int *manyRows[]) { int pids[MAXPROCS]; struct info infos[MAXPROCS]; int i; double aval = curA; for(i=0; i < nprocs - 1; i++,aval -= aincr) { infos[i].row = manyRows[i]; infos[i].curA = aval; pids[i] = sproc(doit,PR_SALL,(void *)&infos[i]); } real_doit(aval,manyRows[i]); /* * We know we started (nprocs - 1) kids, so we wait for (nprocs - 1) kids * to die. */ for(i=0; i < nprocs - 1; i++) { (void)wait((int *)0); } } The prototype is: int sproc(void (*func)(void *arg), unsigned what, ... /* void */); int sprocsp(void (*func)(void *arg, size_t stklen), unsigned what, void *arg, caddr_t sp /* 0 == auto */, size_t maxstklen); There is also a related function: int prctl(pid_t pid, unsigned what, ...); which manages some process-related behavior. The particularly interesting values of `what' for sproc are: PR_SADDR (== RFMEM) PR_SFD (== RFFDG) PR_SDIR (== like RFFDG but for curdir/rootdir) PR_SUMASK (== like RFFDG but for umask) PR_SULIMIT (== like RFFDG but for resource limits) PR_SID (== like RFFDG but for credentials) PR_SALL (== all of the above) There are additionally a couple of of flags, PR_BLOCK (used to provide vfork-like behavior, if I read the man page right) and PR_NOLIBC (which disables the C library thread support for the new child). The prctl(2) system call has a couple of potentially interesting options and a lot of boring ones. The potentially interesting ones are PR_SETEXITSIG (which selects either standard POSIX exit(2) behavior, or causes each share to get a specified signal if the named process exits), and PR_TERMCHILD (which causes children of the caller to receive a SIGHUP if the parent exits). -GAWollman -- Garrett A. Wollman | O Siem / We are all family / O Siem / We're all the same wollman@lcs.mit.edu | O Siem / The fires of freedom Opinions not those of| Dance in the burning flame MIT, LCS, CRS, or NSA| - Susan Aglukark and Chad Irschick