diff options
Diffstat (limited to 'src/pkg/runtime/lock_futex.c')
-rw-r--r-- | src/pkg/runtime/lock_futex.c | 201 |
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; -} |