Permalink
Browse files

hard-to-find locking bug

  • Loading branch information...
rsc
rsc committed Feb 15, 2005
1 parent ee4cfff commit 80b8842f3e4d562e67455de1c1de80cba5532aec
Showing with 19 additions and 5 deletions.
  1. +19 −5 src/libthread/thread.c
@@ -417,18 +417,27 @@ threadqlock(QLock *l, int block, ulong pc)
static void
threadqunlock(QLock *l, ulong pc)
{
_Thread *ready;

lock(&l->l);
//print("qlock unlock %p @%#x by %p (owner %p)\n", l, pc, (*threadnow)(), l->owner);
if(l->owner == 0){
fprint(2, "%s: qunlock pc=0x%lux owner=%p self=%p oops\n",
argv0, pc, l->owner, (*threadnow)());
abort();
}
if((l->owner = l->waiting.head) != nil){
if((l->owner = ready = l->waiting.head) != nil)
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);
if(ready)
_threadready(l->owner);
}

static int
@@ -479,14 +488,17 @@ threadrunlock(RWLock *l, ulong pc)
_Thread *t;

USED(pc);
t = nil;
lock(&l->l);
--l->readers;
if(l->readers == 0 && (t = l->wwaiting.head) != nil){
delthread(&l->wwaiting, t);
l->writer = t;
_threadready(t);
}
unlock(&l->l);
if(t)
_threadready(t);

}

static void
@@ -503,12 +515,14 @@ threadwunlock(RWLock *l, ulong pc)
l->readers++;
_threadready(t);
}
t = nil;
if(l->readers == 0 && (t = l->wwaiting.head) != nil){
delthread(&l->wwaiting, t);
l->writer = t;
_threadready(t);
}
unlock(&l->l);
if(t)
_threadready(t);
}

/*

0 comments on commit 80b8842

Please sign in to comment.