OSDN Git Service

459fc85c7802c945fbf31b78619bf399422ab650
[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 <signal.h>
7
8 #include "runtime.h"
9 #include "go-assert.h"
10
11 /* For targets which don't have the required sync support.  Really
12    these should be provided by gcc itself.  FIXME.  */
13
14 #if !defined (HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4) || !defined (HAVE_SYNC_FETCH_AND_ADD_4)
15
16 static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
17
18 #endif
19
20 #ifndef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4
21
22 _Bool
23 __sync_bool_compare_and_swap_4 (uint32*, uint32, uint32)
24   __attribute__ ((visibility ("hidden")));
25
26 _Bool
27 __sync_bool_compare_and_swap_4 (uint32* ptr, uint32 old, uint32 new)
28 {
29   int i;
30   _Bool ret;
31
32   i = pthread_mutex_lock (&sync_lock);
33   __go_assert (i == 0);
34
35   if (*ptr != old)
36     ret = 0;
37   else
38     {
39       *ptr = new;
40       ret = 1;
41     }
42
43   i = pthread_mutex_unlock (&sync_lock);
44   __go_assert (i == 0);
45
46   return ret;
47 }
48
49 #endif
50
51 #ifndef HAVE_SYNC_FETCH_AND_ADD_4
52
53 uint32
54 __sync_fetch_and_add_4 (uint32*, uint32)
55   __attribute__ ((visibility ("hidden")));
56
57 uint32
58 __sync_fetch_and_add_4 (uint32* ptr, uint32 add)
59 {
60   int i;
61   uint32 ret;
62
63   i = pthread_mutex_lock (&sync_lock);
64   __go_assert (i == 0);
65
66   ret = *ptr;
67   *ptr += add;
68
69   i = pthread_mutex_unlock (&sync_lock);
70   __go_assert (i == 0);
71
72   return ret;
73 }
74
75 #endif
76
77 // Called to initialize a new m (including the bootstrap m).
78 void
79 runtime_minit(void)
80 {
81         byte* stack;
82         size_t stacksize;
83         stack_t ss;
84
85         // Initialize signal handling.
86         runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize);       // OS X wants >=8K, Linux >=2K
87         ss.ss_sp = stack;
88         ss.ss_flags = 0;
89         ss.ss_size = stacksize;
90         if(sigaltstack(&ss, nil) < 0)
91                 *(int *)0xf1 = 0xf1;
92 }
93
94 // Temporary functions, which will be removed when we stop using
95 // condition variables.
96
97 void
98 runtime_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
99 {
100         int i;
101
102         runtime_entersyscall();
103
104         i = pthread_cond_wait(cond, mutex);
105         if(i != 0)
106                 runtime_throw("pthread_cond_wait");
107         i = pthread_mutex_unlock(mutex);
108         if(i != 0)
109                 runtime_throw("pthread_mutex_unlock");
110
111         runtime_exitsyscall();
112
113         i = pthread_mutex_lock(mutex);
114         if(i != 0)
115                 runtime_throw("pthread_mutex_lock");
116 }