hard-to-find locking bug
This commit is contained in:
parent
ee4cffff9a
commit
80b8842f3e
1 changed files with 19 additions and 5 deletions
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue