diff options
author | rsc <devnull@localhost> | 2004-09-17 00:38:29 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-09-17 00:38:29 +0000 |
commit | 06bb4ed20d855b60e39c1125d8d715ba8892265b (patch) | |
tree | 8294b537f5b81809671985903e31c4835c41cd04 /src/lib9 | |
parent | 984e353160593b20d1e2944e1f2e9ce2117c8490 (diff) | |
download | plan9port-06bb4ed20d855b60e39c1125d8d715ba8892265b.tar.gz plan9port-06bb4ed20d855b60e39c1125d8d715ba8892265b.tar.bz2 plan9port-06bb4ed20d855b60e39c1125d8d715ba8892265b.zip |
Rewrite to remove dependence on rendezvous and its bizarre
data structures. Makes it easier to use pthreads too.
Still need to add code for non-pthreads systems.
Just a checkpoint to switch work to another machine.
Diffstat (limited to 'src/lib9')
-rw-r--r-- | src/lib9/ffork-Linux.c | 4 | ||||
-rw-r--r-- | src/lib9/lock.c | 70 | ||||
-rw-r--r-- | src/lib9/qlock.c | 87 |
3 files changed, 89 insertions, 72 deletions
diff --git a/src/lib9/ffork-Linux.c b/src/lib9/ffork-Linux.c index f4704c60..4f976359 100644 --- a/src/lib9/ffork-Linux.c +++ b/src/lib9/ffork-Linux.c @@ -1,3 +1,6 @@ +#include "ffork-pthread.c" + +#ifdef OLD /* * Is nothing simple? * @@ -191,3 +194,4 @@ getfforkid(void) return getpid(); } +#endif diff --git a/src/lib9/lock.c b/src/lib9/lock.c index 80f65b33..eb3ea21d 100644 --- a/src/lib9/lock.c +++ b/src/lib9/lock.c @@ -2,52 +2,54 @@ #include <unistd.h> #include <sys/time.h> #include <sched.h> +#include <errno.h> #include <libc.h> -int _ntas; -static int -_xtas(void *v) +static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER; + +static void +lockinit(Lock *lk) { - int x; + pthread_mutexattr_t attr; - _ntas++; - x = _tas(v); - return x; + pthread_mutex_lock(&initmutex); + if(lk->init == 0){ + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutex_init(&lk->mutex, &attr); + pthread_mutexattr_destroy(&attr); + lk->init = 1; + } + pthread_mutex_unlock(&initmutex); } -int -canlock(Lock *l) +void +lock(Lock *lk) { - return !_xtas(&l->val); + if(!lk->init) + lockinit(lk); + if(pthread_mutex_lock(&lk->mutex) != 0) + abort(); } -void -unlock(Lock *l) +int +canlock(Lock *lk) { - l->val = 0; + int r; + + if(!lk->init) + lockinit(lk); + r = pthread_mutex_trylock(&lk->mutex); + if(r == 0) + return 1; + if(r == EBUSY) + return 0; + abort(); } void -lock(Lock *lk) +unlock(Lock *lk) { - int i; - - /* once fast */ - if(!_xtas(&lk->val)) - return; - /* a thousand times pretty fast */ - for(i=0; i<1000; i++){ - if(!_xtas(&lk->val)) - return; - sched_yield(); - } - /* now nice and slow */ - for(i=0; i<1000; i++){ - if(!_xtas(&lk->val)) - return; - usleep(100*1000); - } - /* take your time */ - while(_xtas(&lk->val)) - usleep(1000*1000); + if(pthread_mutex_unlock(&lk->mutex) != 0) + abort(); } diff --git a/src/lib9/qlock.c b/src/lib9/qlock.c index d83a4b7f..798b08f3 100644 --- a/src/lib9/qlock.c +++ b/src/lib9/qlock.c @@ -16,13 +16,15 @@ enum Waking, }; -static ulong (*_rendezvousp)(ulong, ulong) = rendezvous; +static void (*procsleep)(_Procrend*) = _procsleep; +static void (*procwakeup)(_Procrend*) = _procwakeup; /* this gets called by the thread library ONLY to get us to use its rendezvous */ void -_qlockinit(ulong (*r)(ulong, ulong)) +_qlockinit(void (*sleep)(_Procrend*), void (*wakeup)(_Procrend*)) { - _rendezvousp = r; + procsleep = sleep; + procwakeup = wakeup; } /* find a free shared memory location to queue ourselves in */ @@ -39,7 +41,7 @@ getqlp(void) fprint(2, "qlock: out of qlp\n"); abort(); } - if(_tas(&(p->inuse)) == 0){ + if(canlock(&p->inuse)){ ql.p = p; p->next = nil; break; @@ -70,13 +72,11 @@ qlock(QLock *q) p->next = mp; q->tail = mp; mp->state = Queuing; + mp->rend.l = &q->lock; + _procsleep(&mp->rend); unlock(&q->lock); - - /* wait */ - while((*_rendezvousp)((ulong)mp, 1) == ~0) - ; assert(mp->state == Waking); - mp->inuse = 0; + unlock(&mp->inuse); } void @@ -91,10 +91,9 @@ qunlock(QLock *q) q->head = p->next; if(q->head == nil) q->tail = nil; - unlock(&q->lock); p->state = Waking; - while((*_rendezvousp)((ulong)p, 0x12345) == ~0) - ; + _procwakeup(&p->rend); + unlock(&q->lock); return; } q->locked = 0; @@ -137,13 +136,11 @@ rlock(RWLock *q) q->tail = mp; mp->next = nil; mp->state = QueuingR; + mp->rend.l = &q->lock; + _procsleep(&mp->rend); unlock(&q->lock); - - /* wait in kernel */ - while((*_rendezvousp)((ulong)mp, 1) == ~0) - ; assert(mp->state == Waking); - mp->inuse = 0; + unlock(&mp->inuse); } int @@ -181,12 +178,11 @@ runlock(RWLock *q) if(q->head == 0) q->tail = 0; q->writer = 1; - unlock(&q->lock); /* wakeup waiter */ p->state = Waking; - while((*_rendezvousp)((ulong)p, 0) == ~0) - ; + _procwakeup(&p->rend); + unlock(&q->lock); } void @@ -212,13 +208,13 @@ wlock(RWLock *q) q->tail = mp; mp->next = nil; mp->state = QueuingW; - unlock(&q->lock); /* wait in kernel */ - while((*_rendezvousp)((ulong)mp, 1) == ~0) - ; + mp->rend.l = &q->lock; + _procsleep(&mp->rend); + unlock(&q->lock); assert(mp->state == Waking); - mp->inuse = 0; + unlock(&mp->inuse); } int @@ -256,10 +252,9 @@ wunlock(RWLock *q) q->head = p->next; if(q->head == nil) q->tail = nil; - unlock(&q->lock); p->state = Waking; - while((*_rendezvousp)((ulong)p, 0) == ~0) - ; + _procwakeup(&p->rend); + unlock(&q->lock); return; } @@ -274,8 +269,7 @@ wunlock(RWLock *q) q->head = p->next; q->readers++; p->state = Waking; - while((*_rendezvousp)((ulong)p, 0) == ~0) - ; + _procwakeup(&p->rend); } if(q->head == nil) q->tail = nil; @@ -315,20 +309,17 @@ rsleep(Rendez *r) r->l->head = t->next; if(r->l->head == nil) r->l->tail = nil; - unlock(&r->l->lock); t->state = Waking; - while((*_rendezvousp)((ulong)t, 0x12345) == ~0) - ; - }else{ + _procwakeup(&t->rend); + }else r->l->locked = 0; - unlock(&r->l->lock); - } /* wait for a wakeup */ - while((*_rendezvousp)((ulong)me, 0x23456) == ~0) - ; + me->rend.l = &r->l->lock; + _procsleep(&me->rend); + assert(me->state == Waking); - me->inuse = 0; + unlock(&me->inuse); if(!r->l->locked){ fprint(2, "rsleep: not locked after wakeup\n"); abort(); @@ -384,3 +375,23 @@ rwakeupall(Rendez *r) ; return i; } + +void +_procsleep(_Procrend *rend) +{ +//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 +_procwakeup(_Procrend *rend) +{ +//print("wakeup %p\n", rend); + rend->asleep = 0; + pthread_cond_signal(&rend->cond); +} + |