hard-to-find locking bug

This commit is contained in:
rsc 2005-02-15 18:08:28 +00:00
parent ee4cffff9a
commit 80b8842f3e

View file

@ -417,6 +417,8 @@ threadqlock(QLock *l, int block, ulong pc)
static void static void
threadqunlock(QLock *l, ulong pc) threadqunlock(QLock *l, ulong pc)
{ {
_Thread *ready;
lock(&l->l); lock(&l->l);
//print("qlock unlock %p @%#x by %p (owner %p)\n", l, pc, (*threadnow)(), l->owner); //print("qlock unlock %p @%#x by %p (owner %p)\n", l, pc, (*threadnow)(), l->owner);
if(l->owner == 0){ if(l->owner == 0){
@ -424,11 +426,18 @@ threadqunlock(QLock *l, ulong pc)
argv0, pc, l->owner, (*threadnow)()); argv0, pc, l->owner, (*threadnow)());
abort(); abort();
} }
if((l->owner = l->waiting.head) != nil){ if((l->owner = ready = l->waiting.head) != nil)
delthread(&l->waiting, l->owner); delthread(&l->waiting, l->owner);
_threadready(l->owner); /*
} * N.B. Cannot call _threadready() before unlocking l->l,
* because the thread we are readying might:
* - be in another proc
* - start running immediately
* - and free l before we get a chance to run again
*/
unlock(&l->l); unlock(&l->l);
if(ready)
_threadready(l->owner);
} }
static int static int
@ -479,14 +488,17 @@ threadrunlock(RWLock *l, ulong pc)
_Thread *t; _Thread *t;
USED(pc); USED(pc);
t = nil;
lock(&l->l); lock(&l->l);
--l->readers; --l->readers;
if(l->readers == 0 && (t = l->wwaiting.head) != nil){ if(l->readers == 0 && (t = l->wwaiting.head) != nil){
delthread(&l->wwaiting, t); delthread(&l->wwaiting, t);
l->writer = t; l->writer = t;
_threadready(t);
} }
unlock(&l->l); unlock(&l->l);
if(t)
_threadready(t);
} }
static void static void
@ -503,12 +515,14 @@ threadwunlock(RWLock *l, ulong pc)
l->readers++; l->readers++;
_threadready(t); _threadready(t);
} }
t = nil;
if(l->readers == 0 && (t = l->wwaiting.head) != nil){ if(l->readers == 0 && (t = l->wwaiting.head) != nil){
delthread(&l->wwaiting, t); delthread(&l->wwaiting, t);
l->writer = t; l->writer = t;
_threadready(t);
} }
unlock(&l->l); unlock(&l->l);
if(t)
_threadready(t);
} }
/* /*