boehm-gc: revert all CACAO-specific modifications; this is now an exact copy of the...
[cacao.git] / src / mm / boehm-gc / libatomic_ops-1.2 / src / atomic_ops / sysdeps / generic_pthread.h
1 /*
2  * Copyright (c) 2003 by Hewlett-Packard Company.  All rights reserved.
3  * 
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  * 
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  * 
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE. 
21  */
22
23 /* The following is useful primarily for debugging and documentation.   */
24 /* We define various atomic operations by acquiring a global pthread    */
25 /* lock.  The resulting implementation will perform poorly, but should  */
26 /* be correct unless it is used from signal handlers.                   */
27 /* We assume that all pthread operations act like full memory barriers. */
28 /* (We believe that is the intent of the specification.)                */
29
30 #include <pthread.h>
31
32 #include "test_and_set_t_is_ao_t.h"
33         /* This is not necessarily compatible with the native           */
34         /* implementation.  But those can't be safely mixed anyway.     */
35
36 /* We define only the full barrier variants, and count on the           */
37 /* generalization section below to fill in the rest.                    */
38 extern pthread_mutex_t AO_pt_lock;
39
40 AO_INLINE void
41 AO_nop_full(void)
42 {
43   pthread_mutex_lock(&AO_pt_lock);
44   pthread_mutex_unlock(&AO_pt_lock);
45 }
46
47 #define AO_HAVE_nop_full
48
49 AO_INLINE AO_t
50 AO_load_full(const volatile AO_t *addr)
51 {
52   AO_t result;
53   pthread_mutex_lock(&AO_pt_lock);
54   result = *addr;
55   pthread_mutex_unlock(&AO_pt_lock);
56   return result;
57 }
58
59 #define AO_HAVE_load_full
60
61 AO_INLINE void
62 AO_store_full(volatile AO_t *addr, AO_t val)
63 {
64   pthread_mutex_lock(&AO_pt_lock);
65   *addr = val;
66   pthread_mutex_unlock(&AO_pt_lock);
67 }
68
69 #define AO_HAVE_store_full
70
71 AO_INLINE unsigned char
72 AO_char_load_full(const volatile unsigned char *addr)
73 {
74   unsigned char result;
75   pthread_mutex_lock(&AO_pt_lock);
76   result = *addr;
77   pthread_mutex_unlock(&AO_pt_lock);
78   return result;
79 }
80
81 #define AO_HAVE_char_load_full
82
83 AO_INLINE void
84 AO_char_store_full(volatile unsigned char *addr, unsigned char val)
85 {
86   pthread_mutex_lock(&AO_pt_lock);
87   *addr = val;
88   pthread_mutex_unlock(&AO_pt_lock);
89 }
90
91 #define AO_HAVE_char_store_full
92
93 AO_INLINE unsigned short
94 AO_short_load_full(const volatile unsigned short *addr)
95 {
96   unsigned short result;
97   pthread_mutex_lock(&AO_pt_lock);
98   result = *addr;
99   pthread_mutex_unlock(&AO_pt_lock);
100   return result;
101 }
102
103 #define AO_HAVE_short_load_full
104
105 AO_INLINE void
106 AO_short_store_full(volatile unsigned short *addr, unsigned short val)
107 {
108   pthread_mutex_lock(&AO_pt_lock);
109   *addr = val;
110   pthread_mutex_unlock(&AO_pt_lock);
111 }
112
113 #define AO_HAVE_short_store_full
114
115 AO_INLINE unsigned int
116 AO_int_load_full(const volatile unsigned int *addr)
117 {
118   unsigned int result;
119   pthread_mutex_lock(&AO_pt_lock);
120   result = *addr;
121   pthread_mutex_unlock(&AO_pt_lock);
122   return result;
123 }
124
125 #define AO_HAVE_int_load_full
126
127 AO_INLINE void
128 AO_int_store_full(volatile unsigned int *addr, unsigned int val)
129 {
130   pthread_mutex_lock(&AO_pt_lock);
131   *addr = val;
132   pthread_mutex_unlock(&AO_pt_lock);
133 }
134
135 #define AO_HAVE_int_store_full
136
137 AO_INLINE AO_TS_VAL_t
138 AO_test_and_set_full(volatile AO_TS_t *addr)
139 {
140   AO_TS_VAL_t result;
141   pthread_mutex_lock(&AO_pt_lock);
142   result = (AO_TS_VAL_t)(*addr);
143   *addr = AO_TS_SET;
144   pthread_mutex_unlock(&AO_pt_lock);
145   assert(result == AO_TS_SET || result == AO_TS_CLEAR);
146   return result;
147 }
148
149 #define AO_HAVE_test_and_set_full
150
151 AO_INLINE AO_t
152 AO_fetch_and_add_full(volatile AO_t *p, AO_t incr)
153 {
154   AO_t tmp;
155
156   pthread_mutex_lock(&AO_pt_lock);
157   tmp = *p;
158   *p = tmp + incr;
159   pthread_mutex_unlock(&AO_pt_lock);
160   return tmp;
161 }
162
163 #define AO_HAVE_fetch_and_add_full
164
165 AO_INLINE unsigned char
166 AO_char_fetch_and_add_full(volatile unsigned char *p, unsigned char incr)
167 {
168   unsigned char tmp;
169
170   pthread_mutex_lock(&AO_pt_lock);
171   tmp = *p;
172   *p = tmp + incr;
173   pthread_mutex_unlock(&AO_pt_lock);
174   return tmp;
175 }
176
177 #define AO_HAVE_char_fetch_and_add_full
178
179 AO_INLINE unsigned short
180 AO_short_fetch_and_add_full(volatile unsigned short *p, unsigned short incr)
181 {
182   unsigned short tmp;
183
184   pthread_mutex_lock(&AO_pt_lock);
185   tmp = *p;
186   *p = tmp + incr;
187   pthread_mutex_unlock(&AO_pt_lock);
188   return tmp;
189 }
190
191 #define AO_HAVE_short_fetch_and_add_full
192
193 AO_INLINE unsigned int
194 AO_int_fetch_and_add_full(volatile unsigned int *p, unsigned int incr)
195 {
196   unsigned int tmp;
197
198   pthread_mutex_lock(&AO_pt_lock);
199   tmp = *p;
200   *p = tmp + incr;
201   pthread_mutex_unlock(&AO_pt_lock);
202   return tmp;
203 }
204
205 #define AO_HAVE_int_fetch_and_add_full
206
207 AO_INLINE void
208 AO_or_full(volatile AO_t *p, AO_t incr)
209 {
210   AO_t tmp;
211
212   pthread_mutex_lock(&AO_pt_lock);
213   tmp = *p;
214   *p = (tmp | incr);
215   pthread_mutex_unlock(&AO_pt_lock);
216 }
217
218 #define AO_HAVE_or_full
219
220 AO_INLINE int
221 AO_compare_and_swap_full(volatile AO_t *addr,
222                              AO_t old, AO_t new_val) 
223 {
224   pthread_mutex_lock(&AO_pt_lock);
225   if (*addr == old)
226     {
227       *addr = new_val;
228       pthread_mutex_unlock(&AO_pt_lock);
229       return 1;
230     }
231   else
232     pthread_mutex_unlock(&AO_pt_lock);
233     return 0;
234 }
235
236 #define AO_HAVE_compare_and_swap_full
237
238 /* Unlike real architectures, we define both double-width CAS variants. */
239
240 typedef struct {
241         AO_t AO_val1;
242         AO_t AO_val2;
243 } AO_double_t;
244
245 #define AO_HAVE_double_t
246
247 AO_INLINE int
248 AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
249                                        AO_t old1, AO_t old2,
250                                        AO_t new1, AO_t new2) 
251 {
252   pthread_mutex_lock(&AO_pt_lock);
253   if (addr -> AO_val1 == old1 && addr -> AO_val2 == old2)
254     {
255       addr -> AO_val1 = new1;
256       addr -> AO_val2 = new2;
257       pthread_mutex_unlock(&AO_pt_lock);
258       return 1;
259     }
260   else
261     pthread_mutex_unlock(&AO_pt_lock);
262     return 0;
263 }
264
265 #define AO_HAVE_compare_double_and_swap_double_full
266
267 AO_INLINE int
268 AO_compare_and_swap_double_full(volatile AO_double_t *addr,
269                                 AO_t old1,
270                                 AO_t new1, AO_t new2) 
271 {
272   pthread_mutex_lock(&AO_pt_lock);
273   if (addr -> AO_val1 == old1)
274     {
275       addr -> AO_val1 = new1;
276       addr -> AO_val2 = new2;
277       pthread_mutex_unlock(&AO_pt_lock);
278       return 1;
279     }
280   else
281     pthread_mutex_unlock(&AO_pt_lock);
282     return 0;
283 }
284
285 #define AO_HAVE_compare_and_swap_double_full
286
287 /* We can't use hardware loads and stores, since they don't     */
288 /* interact correctly with atomic updates.                      */
289