summaryrefslogtreecommitdiff
path: root/libgo/runtime/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/runtime/thread.c')
-rw-r--r--libgo/runtime/thread.c159
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");
+}