commit - ee4cffff9a1068d9c9bab99788d27fd235ade2dc
commit + 80b8842f3e4d562e67455de1c1de80cba5532aec
blob - 57ffa1cb049651a5879911a7ab2c95793275b897
blob + eb8370b34808a5da6506b4a2cd51553f3450e3e6
--- src/libthread/thread.c
+++ src/libthread/thread.c
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){
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
_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
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);
}
/*