* doc/sourcebuild.texi (Ada Tests): Adjust reference to ACATS
[official-gcc.git] / libgo / runtime / thread.c
blobbac3f7dfdc1bbe0d8d3e30ddf414a73a1dbd2236
1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 #include <errno.h>
6 #include "runtime.h"
7 #include "go-assert.h"
9 void
10 runtime_initlock(Lock *l)
12 l->key = 0;
13 if(sem_init(&l->sem, 0, 0) != 0)
14 runtime_throw("sem_init failed");
17 static uint32
18 runtime_xadd(uint32 volatile *val, int32 delta)
20 uint32 oval, nval;
22 for(;;){
23 oval = *val;
24 nval = oval + delta;
25 if(runtime_cas(val, oval, nval))
26 return nval;
30 // noinline so that runtime_lock doesn't have to split the stack.
31 static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
33 static void
34 runtime_lock_full(Lock *l)
36 for(;;){
37 if(sem_wait(&l->sem) == 0)
38 return;
39 if(errno != EINTR)
40 runtime_throw("sem_wait failed");
44 void
45 runtime_lock(Lock *l)
47 if(m != nil) {
48 if(m->locks < 0)
49 runtime_throw("lock count");
50 m->locks++;
53 if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
54 runtime_lock_full(l);
57 static void runtime_unlock_full(Lock *l) __attribute__ ((noinline));
59 static void
60 runtime_unlock_full(Lock *l)
62 if(sem_post(&l->sem) != 0)
63 runtime_throw("sem_post failed");
66 void
67 runtime_unlock(Lock *l)
69 if(m != nil) {
70 m->locks--;
71 if(m->locks < 0)
72 runtime_throw("lock count");
75 if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
76 runtime_unlock_full(l);
79 void
80 runtime_destroylock(Lock *l)
82 sem_destroy(&l->sem);
85 #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
87 // For targets which don't have the required sync support. Really
88 // this should be provided by gcc itself. FIXME.
90 static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
92 _Bool
93 __sync_bool_compare_and_swap_4(uint32*, uint32, uint32)
94 __attribute__((visibility("hidden")));
96 _Bool
97 __sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new)
99 int i;
100 _Bool ret;
102 i = pthread_mutex_lock(&sync_lock);
103 __go_assert(i == 0);
105 if(*ptr != old) {
106 ret = 0;
107 } else {
108 *ptr = new;
109 ret = 1;
112 i = pthread_mutex_unlock(&sync_lock);
113 __go_assert(i == 0);
115 return ret;
118 #endif