diff options
Diffstat (limited to 'libgo/runtime/thread.c')
-rw-r--r-- | libgo/runtime/thread.c | 159 |
1 files changed, 85 insertions, 74 deletions
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c index 822d5da0cac..459fc85c780 100644 --- a/libgo/runtime/thread.c +++ b/libgo/runtime/thread.c @@ -3,103 +3,114 @@ // license that can be found in the LICENSE file. #include <errno.h> +#include <signal.h> + #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"); -} +/* For targets which don't have the required sync support. Really + these should be provided by gcc itself. FIXME. */ -// noinline so that runtime_lock doesn't have to split the stack. -static void runtime_lock_full(Lock *l) __attribute__ ((noinline)); +#if !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4) || !defined (HAVE_SYNC_FETCH_AND_ADD_4) -static void -runtime_lock_full(Lock *l) -{ - for(;;){ - if(sem_wait(&l->sem) == 0) - return; - if(errno != EINTR) - runtime_throw("sem_wait failed"); - } -} +static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER; -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); -} +#endif -static void runtime_unlock_full(Lock *l) __attribute__ ((noinline)); +#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 -static void -runtime_unlock_full(Lock *l) -{ - if(sem_post(&l->sem) != 0) - runtime_throw("sem_post failed"); -} +_Bool +__sync_bool_compare_and_swap_4 (uint32*, uint32, uint32) + __attribute__ ((visibility ("hidden"))); -void -runtime_unlock(Lock *l) +_Bool +__sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new) { - 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); -} + int i; + _Bool ret; -void -runtime_destroylock(Lock *l) -{ - sem_destroy(&l->sem); -} + i = pthread_mutex_lock (&sync_lock); + __go_assert (i == 0); -#ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 + if (*ptr != old) + ret = 0; + else + { + *ptr = new; + ret = 1; + } -// For targets which don't have the required sync support. Really -// this should be provided by gcc itself. FIXME. + i = pthread_mutex_unlock (&sync_lock); + __go_assert (i == 0); -static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER; + return ret; +} -_Bool -__sync_bool_compare_and_swap_4(uint32*, uint32, uint32) - __attribute__((visibility("hidden"))); +#endif -_Bool -__sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new) +#ifndef HAVE_SYNC_FETCH_AND_ADD_4 + +uint32 +__sync_fetch_and_add_4 (uint32*, uint32) + __attribute__ ((visibility ("hidden"))); + +uint32 +__sync_fetch_and_add_4 (uint32* ptr, uint32 add) { int i; - _Bool ret; + uint32 ret; - i = pthread_mutex_lock(&sync_lock); - __go_assert(i == 0); + i = pthread_mutex_lock (&sync_lock); + __go_assert (i == 0); - if(*ptr != old) { - ret = 0; - } else { - *ptr = new; - ret = 1; - } + ret = *ptr; + *ptr += add; - i = pthread_mutex_unlock(&sync_lock); - __go_assert(i == 0); + i = pthread_mutex_unlock (&sync_lock); + __go_assert (i == 0); return ret; } #endif + +// Called to initialize a new m (including the bootstrap m). +void +runtime_minit(void) +{ + byte* stack; + size_t stacksize; + stack_t ss; + + // Initialize signal handling. + runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize); // OS X wants >=8K, Linux >=2K + ss.ss_sp = stack; + ss.ss_flags = 0; + ss.ss_size = stacksize; + if(sigaltstack(&ss, nil) < 0) + *(int *)0xf1 = 0xf1; +} + +// Temporary functions, which will be removed when we stop using +// condition variables. + +void +runtime_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) +{ + int i; + + runtime_entersyscall(); + + i = pthread_cond_wait(cond, mutex); + if(i != 0) + runtime_throw("pthread_cond_wait"); + i = pthread_mutex_unlock(mutex); + if(i != 0) + runtime_throw("pthread_mutex_unlock"); + + runtime_exitsyscall(); + + i = pthread_mutex_lock(mutex); + if(i != 0) + runtime_throw("pthread_mutex_lock"); +} |