summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-01-27 14:01:20 -0800
committerRuss Cox <rsc@golang.org>2009-01-27 14:01:20 -0800
commit8419d90c6d6649d95bdfb7262dfd1eec22cd9dc0 (patch)
treeeed590ded955f1f25cb25203b5ca94ece0716b75 /src
parenta744ae8e7dccc7a4d0830d2a3204a222baa67cba (diff)
downloadgolang-8419d90c6d6649d95bdfb7262dfd1eec22cd9dc0.tar.gz
various race conditions.
R=r DELTA=43 (29 added, 5 deleted, 9 changed) OCL=23608 CL=23611
Diffstat (limited to 'src')
-rw-r--r--src/runtime/proc.c6
-rw-r--r--src/runtime/rt1_amd64_darwin.c8
-rw-r--r--src/runtime/rt1_amd64_linux.c38
3 files changed, 38 insertions, 14 deletions
diff --git a/src/runtime/proc.c b/src/runtime/proc.c
index 3fe08df94..0b509bb87 100644
--- a/src/runtime/proc.c
+++ b/src/runtime/proc.c
@@ -397,7 +397,7 @@ nextgandunlock(void)
throw("all goroutines are asleep - deadlock!");
m->nextg = nil;
noteclear(&m->havenextg);
- if(sched.waitstop) {
+ if(sched.waitstop && sched.mcpu <= sched.mcpumax) {
sched.waitstop = 0;
notewakeup(&sched.stopped);
}
@@ -590,6 +590,10 @@ sys·entersyscall(uint64 callerpc, int64 trap)
sched.msyscall++;
if(sched.gwait != 0)
matchmg();
+ if(sched.waitstop && sched.mcpu <= sched.mcpumax) {
+ sched.waitstop = 0;
+ notewakeup(&sched.stopped);
+ }
unlock(&sched);
// leave SP around for gc; poison PC to make sure it's not used
g->sched.SP = (byte*)&callerpc;
diff --git a/src/runtime/rt1_amd64_darwin.c b/src/runtime/rt1_amd64_darwin.c
index b61475672..c476f89b5 100644
--- a/src/runtime/rt1_amd64_darwin.c
+++ b/src/runtime/rt1_amd64_darwin.c
@@ -277,19 +277,25 @@ xadd(uint32 volatile *val, int32 delta)
void
lock(Lock *l)
{
+ if(m->locks < 0)
+ throw("lock count");
+ m->locks++;
+
// Allocate semaphore if needed.
if(l->sema == 0)
initsema(&l->sema);
if(xadd(&l->key, 1) > 1) // someone else has it; wait
mach_semacquire(l->sema);
- m->locks++;
}
void
unlock(Lock *l)
{
m->locks--;
+ if(m->locks < 0)
+ throw("lock count");
+
if(xadd(&l->key, -1) > 0) // someone else is waiting
mach_semrelease(l->sema);
}
diff --git a/src/runtime/rt1_amd64_linux.c b/src/runtime/rt1_amd64_linux.c
index c0c203805..5b3e45809 100644
--- a/src/runtime/rt1_amd64_linux.c
+++ b/src/runtime/rt1_amd64_linux.c
@@ -301,13 +301,11 @@ futexwakeup(uint32 *addr)
// else return 0;
// but atomically.
-void
-lock(Lock *l)
+static void
+futexlock(Lock *l)
{
uint32 v;
- m->locks++;
-
again:
v = l->key;
if((v&1) == 0){
@@ -346,13 +344,11 @@ again:
goto again;
}
-void
-unlock(Lock *l)
+static void
+futexunlock(Lock *l)
{
uint32 v;
- m->locks--;
-
// Atomically get value and clear lock bit.
again:
v = l->key;
@@ -366,6 +362,24 @@ again:
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.
//
@@ -383,20 +397,20 @@ void
noteclear(Note *n)
{
n->lock.key = 0; // memset(n, 0, sizeof *n)
- lock(&n->lock);
+ futexlock(&n->lock);
}
void
notewakeup(Note *n)
{
- unlock(&n->lock);
+ futexunlock(&n->lock);
}
void
notesleep(Note *n)
{
- lock(&n->lock);
- unlock(&n->lock); // Let other sleepers find out too.
+ futexlock(&n->lock);
+ futexunlock(&n->lock); // Let other sleepers find out too.
}