7 QueuingW, /* queuing for write lock */
8 QueuingR, /* queuing for read lock */
12 typedef struct Thread Thread;
24 Thread *writer; /* thread writering write lock */
25 int readers; /* number writering read lock */
40 static Thread **vtRock;
42 static void vtThreadInit(void);
43 static void threadSleep(Thread*);
44 static void threadWakeup(Thread*);
47 vtThread(void (*f)(void*), void *rock)
51 tid = rfork(RFNOWAIT|RFMEM|RFPROC);
92 if(p != nil && p->pid == pid) {
96 p = vtMemAllocZ(sizeof(Thread));
123 fprint(2, "vtGetError: %s\n", threadLookup()->error);
124 s = threadLookup()->error;
126 return "unknown error";
131 vtSetError(char* fmt, ...)
140 s = vsmprint(fmt, args);
145 fprint(2, "vtSetError: %s\n", p->error);
146 werrstr("%s", p->error);
160 vtRock = privalloc();
162 vtFatal("can't allocate thread-private storage");
169 return vtMemAllocZ(sizeof(VtLock));
173 * RSC: I think the test is backward. Let's see who uses it.
176 vtLockInit(VtLock **p)
188 vtLockFree(VtLock *p)
192 assert(p->writer == nil);
193 assert(p->readers == 0);
194 assert(p->qfirst == nil);
199 vtRendezAlloc(VtLock *p)
203 q = vtMemAllocZ(sizeof(VtRendez));
205 setmalloctag(q, getcallerpc(&p));
210 vtRendezFree(VtRendez *q)
214 assert(q->wfirst == nil);
225 if(p->writer == nil && p->readers == 0) {
242 if(p->writer == nil && p->readers == 0) {
249 * venti currently contains code that assume locks can be passed between threads :-(
250 * assert(p->writer != t);
263 assert(p->writer == t && p->readers == 0);
267 vtCanRLock(VtLock *p)
270 if(p->writer == nil && p->qfirst == nil) {
286 if(p->writer == nil && p->qfirst == nil) {
293 * venti currently contains code that assumes locks can be passed between threads
294 * assert(p->writer != t);
306 assert(p->writer == nil && p->readers > 0);
316 * venti currently has code that assumes lock can be passed between threads :-)
317 * assert(p->writer == *vtRock);
319 assert(p->writer != nil);
320 assert(p->readers == 0);
327 if(t->state == QueuingW) {
336 while(t != nil && t->state == QueuingR) {
352 assert(p->writer == nil && p->readers > 0);
355 if(p->readers > 0 || t == nil) {
359 assert(t->state == QueuingW);
378 * venti currently contains code that assume locks can be passed between threads :-(
379 * assert(p->writer != s);
381 assert(p->writer != nil);
382 assert(p->readers == 0);
386 } else if(t->state == QueuingW) {
392 while(t != nil && t->state == QueuingR) {
409 assert(p->writer == s);
414 vtWakeup(VtRendez *q)
420 * take off wait and put on front of queue
421 * put on front so guys that have been waiting will not get starved
426 * venti currently has code that assumes lock can be passed between threads :-)
427 * assert(p->writer == *vtRock);
429 assert(p->writer != nil);
447 vtWakeupAll(VtRendez *q)
451 for(i=0; vtWakeup(q); i++)
457 threadSleep(Thread *t)
459 if(rendezvous(t, (void*)0x22bbdfd6) != (void*)0x44391f14)
460 sysfatal("threadSleep: rendezvous failed: %r");
464 threadWakeup(Thread *t)
466 if(rendezvous(t, (void*)0x44391f14) != (void*)0x22bbdfd6)
467 sysfatal("threadWakeup: rendezvous failed: %r");