aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime/thread.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-11-22 20:24:44 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-11-22 20:24:44 +0000
commit48e7d50e9f4e4d866e12383bd76a0e488eb14c54 (patch)
treef19dd9facaf8d0ad06290f19a199cc449393ffdd /libgo/runtime/thread.c
parent2195c9beb6abfb06b7981643e2f3ea926ec0593b (diff)
downloadgcc-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.c116
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;
}