PR 47802 Use builtins to check localtime_r return type
[official-gcc.git] / libgo / runtime / thread.c
blobb600754f64c1673fd5a33225a2993267692282c0
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 "runtime.h"
6 #include "go-assert.h"
8 void
9 runtime_initlock(Lock *l)
11 l->key = 0;
12 if(sem_init(&l->sem, 0, 0) != 0)
13 runtime_throw("sem_init failed");
16 static uint32
17 runtime_xadd(uint32 volatile *val, int32 delta)
19 uint32 oval, nval;
21 for(;;){
22 oval = *val;
23 nval = oval + delta;
24 if(runtime_cas(val, oval, nval))
25 return nval;
29 // noinline so that runtime_lock doesn't have to split the stack.
30 static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
32 static void
33 runtime_lock_full(Lock *l)
35 if(sem_wait(&l->sem) != 0)
36 runtime_throw("sem_wait failed");
39 void
40 runtime_lock(Lock *l)
42 if(m != nil) {
43 if(m->locks < 0)
44 runtime_throw("lock count");
45 m->locks++;
48 if(runtime_xadd(&l->key, 1) > 1) // someone else has it; wait
49 runtime_lock_full(l);
52 static void runtime_unlock_full(Lock *l) __attribute__ ((noinline));
54 static void
55 runtime_unlock_full(Lock *l)
57 if(sem_post(&l->sem) != 0)
58 runtime_throw("sem_post failed");
61 void
62 runtime_unlock(Lock *l)
64 if(m != nil) {
65 m->locks--;
66 if(m->locks < 0)
67 runtime_throw("lock count");
70 if(runtime_xadd(&l->key, -1) > 0) // someone else is waiting
71 runtime_unlock_full(l);
74 void
75 runtime_destroylock(Lock *l)
77 sem_destroy(&l->sem);
80 #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
82 // For targets which don't have the required sync support. Really
83 // this should be provided by gcc itself. FIXME.
85 static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
87 _Bool
88 __sync_bool_compare_and_swap_4(uint32*, uint32, uint32)
89 __attribute__((visibility("hidden")));
91 _Bool
92 __sync_bool_compare_and_swap_4(uint32* ptr, uint32 old, uint32 new)
94 int i;
95 _Bool ret;
97 i = pthread_mutex_lock(&sync_lock);
98 __go_assert(i == 0);
100 if(*ptr != old) {
101 ret = 0;
102 } else {
103 *ptr = new;
104 ret = 1;
107 i = pthread_mutex_unlock(&sync_lock);
108 __go_assert(i == 0);
110 return ret;
113 #endif