aboutsummaryrefslogtreecommitdiff
path: root/src/lib9
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib9')
-rw-r--r--src/lib9/ffork-Linux.c4
-rw-r--r--src/lib9/lock.c70
-rw-r--r--src/lib9/qlock.c87
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);
+}
+