From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: To: 9fans@cse.psu.edu Subject: Re: [9fans] fun with rfork From: Charles Forsyth In-Reply-To: <007701c3a06d$158bd1b0$8201a8c0@cc77109e> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="upas-kccbtwfckazjokleorqnosurts" Date: Sat, 1 Nov 2003 12:41:32 +0000 Topicbox-Message-UUID: 7ba3dcd4-eacc-11e9-9e20-41e7f4b1d025 This is a multi-part message in MIME format. --upas-kccbtwfckazjokleorqnosurts Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit yes i see now why you said the spinptr code didn't work, but the code i posted was a little different. the spinptr code really did work originally: the code was a little different from what i posted earlier--it had switch(fork()){ which became switch(rfork(RFFDG|RFPROC)) { in your version BUT in Plan 9 when the code was originally written, an rfork with RFMEM caused RFMEM to be implied(!) in all subsequent rforks (and thus forks), so the original spinptr worked because although it said `fork', it was still sharing the address space. (i first noticed the feature when i had a little trouble with the 8-1/2 event library.) when Plan 9's implementation (fortunately) later changed to eliminate that unpleasant effect, the fork made the memory unshared, spinptr stopped working and a rendezvous would indeed be needed. on the other hand, the vstack probably isn't needed then because the two processes are not sharing the stack. my rfork call in the example was rfork(RFMEM|RFPROC|RFFDG|RFENVG|RFREND) which kept the RFMEM (explicitly), and that does keep the spinptr working. not that it's an efficient method, but there's a reason it's hard to use rendezvous straightforwardly in that particular context. it was really some of the peculiar effects of RFMEM and consequent shared (malloc'd) stack in this particular case that interested me, as an example of how plausible code and helpful comments can be completely misleading. the idea behind spinptr/vstack is that the two processes are sharing the malloc'd stack after the rfork so the child calls assembly-language vstack to shift its stack to its private, unshared memory (rfork even with RFMEM doesn't share the stack segment). until the child does that, the parent had better not budge because that would change the stack on which the child is still executing, corrupting its data. once the child has switched to its unshared stack, by setting SP to the value of ustack, which points into the unshared stack segment, it can let the parent continue. it works, but for odd reasons, and it's critical how the code is arranged. one key point is that the comment next to vstack, is wrong (on an x86). the set of possible execution traces is rather bizarre, and depends who runs first after the rfork. the child needs to call something in assembly language to change the stack pointer. they both return from rfork. if the parent returns first, it blocks on the while(*spinptr) ; the child process runs, calls vstack, changes its stack pointer, calls exectramp on that new stack, writes zero to the spin value, and allows the parent to proceed. if the child returns from rfork first, it calls vstack, changes its stack pointer, etc. the parent returns from rfork, finds *spinptr zero and simply continues on its way. that's the way the code is written but it overlooks the stack sharing: the child must call vstack (it can't change the stack pointer otherwise), so its return address will be at the default: following the call to vstack. but its stack is the parent's too, so its vstack return address replaces the parent's rfork return address, and when it runs it doesn't execute the switch but ends up on the other side of the vstack call, and falls through into the default: case. of course on a multiprocessor the two paths can run concurrently, or if a time slice hits on a uniprocessor, they can be interleaved. switch(rfork(RFPROC|RFMEM|RFREND|RFNOTEG|RFFDG|RFNAMEG|RFENVG)) { case -1: goto Error; case 0: /* if child returns first from rfork, its call to vstack replaces ... */ vstack(t); /* ... parent's return address from rfork and parent returns here */ default: /* if parent returns first from rfork, it comes here */ /* can't call anything: on shared stack until child releases spin in exectramp */ while(*spinptr) ; break; } --upas-kccbtwfckazjokleorqnosurts Content-Type: message/rfc822 Content-Disposition: inline Return-path: <9fans-admin@cse.psu.edu> Received: from punt-3.mail.demon.net by mailstore for forsyth@caldo.demon.co.uk id 1AFu6M-0001DN-Aa; Sat, 01 Nov 2003 11:39:30 +0000 Received: from [130.203.4.6] (helo=mail.cse.psu.edu) by punt-3.mail.demon.net with esmtp id 1AFu6M-0001DN-Aa for forsyth@caldo.demon.co.uk; Sat, 01 Nov 2003 11:39:30 +0000 Received: by mail.cse.psu.edu (CSE Mail Server, from userid 60001) id 8858A19980; Sat, 1 Nov 2003 06:39:29 -0500 (EST) Received: from psuvax1.cse.psu.edu (psuvax1.cse.psu.edu [130.203.23.6]) by mail.cse.psu.edu (CSE Mail Server) with ESMTP id B2BA019B66; Sat, 1 Nov 2003 06:39:08 -0500 (EST) X-Original-To: 9fans@cse.psu.edu Delivered-To: 9fans@cse.psu.edu Received: by mail.cse.psu.edu (CSE Mail Server, from userid 60001) id A4F3019980; Sat, 1 Nov 2003 06:38:41 -0500 (EST) Received: from wmail.atlantic.net (wmail.atlantic.net [209.208.0.84]) by mail.cse.psu.edu (CSE Mail Server) with SMTP id 85EE1199E1 for <9fans@cse.psu.edu>; Sat, 1 Nov 2003 06:38:29 -0500 (EST) Received: (qmail 11756 invoked from network); 1 Nov 2003 11:38:08 -0000 Received: from cpe-203-51-66-224.nsw.bigpond.net.au (HELO cc77109e) (203.51.66.224) by wmail.atlantic.net with SMTP; 1 Nov 2003 11:38:08 -0000 Message-ID: <007701c3a06d$158bd1b0$8201a8c0@cc77109e> From: "Bruce Ellis" To: <9fans@cse.psu.edu> References: Subject: Re: [9fans] fun with rfork Organization: www.chunder.com MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1158 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165 Sender: 9fans-admin@cse.psu.edu Errors-To: 9fans-admin@cse.psu.edu X-BeenThere: 9fans@cse.psu.edu X-Mailman-Version: 2.0.11 Precedence: bulk Reply-To: 9fans@cse.psu.edu List-Id: Fans of the OS Plan 9 from Bell Labs <9fans.cse.psu.edu> List-Archive: Date: Sat, 1 Nov 2003 22:40:44 +1100 X-Spam-Status: No, hits=-0.5 required=5.0 tests=REFERENCES version=2.55 X-Spam-Level: X-Spam-Checker-Version: SpamAssassin 2.55 (1.174.2.19-2003-05-19-exp) looks a bit like this ... targ.fd = fd[0]; targ.cmd = cmd; targ.tag = &tag; switch(rfork(RFFDG|RFPROC)) { case -1: return -1; case 0: vstack(&targ); /* Never returns */ default: rendezvous(&tag, 0); break; } ----- Original Message ----- From: "Charles Forsyth" To: <9fans@cse.psu.edu> Sent: Saturday, November 01, 2003 10:03 AM Subject: Re: [9fans] fun with rfork > even more than that! > i ought to have said that it's perhaps most interesting on > an x86. (Hint: how and where could you call rendezvous?) > --upas-kccbtwfckazjokleorqnosurts--