1
0
mirror of https://github.com/golang/go synced 2024-09-25 01:10:13 -06:00

various race conditions.

R=r
DELTA=43  (29 added, 5 deleted, 9 changed)
OCL=23608
CL=23611
This commit is contained in:
Russ Cox 2009-01-27 14:01:20 -08:00
parent 47ab1c1e99
commit 53e69e1db5
3 changed files with 38 additions and 14 deletions

View File

@ -397,7 +397,7 @@ nextgandunlock(void)
throw("all goroutines are asleep - deadlock!"); throw("all goroutines are asleep - deadlock!");
m->nextg = nil; m->nextg = nil;
noteclear(&m->havenextg); noteclear(&m->havenextg);
if(sched.waitstop) { if(sched.waitstop && sched.mcpu <= sched.mcpumax) {
sched.waitstop = 0; sched.waitstop = 0;
notewakeup(&sched.stopped); notewakeup(&sched.stopped);
} }
@ -590,6 +590,10 @@ sys·entersyscall(uint64 callerpc, int64 trap)
sched.msyscall++; sched.msyscall++;
if(sched.gwait != 0) if(sched.gwait != 0)
matchmg(); matchmg();
if(sched.waitstop && sched.mcpu <= sched.mcpumax) {
sched.waitstop = 0;
notewakeup(&sched.stopped);
}
unlock(&sched); unlock(&sched);
// leave SP around for gc; poison PC to make sure it's not used // leave SP around for gc; poison PC to make sure it's not used
g->sched.SP = (byte*)&callerpc; g->sched.SP = (byte*)&callerpc;

View File

@ -277,19 +277,25 @@ xadd(uint32 volatile *val, int32 delta)
void void
lock(Lock *l) lock(Lock *l)
{ {
if(m->locks < 0)
throw("lock count");
m->locks++;
// Allocate semaphore if needed. // Allocate semaphore if needed.
if(l->sema == 0) if(l->sema == 0)
initsema(&l->sema); initsema(&l->sema);
if(xadd(&l->key, 1) > 1) // someone else has it; wait if(xadd(&l->key, 1) > 1) // someone else has it; wait
mach_semacquire(l->sema); mach_semacquire(l->sema);
m->locks++;
} }
void void
unlock(Lock *l) unlock(Lock *l)
{ {
m->locks--; m->locks--;
if(m->locks < 0)
throw("lock count");
if(xadd(&l->key, -1) > 0) // someone else is waiting if(xadd(&l->key, -1) > 0) // someone else is waiting
mach_semrelease(l->sema); mach_semrelease(l->sema);
} }

View File

@ -301,13 +301,11 @@ futexwakeup(uint32 *addr)
// else return 0; // else return 0;
// but atomically. // but atomically.
void static void
lock(Lock *l) futexlock(Lock *l)
{ {
uint32 v; uint32 v;
m->locks++;
again: again:
v = l->key; v = l->key;
if((v&1) == 0){ if((v&1) == 0){
@ -346,13 +344,11 @@ again:
goto again; goto again;
} }
void static void
unlock(Lock *l) futexunlock(Lock *l)
{ {
uint32 v; uint32 v;
m->locks--;
// Atomically get value and clear lock bit. // Atomically get value and clear lock bit.
again: again:
v = l->key; v = l->key;
@ -366,6 +362,24 @@ again:
futexwakeup(&l->key); futexwakeup(&l->key);
} }
void
lock(Lock *l)
{
if(m->locks < 0)
throw("lock count");
m->locks++;
futexlock(l);
}
void
unlock(Lock *l)
{
m->locks--;
if(m->locks < 0)
throw("lock count");
futexunlock(l);
}
// One-time notifications. // One-time notifications.
// //
@ -383,20 +397,20 @@ void
noteclear(Note *n) noteclear(Note *n)
{ {
n->lock.key = 0; // memset(n, 0, sizeof *n) n->lock.key = 0; // memset(n, 0, sizeof *n)
lock(&n->lock); futexlock(&n->lock);
} }
void void
notewakeup(Note *n) notewakeup(Note *n)
{ {
unlock(&n->lock); futexunlock(&n->lock);
} }
void void
notesleep(Note *n) notesleep(Note *n)
{ {
lock(&n->lock); futexlock(&n->lock);
unlock(&n->lock); // Let other sleepers find out too. futexunlock(&n->lock); // Let other sleepers find out too.
} }