diff options
Diffstat (limited to 'src/lib9/rendez-pthread.c')
-rw-r--r-- | src/lib9/rendez-pthread.c | 173 |
1 files changed, 13 insertions, 160 deletions
diff --git a/src/lib9/rendez-pthread.c b/src/lib9/rendez-pthread.c index fe930cef..2d08e0c3 100644 --- a/src/lib9/rendez-pthread.c +++ b/src/lib9/rendez-pthread.c @@ -1,170 +1,23 @@ -/* - NAME - rendezvous - user level process synchronization - - SYNOPSIS - ulong rendezvous(ulong tag, ulong value) - - DESCRIPTION - The rendezvous system call allows two processes to synchro- - nize and exchange a value. In conjunction with the shared - memory system calls (see segattach(2) and fork(2)), it - enables parallel programs to control their scheduling. - - Two processes wishing to synchronize call rendezvous with a - common tag, typically an address in memory they share. One - process will arrive at the rendezvous first; it suspends - execution until a second arrives. When a second process - meets the rendezvous the value arguments are exchanged - between the processes and returned as the result of the - respective rendezvous system calls. Both processes are - awakened when the rendezvous succeeds. - - The set of tag values which two processes may use to - rendezvous-their tag space-is inherited when a process - forks, unless RFREND is set in the argument to rfork; see - fork(2). - - If a rendezvous is interrupted the return value is ~0, so - that value should not be used in normal communication. - - * This assumes we're using pthreads and simulates rendezvous using - * shared memory and mutexes. - */ - #include <u.h> #include <pthread.h> -#include <signal.h> #include <libc.h> -enum +void +_procsleep(_Procrend *rend) { - VOUSHASH = 257, -}; - -typedef struct Vous Vous; -struct Vous -{ - Vous *link; - Lock lk; - ulong val; - ulong tag; - pthread_mutex_t mutex; -}; - -static void -ign(int x) -{ - USED(x); +//print("sleep %p %d\n", rend, getpid()); + pthread_cond_init(&rend->cond, 0); + rend->asleep = 1; + while(rend->asleep) + pthread_cond_wait(&rend->cond, &rend->l->mutex); + pthread_cond_destroy(&rend->cond); } -void /*__attribute__((constructor))*/ -ignusr1(void) +void +_procwakeup(_Procrend *rend) { - signal(SIGUSR1, ign); -} - -static Vous vouspool[2048]; -static int nvousused; -static Vous *vousfree; -static Vous *voushash[VOUSHASH]; -static Lock vouslock; - -static Vous* -getvous(void) -{ - Vous *v; - - if(vousfree){ - v = vousfree; - vousfree = v->link; - }else if(nvousused < nelem(vouspool)){ - v = &vouspool[nvousused++]; - pthread_mutex_init(&v->mutex, NULL); - }else - abort(); - return v; -} - -static void -putvous(Vous *v) -{ - lock(&vouslock); - v->link = vousfree; - vousfree = v; - unlock(&vouslock); -} - -static Vous* -findvous(ulong tag, ulong val, int *found) -{ - int h; - Vous *v, **l; - - lock(&vouslock); - h = tag%VOUSHASH; - for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){ - if(v->tag == tag){ - *l = v->link; - *found = 1; - unlock(&vouslock); - return v; - } - } - v = getvous(); - v->link = voushash[h]; - v->val = val; - v->tag = tag; - lock(&v->lk); - voushash[h] = v; - unlock(&vouslock); - *found = 0; - return v; -} - -#define DBG 0 -ulong -rendezvous(ulong tag, ulong val) -{ - int found; - ulong rval; - Vous *v; - - v = findvous(tag, val, &found); - if(!found){ - if(DBG)fprint(2, "tag %lux, sleeping on %p\n", tag, v); - /* - * No rendezvous partner was found; the next guy - * through will find v and wake us, so we must go - * to sleep. Do this by locking the mutex (it is - * unlocked) and then locking it again (our waker will - * unlock it for us). - */ - if(pthread_mutex_lock(&v->mutex) != 0) - abort(); - unlock(&v->lk); - if(pthread_mutex_lock(&v->mutex) != 0) - abort(); - rval = v->val; - pthread_mutex_unlock(&v->mutex); - if(DBG)fprint(2, " awake on %p\n", v); - unlock(&v->lk); - putvous(v); - }else{ - /* - * Found someone to meet. Wake him: - * - * A. lock v->lk (waits for him to lock the mutex once. - * B. unlock the mutex (wakes him up) - */ - if(DBG)fprint(2, "found tag %lux on %p, waking\n", tag, v); - lock(&v->lk); - rval = v->val; - v->val = val; - if(pthread_mutex_unlock(&v->mutex) != 0) - abort(); - /* lock passes to him */ - } - return rval; +//print("wakeup %p\n", rend); + rend->asleep = 0; + pthread_cond_signal(&rend->cond); } |