2010-12-03 05:34:57 +01:00
|
|
|
// Copyright 2010 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.
|
|
|
|
|
|
|
|
#include "runtime.h"
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime_initlock(Lock *l)
|
|
|
|
{
|
2010-12-17 07:42:06 +01:00
|
|
|
l->key = 0;
|
|
|
|
if(sem_init(&l->sem, 0, 0) != 0)
|
|
|
|
runtime_throw("sem_init failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32
|
|
|
|
runtime_xadd(uint32 volatile *val, int32 delta)
|
|
|
|
{
|
|
|
|
uint32 oval, nval;
|
|
|
|
|
|
|
|
for(;;){
|
|
|
|
oval = *val;
|
|
|
|
nval = oval + delta;
|
|
|
|
if(runtime_cas(val, oval, nval))
|
|
|
|
return nval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// noinline so that runtime_lock doesn't have to split the stack.
|
|
|
|
static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
|
|
|
|
|
|
|
|
static void
|
|
|
|
runtime_lock_full(Lock *l)
|
|
|
|
{
|
|
|
|
if(sem_wait(&l->sem) != 0)
|
|
|
|
runtime_throw("sem_wait failed");
|
2010-12-03 05:34:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime_lock(Lock *l)
|
|
|
|
{
|
2011-01-22 03:59:24 +01:00
|
|
|
if(m != nil) {
|
|
|
|
if(m->locks < 0)
|
|
|
|
runtime_throw("lock count");
|
|
|
|
m->locks++;
|
|
|
|
}
|
2010-12-17 07:42:06 +01:00
|
|
|
|
|
|
|
if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
|
|
|
|
runtime_lock_full(l);
|
2010-12-03 05:34:57 +01:00
|
|
|
}
|
|
|
|
|
2010-12-17 07:42:06 +01:00
|
|
|
static void runtime_unlock_full(Lock *l) __attribute__ ((noinline));
|
|
|
|
|
|
|
|
static void
|
|
|
|
runtime_unlock_full(Lock *l)
|
2010-12-03 05:34:57 +01:00
|
|
|
{
|
2010-12-17 07:42:06 +01:00
|
|
|
if(sem_post(&l->sem) != 0)
|
|
|
|
runtime_throw("sem_post failed");
|
2010-12-03 05:34:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-12-17 07:42:06 +01:00
|
|
|
runtime_unlock(Lock *l)
|
2010-12-03 05:34:57 +01:00
|
|
|
{
|
2011-01-22 03:59:24 +01:00
|
|
|
if(m != nil) {
|
|
|
|
m->locks--;
|
|
|
|
if(m->locks < 0)
|
|
|
|
runtime_throw("lock count");
|
|
|
|
}
|
2010-12-17 07:42:06 +01:00
|
|
|
|
|
|
|
if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
|
|
|
|
runtime_unlock_full(l);
|
2010-12-03 05:34:57 +01:00
|
|
|
}
|
|
|
|
|
2010-12-17 07:42:06 +01:00
|
|
|
void
|
|
|
|
runtime_destroylock(Lock *l)
|
2010-12-03 05:34:57 +01:00
|
|
|
{
|
2010-12-17 07:42:06 +01:00
|
|
|
sem_destroy(&l->sem);
|
2010-12-03 05:34:57 +01:00
|
|
|
}
|