This source file includes following definitions.
- runtime·lock
- runtime·unlock
- runtime·noteclear
- runtime·notewakeup
- runtime·notesleep
- notetsleep
- runtime·notetsleep
- runtime·notetsleepg
#include "runtime.h"
#include "stack.h"
#include "../../cmd/ld/textflag.h"
enum
{
MUTEX_UNLOCKED = 0,
MUTEX_LOCKED = 1,
MUTEX_SLEEPING = 2,
ACTIVE_SPIN = 4,
ACTIVE_SPIN_CNT = 30,
PASSIVE_SPIN = 1,
};
void
runtime·lock(Lock *l)
{
uint32 i, v, wait, spin;
if(m->locks++ < 0)
runtime·throw("runtime·lock: lock count");
v = runtime·xchg((uint32*)&l->key, MUTEX_LOCKED);
if(v == MUTEX_UNLOCKED)
return;
wait = v;
spin = 0;
if(runtime·ncpu > 1)
spin = ACTIVE_SPIN;
for(;;) {
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);
}
for(i=0; i < PASSIVE_SPIN; i++) {
while(l->key == MUTEX_UNLOCKED)
if(runtime·cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
return;
runtime·osyield();
}
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)
g->stackguard0 = StackPreempt;
}
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)
{
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;
}
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;
}