Fix r180999.
[gcc.git] / libgo / runtime / thread.c
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.
4
5 #include <errno.h>
6 #include "runtime.h"
7 #include "go-assert.h"
8
9 void
10 runtime_initlock(Lock *l)
11 {
12 l->key = 0;
13 if(sem_init(&l->sem, 0, 0) != 0)
14 runtime_throw("sem_init failed");
15 }
16
17 // noinline so that runtime_lock doesn't have to split the stack.
18 static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
19
20 static void
21 runtime_lock_full(Lock *l)
22 {
23 for(;;){
24 if(sem_wait(&l->sem) == 0)
25 return;
26 if(errno != EINTR)
27 runtime_throw("sem_wait failed");
28 }
29 }
30
31 void
32 runtime_lock(Lock *l)
33 {
34 if(m != nil) {
35 if(m->locks < 0)
36 runtime_throw("lock count");
37 m->locks++;
38 }
39
40 if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
41 runtime_lock_full(l);
42 }
43
44 static void runtime_unlock_full(Lock *l) __attribute__ ((noinline));
45
46 static void
47 runtime_unlock_full(Lock *l)
48 {
49 if(sem_post(&l->sem) != 0)
50 runtime_throw("sem_post failed");
51 }
52
53 void
54 runtime_unlock(Lock *l)
55 {
56 if(m != nil) {
57 m->locks--;
58 if(m->locks < 0)
59 runtime_throw("lock count");
60 }
61
62 if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
63 runtime_unlock_full(l);
64 }
65
66 void
67 runtime_destroylock(Lock *l)
68 {
69 sem_destroy(&l->sem);
70 }
71
72 #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
73
74 // For targets which don't have the required sync support. Really
75 // this should be provided by gcc itself. FIXME.
76
77 static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
78
79 _Bool
80 __sync_bool_compare_and_swap_4(uint32*, uint32, uint32)
81 __attribute__((visibility("hidden")));
82
83 _Bool
84 __sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new)
85 {
86 int i;
87 _Bool ret;
88
89 i = pthread_mutex_lock(&sync_lock);
90 __go_assert(i == 0);
91
92 if(*ptr != old) {
93 ret = 0;
94 } else {
95 *ptr = new;
96 ret = 1;
97 }
98
99 i = pthread_mutex_unlock(&sync_lock);
100 __go_assert(i == 0);
101
102 return ret;
103 }
104
105 #endif