OSDN Git Service

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