From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: Date: Fri, 25 Mar 2005 12:08:14 -0500 From: Russ Cox To: Sergey Reva , Fans of the OS Plan 9 from Bell Labs <9fans@cse.psu.edu> Subject: Re: [9fans] How it work? In-Reply-To: <676328296.20050325123343@mail.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit References: <3813520625.20050324104618@mail.ru> <4439b95e268ad4987f174271ac554f28@smtp.songnetworks.no> <676328296.20050325123343@mail.ru> Cc: Topicbox-Message-UUID: 2b7b95cc-ead0-11e9-9d60-3106f5b1d025 lock(2): Rendezes are rendezvous points. Each Rendez r is protected by a QLock r->l, which must be held by the callers of rsleep, rwakeup, and rwakeupall. Rsleep atomically releases r->l and suspends execution of the calling task. After resuming execution, rsleep will reacquire r->l before returning. If any processes are sleeping on r, rwakeup wakes one of them. it returns 1 if a process was awakened, 0 if not. Rwakeupall wakes all processes sleeping on r, returning the number of processes awakened. Rwakeup and rwakeupall do not release r->l and do not suspend execution of the current task. Before use, Rendezes should be initialized to all zeros except for r->l pointer, which should point at the QLock that will guard r. You're not locking the qlock first. > I can use lock, qlock and rendezvous without any problem but Rendez > don't work... if rsleep executed earlier than rwakeup, abort() cause > exception, stk() show: > rsleep ... /sys/src/libc/9sys/qlock.c:286 > This line contain me = getqlp() in getqlp i find abort()... You're being misled. The line that stk() shows is the code that the call to abort will return to, which is sometimes the next line of code. The actual call is earlier, on line 283 or so: /* we should hold the qlock */ if(!r->l->locked) > abort(); /* add ourselves to the wait list */ me = getqlp(); Since getqlp wasn't on your stack frame, you can be pretty sure that's not what called abort. (The Plan 9 compilers thankfully don't do any tail call elimination.) > in other way when rwakeup executed first, abort() ... stk() show: > rwakeup ... /sys/src/libc/9sys/qlock.c:329 > which point me to another abort() This time the line ref is correct. > Maybe it wrong initialization? But I also try other way... or I wrong > use rendez? Well, yes. In addition to not locking the qlock before calling rsleep or rwakeup, you're not actually checking a condition. > for(;;) > { > print("Sleep\n"); > rsleep(&r); > print("Wake up!\n"); > } > for (x=0;x<10;) > { > if (rwakeup(&r)) > x++; > } I guess this technically will work, but the standard usage is that you're expecting some condition to happen, like there's a shared queue and one thread is waiting for more input and the other thread, which has just added to the queue, wants to wake him. Commonly you see: qlock(&l); while(bad condition) rsleep(&r); code depending on good condition qunlock(&l) and qlock(&l) make condition good rwakeup(&r) qunlock(&l) It's like the sleep and wakeup in the kernel except that the locking is a little different. See http://swtch.com/usr/local/plan9/src/libmux/queue.c for a full example. It's an arbitrarily buffered queue. The Rendez q->r is slept on by receivers waiting for something to be put into the queue. Russ