From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- libgo/runtime/thread.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 libgo/runtime/thread.c (limited to 'libgo/runtime/thread.c') diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c new file mode 100644 index 000000000..bac3f7dfd --- /dev/null +++ b/libgo/runtime/thread.c @@ -0,0 +1,118 @@ +// 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 +#include "runtime.h" +#include "go-assert.h" + +void +runtime_initlock(Lock *l) +{ + 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) +{ + for(;;){ + if(sem_wait(&l->sem) == 0) + return; + if(errno != EINTR) + runtime_throw("sem_wait failed"); + } +} + +void +runtime_lock(Lock *l) +{ + if(m != nil) { + if(m->locks < 0) + runtime_throw("lock count"); + m->locks++; + } + + if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait + runtime_lock_full(l); +} + +static void runtime_unlock_full(Lock *l) __attribute__ ((noinline)); + +static void +runtime_unlock_full(Lock *l) +{ + if(sem_post(&l->sem) != 0) + runtime_throw("sem_post failed"); +} + +void +runtime_unlock(Lock *l) +{ + if(m != nil) { + m->locks--; + if(m->locks < 0) + runtime_throw("lock count"); + } + + if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting + runtime_unlock_full(l); +} + +void +runtime_destroylock(Lock *l) +{ + sem_destroy(&l->sem); +} + +#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 + +// For targets which don't have the required sync support. Really +// this should be provided by gcc itself. FIXME. + +static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER; + +_Bool +__sync_bool_compare_and_swap_4(uint32*, uint32, uint32) + __attribute__((visibility("hidden"))); + +_Bool +__sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new) +{ + int i; + _Bool ret; + + i = pthread_mutex_lock(&sync_lock); + __go_assert(i == 0); + + if(*ptr != old) { + ret = 0; + } else { + *ptr = new; + ret = 1; + } + + i = pthread_mutex_unlock(&sync_lock); + __go_assert(i == 0); + + return ret; +} + +#endif -- cgit v1.2.3