aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/qlock.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-12-26 21:51:15 +0000
committerrsc <devnull@localhost>2004-12-26 21:51:15 +0000
commit5f8fa94796903bf81db4f1dc76d433a80308b3d4 (patch)
treebc94c36965c4bf6cdb420c4c5fe628024647f88e /src/lib9/qlock.c
parentb2ff5382580e13d82ca48966c9d79d3318865cba (diff)
downloadplan9port-5f8fa94796903bf81db4f1dc76d433a80308b3d4.tar.gz
plan9port-5f8fa94796903bf81db4f1dc76d433a80308b3d4.tar.bz2
plan9port-5f8fa94796903bf81db4f1dc76d433a80308b3d4.zip
cleanups - lots of removed files now in thread library.
qlock.c - stubs to thread library notify.c - clean interface slightly.
Diffstat (limited to 'src/lib9/qlock.c')
-rw-r--r--src/lib9/qlock.c408
1 files changed, 98 insertions, 310 deletions
diff --git a/src/lib9/qlock.c b/src/lib9/qlock.c
index 0eacccd7..a979c443 100644
--- a/src/lib9/qlock.c
+++ b/src/lib9/qlock.c
@@ -1,379 +1,167 @@
-#include <lib9.h>
+#include <u.h>
+#include <libc.h>
+
+/*
+ * The function pointers are supplied by the thread
+ * library during its initialization. If there is no thread
+ * library, there is no multithreading.
+ */
+
+int (*_lock)(Lock*, int, ulong);
+void (*_unlock)(Lock*, ulong);
+int (*_qlock)(QLock*, int, ulong); /* do not use */
+void (*_qunlock)(QLock*, ulong);
+void (*_rsleep)(Rendez*, ulong); /* do not use */
+int (*_rwakeup)(Rendez*, int, ulong);
+int (*_rlock)(RWLock*, int, ulong); /* do not use */
+int (*_wlock)(RWLock*, int, ulong);
+void (*_runlock)(RWLock*, ulong);
+void (*_wunlock)(RWLock*, ulong);
-static struct {
- QLp *p;
- QLp x[1024];
-} ql = {
- ql.x
-};
-
-enum
-{
- Queuing,
- QueuingR,
- QueuingW,
- Sleeping,
- Waking,
-};
-
-static void (*procsleep)(_Procrend*) = _procsleep;
-static void (*procwakeup)(_Procrend*) = _procwakeup;
-#define _procsleep donotcall_procsleep
-#define _procwakeup donotcall_procwakeup
-
-/* this gets called by the thread library ONLY to get us to use its rendezvous */
void
-_qlockinit(void (*sleep)(_Procrend*), void (*wakeup)(_Procrend*))
+lock(Lock *l)
{
- procsleep = sleep;
- procwakeup = wakeup;
+ if(_lock)
+ (*_lock)(l, 1, getcallerpc(&l));
+ else
+ l->held = 1;
}
-/* find a free shared memory location to queue ourselves in */
-static QLp*
-getqlp(void)
+int
+canlock(Lock *l)
{
- QLp *p, *op;
-
- op = ql.p;
- for(p = op+1; ; p++){
- if(p == &ql.x[nelem(ql.x)])
- p = ql.x;
- if(p == op){
- fprint(2, "qlock: out of qlp\n");
- abort();
- }
- if(canlock(&p->inuse)){
- ql.p = p;
- p->next = nil;
- break;
- }
+ if(_lock)
+ return (*_lock)(l, 0, getcallerpc(&l));
+ else{
+ if(l->held)
+ return 0;
+ l->held = 1;
+ return 1;
}
- return p;
}
void
-qlock(QLock *q)
+unlock(Lock *l)
{
- QLp *p, *mp;
-
- lock(&q->lock);
- if(!q->locked){
- q->locked = 1;
- unlock(&q->lock);
- return;
- }
-
-
- /* chain into waiting list */
- mp = getqlp();
- p = q->tail;
- if(p == nil)
- q->head = mp;
+ if(_unlock)
+ (*_unlock)(l, getcallerpc(&l));
else
- p->next = mp;
- q->tail = mp;
- mp->state = Queuing;
- mp->rend.l = &q->lock;
- procsleep(&mp->rend);
- unlock(&q->lock);
- assert(mp->state == Waking);
- unlock(&mp->inuse);
+ l->held = 0;
}
void
-qunlock(QLock *q)
+qlock(QLock *l)
{
- QLp *p;
-
- lock(&q->lock);
- p = q->head;
- if(p != nil){
- /* wakeup head waiting process */
- q->head = p->next;
- if(q->head == nil)
- q->tail = nil;
- p->state = Waking;
- procwakeup(&p->rend);
- unlock(&q->lock);
- return;
- }
- q->locked = 0;
- unlock(&q->lock);
+ if(_qlock)
+ (*_qlock)(l, 1, getcallerpc(&l));
+ else
+ l->l.held = 1;
}
int
-canqlock(QLock *q)
+canqlock(QLock *l)
{
- if(!canlock(&q->lock))
- return 0;
- if(!q->locked){
- q->locked = 1;
- unlock(&q->lock);
+ if(_qlock)
+ return (*_qlock)(l, 0, getcallerpc(&l));
+ else{
+ if(l->l.held)
+ return 0;
+ l->l.held = 1;
return 1;
}
- unlock(&q->lock);
- return 0;
}
void
-rlock(RWLock *q)
+qunlock(QLock *l)
{
- QLp *p, *mp;
-
- lock(&q->lock);
- if(q->writer == 0 && q->head == nil){
- /* no writer, go for it */
- q->readers++;
- unlock(&q->lock);
- return;
- }
+ if(_qunlock)
+ (*_qunlock)(l, getcallerpc(&l));
+ else
+ l->l.held = 0;
+}
- mp = getqlp();
- p = q->tail;
- if(p == 0)
- q->head = mp;
+void
+rlock(RWLock *l)
+{
+ if(_rlock)
+ (*_rlock)(l, 1, getcallerpc(&l));
else
- p->next = mp;
- q->tail = mp;
- mp->next = nil;
- mp->state = QueuingR;
- mp->rend.l = &q->lock;
- procsleep(&mp->rend);
- unlock(&q->lock);
- assert(mp->state == Waking);
- unlock(&mp->inuse);
+ l->readers++;
}
int
-canrlock(RWLock *q)
+canrlock(RWLock *l)
{
- lock(&q->lock);
- if (q->writer == 0 && q->head == nil) {
- /* no writer; go for it */
- q->readers++;
- unlock(&q->lock);
+ if(_rlock)
+ return (*_rlock)(l, 0, getcallerpc(&l));
+ else{
+ if(l->writer)
+ return 0;
+ l->readers++;
return 1;
}
- unlock(&q->lock);
- return 0;
+ return 1;
}
void
-runlock(RWLock *q)
+runlock(RWLock *l)
{
- QLp *p;
-
- lock(&q->lock);
- if(q->readers <= 0)
- abort();
- p = q->head;
- if(--(q->readers) > 0 || p == nil){
- unlock(&q->lock);
- return;
- }
-
- /* start waiting writer */
- if(p->state != QueuingW)
- abort();
- q->head = p->next;
- if(q->head == 0)
- q->tail = 0;
- q->writer = 1;
-
- /* wakeup waiter */
- p->state = Waking;
- procwakeup(&p->rend);
- unlock(&q->lock);
+ if(_runlock)
+ (*_runlock)(l, getcallerpc(&l));
+ else
+ l->readers--;
}
void
-wlock(RWLock *q)
+wlock(RWLock *l)
{
- QLp *p, *mp;
-
- lock(&q->lock);
- if(q->readers == 0 && q->writer == 0){
- /* noone waiting, go for it */
- q->writer = 1;
- unlock(&q->lock);
- return;
- }
-
- /* wait */
- p = q->tail;
- mp = getqlp();
- if(p == nil)
- q->head = mp;
+ if(_wlock)
+ (*_wlock)(l, 1, getcallerpc(&l));
else
- p->next = mp;
- q->tail = mp;
- mp->next = nil;
- mp->state = QueuingW;
-
- /* wait in kernel */
- mp->rend.l = &q->lock;
- procsleep(&mp->rend);
- unlock(&q->lock);
- assert(mp->state == Waking);
- unlock(&mp->inuse);
+ l->writer = (void*)1;
}
int
-canwlock(RWLock *q)
+canwlock(RWLock *l)
{
- lock(&q->lock);
- if (q->readers == 0 && q->writer == 0) {
- /* no one waiting; go for it */
- q->writer = 1;
- unlock(&q->lock);
+ if(_wlock)
+ return (*_wlock)(l, 0, getcallerpc(&l));
+ else{
+ if(l->writer || l->readers)
+ return 0;
+ l->writer = (void*)1;
return 1;
}
- unlock(&q->lock);
- return 0;
}
void
-wunlock(RWLock *q)
+wunlock(RWLock *l)
{
- QLp *p;
-
- lock(&q->lock);
- if(q->writer == 0){
- fprint(2, "wunlock: not holding lock\n");
- abort();
- }
- p = q->head;
- if(p == nil){
- q->writer = 0;
- unlock(&q->lock);
- return;
- }
- if(p->state == QueuingW){
- /* start waiting writer */
- q->head = p->next;
- if(q->head == nil)
- q->tail = nil;
- p->state = Waking;
- procwakeup(&p->rend);
- unlock(&q->lock);
- return;
- }
-
- if(p->state != QueuingR){
- fprint(2, "wunlock: bad state\n");
- abort();
- }
-
- /* wake waiting readers */
- while(q->head != nil && q->head->state == QueuingR){
- p = q->head;
- q->head = p->next;
- q->readers++;
- p->state = Waking;
- procwakeup(&p->rend);
- }
- if(q->head == nil)
- q->tail = nil;
- q->writer = 0;
- unlock(&q->lock);
+ if(_wunlock)
+ (*_wunlock)(l, getcallerpc(&l));
+ else
+ l->writer = nil;
}
void
rsleep(Rendez *r)
{
- QLp *t, *me;
-
- if(!r->l){
- fprint(2, "rsleep: no lock\n");
- abort();
- }
- lock(&r->l->lock);
- /* we should hold the qlock */
- if(!r->l->locked){
- fprint(2, "rsleep: not locked\n");
- abort();
- }
-
- /* add ourselves to the wait list */
- me = getqlp();
- me->state = Sleeping;
- if(r->head == nil)
- r->head = me;
- else
- r->tail->next = me;
- me->next = nil;
- r->tail = me;
-
- /* pass the qlock to the next guy */
- t = r->l->head;
- if(t){
- r->l->head = t->next;
- if(r->l->head == nil)
- r->l->tail = nil;
- t->state = Waking;
- procwakeup(&t->rend);
- }else
- r->l->locked = 0;
-
- /* wait for a wakeup */
- me->rend.l = &r->l->lock;
- procsleep(&me->rend);
- assert(me->state == Waking);
- unlock(&me->inuse);
- if(!r->l->locked){
- fprint(2, "rsleep: not locked after wakeup\n");
- abort();
- }
- unlock(&r->l->lock);
+ if(_rsleep)
+ (*_rsleep)(r, getcallerpc(&r));
}
int
rwakeup(Rendez *r)
{
- QLp *t;
-
- /*
- * take off wait and put on front of queue
- * put on front so guys that have been waiting will not get starved
- */
-
- if(!r->l){
- fprint(2, "rwakeup: no lock\n");
- abort();
- }
- lock(&r->l->lock);
- if(!r->l->locked){
- fprint(2, "rwakeup: not locked\n");
- abort();
- }
-
- t = r->head;
- if(t == nil){
- unlock(&r->l->lock);
- return 0;
- }
-
- r->head = t->next;
- if(r->head == nil)
- r->tail = nil;
-
- t->next = r->l->head;
- r->l->head = t;
- if(r->l->tail == nil)
- r->l->tail = t;
-
- t->state = Queuing;
- unlock(&r->l->lock);
- return 1;
+ if(_rwakeup)
+ return (*_rwakeup)(r, 0, getcallerpc(&r));
+ return 0;
}
int
rwakeupall(Rendez *r)
{
- int i;
-
- for(i=0; rwakeup(r); i++)
- ;
- return i;
+ if(_rwakeup)
+ return (*_rwakeup)(r, 1, getcallerpc(&r));
+ return 0;
}