summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/lock_futex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/lock_futex.c')
-rw-r--r--src/pkg/runtime/lock_futex.c74
1 files changed, 55 insertions, 19 deletions
diff --git a/src/pkg/runtime/lock_futex.c b/src/pkg/runtime/lock_futex.c
index 3c2ef4ede..e6e9be923 100644
--- a/src/pkg/runtime/lock_futex.c
+++ b/src/pkg/runtime/lock_futex.c
@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build freebsd linux
+// +build dragonfly freebsd linux
#include "runtime.h"
+#include "stack.h"
+#include "../../cmd/ld/textflag.h"
// This implementation depends on OS-specific implementations of
//
@@ -91,14 +93,16 @@ runtime·unlock(Lock *l)
{
uint32 v;
- if(--m->locks < 0)
- runtime·throw("runtime·unlock: lock count");
-
v = runtime·xchg((uint32*)&l->key, MUTEX_UNLOCKED);
if(v == MUTEX_UNLOCKED)
runtime·throw("unlock of unlocked lock");
if(v == MUTEX_SLEEPING)
runtime·futexwakeup((uint32*)&l->key, 1);
+
+ if(--m->locks < 0)
+ runtime·throw("runtime·unlock: lock count");
+ if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
+ g->stackguard0 = StackPreempt;
}
// One-time notifications.
@@ -111,37 +115,42 @@ runtime·noteclear(Note *n)
void
runtime·notewakeup(Note *n)
{
- if(runtime·xchg((uint32*)&n->key, 1))
+ uint32 old;
+
+ old = runtime·xchg((uint32*)&n->key, 1);
+ if(old != 0) {
+ runtime·printf("notewakeup - double wakeup (%d)\n", old);
runtime·throw("notewakeup - double wakeup");
+ }
runtime·futexwakeup((uint32*)&n->key, 1);
}
void
runtime·notesleep(Note *n)
{
- if(m->profilehz > 0)
- runtime·setprof(false);
+ if(g != m->g0)
+ runtime·throw("notesleep not on g0");
while(runtime·atomicload((uint32*)&n->key) == 0)
runtime·futexsleep((uint32*)&n->key, 0, -1);
- if(m->profilehz > 0)
- runtime·setprof(true);
}
-void
-runtime·notetsleep(Note *n, int64 ns)
+#pragma textflag NOSPLIT
+static bool
+notetsleep(Note *n, int64 ns, int64 deadline, int64 now)
{
- int64 deadline, now;
+ // Conceptually, deadline and now are local variables.
+ // They are passed as arguments so that the space for them
+ // does not count against our nosplit stack sequence.
if(ns < 0) {
- runtime·notesleep(n);
- return;
+ while(runtime·atomicload((uint32*)&n->key) == 0)
+ runtime·futexsleep((uint32*)&n->key, 0, -1);
+ return true;
}
if(runtime·atomicload((uint32*)&n->key) != 0)
- return;
+ return true;
- if(m->profilehz > 0)
- runtime·setprof(false);
deadline = runtime·nanotime() + ns;
for(;;) {
runtime·futexsleep((uint32*)&n->key, 0, ns);
@@ -152,6 +161,33 @@ runtime·notetsleep(Note *n, int64 ns)
break;
ns = deadline - now;
}
- if(m->profilehz > 0)
- runtime·setprof(true);
+ return runtime·atomicload((uint32*)&n->key) != 0;
+}
+
+bool
+runtime·notetsleep(Note *n, int64 ns)
+{
+ bool res;
+
+ if(g != m->g0 && !m->gcing)
+ runtime·throw("notetsleep not on g0");
+
+ res = notetsleep(n, ns, 0, 0);
+ return res;
+}
+
+// same as runtime·notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+bool
+runtime·notetsleepg(Note *n, int64 ns)
+{
+ bool res;
+
+ if(g == m->g0)
+ runtime·throw("notetsleepg on g0");
+
+ runtime·entersyscallblock();
+ res = notetsleep(n, ns, 0, 0);
+ runtime·exitsyscall();
+ return res;
}