diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-11-22 20:24:44 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-11-22 20:24:44 +0000 |
commit | 48e7d50e9f4e4d866e12383bd76a0e488eb14c54 (patch) | |
tree | f19dd9facaf8d0ad06290f19a199cc449393ffdd /libgo/runtime/thread.c | |
parent | 2195c9beb6abfb06b7981643e2f3ea926ec0593b (diff) | |
download | gcc-48e7d50e9f4e4d866e12383bd76a0e488eb14c54.zip gcc-48e7d50e9f4e4d866e12383bd76a0e488eb14c54.tar.gz gcc-48e7d50e9f4e4d866e12383bd76a0e488eb14c54.tar.bz2 |
runtime: New lock/note implementation.
From-SVN: r181633
Diffstat (limited to 'libgo/runtime/thread.c')
-rw-r--r-- | libgo/runtime/thread.c | 116 |
1 files changed, 42 insertions, 74 deletions
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c index 822d5da..821668b 100644 --- a/libgo/runtime/thread.c +++ b/libgo/runtime/thread.c @@ -6,98 +6,66 @@ #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; } |