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.c201
1 files changed, 0 insertions, 201 deletions
diff --git a/src/pkg/runtime/lock_futex.c b/src/pkg/runtime/lock_futex.c
deleted file mode 100644
index c16ac905d..000000000
--- a/src/pkg/runtime/lock_futex.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build dragonfly freebsd linux
-
-#include "runtime.h"
-#include "stack.h"
-#include "../../cmd/ld/textflag.h"
-
-// This implementation depends on OS-specific implementations of
-//
-// runtime·futexsleep(uint32 *addr, uint32 val, int64 ns)
-// Atomically,
-// if(*addr == val) sleep
-// Might be woken up spuriously; that's allowed.
-// Don't sleep longer than ns; ns < 0 means forever.
-//
-// runtime·futexwakeup(uint32 *addr, uint32 cnt)
-// If any procs are sleeping on addr, wake up at most cnt.
-
-enum
-{
- MUTEX_UNLOCKED = 0,
- MUTEX_LOCKED = 1,
- MUTEX_SLEEPING = 2,
-
- ACTIVE_SPIN = 4,
- ACTIVE_SPIN_CNT = 30,
- PASSIVE_SPIN = 1,
-};
-
-// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
-// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
-// Note that there can be spinning threads during all states - they do not
-// affect mutex's state.
-void
-runtime·lock(Lock *l)
-{
- uint32 i, v, wait, spin;
-
- if(m->locks++ < 0)
- runtime·throw("runtime·lock: lock count");
-
- // Speculative grab for lock.
- v = runtime·xchg((uint32*)&l->key, MUTEX_LOCKED);
- if(v == MUTEX_UNLOCKED)
- return;
-
- // wait is either MUTEX_LOCKED or MUTEX_SLEEPING
- // depending on whether there is a thread sleeping
- // on this mutex. If we ever change l->key from
- // MUTEX_SLEEPING to some other value, we must be
- // careful to change it back to MUTEX_SLEEPING before
- // returning, to ensure that the sleeping thread gets
- // its wakeup call.
- wait = v;
-
- // On uniprocessor's, no point spinning.
- // On multiprocessors, spin for ACTIVE_SPIN attempts.
- spin = 0;
- if(runtime·ncpu > 1)
- spin = ACTIVE_SPIN;
-
- for(;;) {
- // Try for lock, spinning.
- for(i = 0; i < spin; i++) {
- while(l->key == MUTEX_UNLOCKED)
- if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
- return;
- runtime·procyield(ACTIVE_SPIN_CNT);
- }
-
- // Try for lock, rescheduling.
- for(i=0; i < PASSIVE_SPIN; i++) {
- while(l->key == MUTEX_UNLOCKED)
- if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
- return;
- runtime·osyield();
- }
-
- // Sleep.
- v = runtime·xchg((uint32*)&l->key, MUTEX_SLEEPING);
- if(v == MUTEX_UNLOCKED)
- return;
- wait = MUTEX_SLEEPING;
- runtime·futexsleep((uint32*)&l->key, MUTEX_SLEEPING, -1);
- }
-}
-
-void
-runtime·unlock(Lock *l)
-{
- uint32 v;
-
- 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.
-void
-runtime·noteclear(Note *n)
-{
- n->key = 0;
-}
-
-void
-runtime·notewakeup(Note *n)
-{
- 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(g != m->g0)
- runtime·throw("notesleep not on g0");
- while(runtime·atomicload((uint32*)&n->key) == 0) {
- m->blocked = true;
- runtime·futexsleep((uint32*)&n->key, 0, -1);
- m->blocked = false;
- }
-}
-
-#pragma textflag NOSPLIT
-static bool
-notetsleep(Note *n, int64 ns, int64 deadline, int64 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) {
- while(runtime·atomicload((uint32*)&n->key) == 0) {
- m->blocked = true;
- runtime·futexsleep((uint32*)&n->key, 0, -1);
- m->blocked = false;
- }
- return true;
- }
-
- if(runtime·atomicload((uint32*)&n->key) != 0)
- return true;
-
- deadline = runtime·nanotime() + ns;
- for(;;) {
- m->blocked = true;
- runtime·futexsleep((uint32*)&n->key, 0, ns);
- m->blocked = false;
- if(runtime·atomicload((uint32*)&n->key) != 0)
- break;
- now = runtime·nanotime();
- if(now >= deadline)
- break;
- ns = deadline - now;
- }
- 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;
-}