Mercurial > hg > CbC > CbC_gcc
annotate gcc/gthr-posix95.h @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | 77e2b8dfacca |
children |
rev | line source |
---|---|
0 | 1 /* Threads compatibility routines for libgcc2 and libobjc. */ |
2 /* Compile this one with gcc. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
3 /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
4 Free Software Foundation, Inc. |
0 | 5 |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 Under Section 7 of GPL version 3, you are granted additional | |
19 permissions described in the GCC Runtime Library Exception, version | |
20 3.1, as published by the Free Software Foundation. | |
21 | |
22 You should have received a copy of the GNU General Public License and | |
23 a copy of the GCC Runtime Library Exception along with this program; | |
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
25 <http://www.gnu.org/licenses/>. */ | |
26 | |
27 #ifndef GCC_GTHR_POSIX_H | |
28 #define GCC_GTHR_POSIX_H | |
29 | |
30 /* POSIX threads specific definitions. | |
31 Easy, since the interface is just one-to-one mapping. */ | |
32 | |
33 #define __GTHREADS 1 | |
34 | |
35 /* Some implementations of <pthread.h> require this to be defined. */ | |
36 #ifndef _REENTRANT | |
37 #define _REENTRANT 1 | |
38 #endif | |
39 | |
40 #include <pthread.h> | |
41 #include <unistd.h> | |
42 | |
43 typedef pthread_key_t __gthread_key_t; | |
44 typedef pthread_once_t __gthread_once_t; | |
45 typedef pthread_mutex_t __gthread_mutex_t; | |
46 typedef pthread_cond_t __gthread_cond_t; | |
47 | |
48 /* POSIX like conditional variables are supported. Please look at comments | |
49 in gthr.h for details. */ | |
50 #define __GTHREAD_HAS_COND 1 | |
51 | |
52 typedef struct { | |
53 long depth; | |
54 pthread_t owner; | |
55 pthread_mutex_t actual; | |
56 } __gthread_recursive_mutex_t; | |
57 | |
58 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER | |
59 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT | |
60 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function | |
61 #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER | |
62 | |
63 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK | |
64 # define __gthrw(name) \ | |
65 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); | |
66 # define __gthrw_(name) __gthrw_ ## name | |
67 #else | |
68 # define __gthrw(name) | |
69 # define __gthrw_(name) name | |
70 #endif | |
71 | |
72 __gthrw(pthread_once) | |
73 __gthrw(pthread_key_create) | |
74 __gthrw(pthread_key_delete) | |
75 __gthrw(pthread_getspecific) | |
76 __gthrw(pthread_setspecific) | |
77 __gthrw(pthread_create) | |
78 __gthrw(pthread_cancel) | |
79 __gthrw(pthread_self) | |
80 | |
81 __gthrw(pthread_mutex_init) | |
82 __gthrw(pthread_mutex_destroy) | |
83 __gthrw(pthread_mutex_lock) | |
84 __gthrw(pthread_mutex_trylock) | |
85 __gthrw(pthread_mutex_unlock) | |
86 __gthrw(pthread_mutexattr_init) | |
87 __gthrw(pthread_mutexattr_destroy) | |
88 | |
89 __gthrw(pthread_cond_broadcast) | |
90 __gthrw(pthread_cond_wait) | |
91 | |
92 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) | |
93 /* Objective-C. */ | |
94 __gthrw(pthread_cond_destroy) | |
95 __gthrw(pthread_cond_init) | |
96 __gthrw(pthread_cond_signal) | |
97 __gthrw(pthread_exit) | |
98 #ifdef _POSIX_PRIORITY_SCHEDULING | |
99 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
100 __gthrw(sched_get_priority_max) | |
101 __gthrw(sched_get_priority_min) | |
102 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ | |
103 #endif /* _POSIX_PRIORITY_SCHEDULING */ | |
104 __gthrw(sched_yield) | |
105 __gthrw(pthread_attr_destroy) | |
106 __gthrw(pthread_attr_init) | |
107 __gthrw(pthread_attr_setdetachstate) | |
108 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
109 __gthrw(pthread_getschedparam) | |
110 __gthrw(pthread_setschedparam) | |
111 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ | |
112 #endif /* _LIBOBJC || _LIBOBJC_WEAK */ | |
113 | |
114 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK | |
115 | |
116 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if | |
117 -pthreads is not specified. The functions are dummies and most return an | |
118 error value. However pthread_once returns 0 without invoking the routine | |
119 it is passed so we cannot pretend that the interface is active if -pthreads | |
120 is not specified. On Solaris 2.5.1, the interface is not exposed at all so | |
121 we need to play the usual game with weak symbols. On Solaris 10 and up, a | |
122 working interface is always exposed. On FreeBSD 6 and later, libc also | |
123 exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up | |
124 to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, | |
125 which means the alternate __gthread_active_p below cannot be used there. */ | |
126 | |
127 #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) | |
128 | |
129 static volatile int __gthread_active = -1; | |
130 | |
131 static void | |
132 __gthread_trigger (void) | |
133 { | |
134 __gthread_active = 1; | |
135 } | |
136 | |
137 static inline int | |
138 __gthread_active_p (void) | |
139 { | |
140 static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; | |
141 static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; | |
142 | |
143 /* Avoid reading __gthread_active twice on the main code path. */ | |
144 int __gthread_active_latest_value = __gthread_active; | |
145 | |
146 /* This test is not protected to avoid taking a lock on the main code | |
147 path so every update of __gthread_active in a threaded program must | |
148 be atomic with regard to the result of the test. */ | |
149 if (__builtin_expect (__gthread_active_latest_value < 0, 0)) | |
150 { | |
151 if (__gthrw_(pthread_once)) | |
152 { | |
153 /* If this really is a threaded program, then we must ensure that | |
154 __gthread_active has been set to 1 before exiting this block. */ | |
155 __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); | |
156 __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); | |
157 __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); | |
158 } | |
159 | |
160 /* Make sure we'll never enter this block again. */ | |
161 if (__gthread_active < 0) | |
162 __gthread_active = 0; | |
163 | |
164 __gthread_active_latest_value = __gthread_active; | |
165 } | |
166 | |
167 return __gthread_active_latest_value != 0; | |
168 } | |
169 | |
170 #else /* neither FreeBSD nor Solaris */ | |
171 | |
172 static inline int | |
173 __gthread_active_p (void) | |
174 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
175 static void *const __gthread_active_ptr |
0 | 176 = __extension__ (void *) &__gthrw_(pthread_cancel); |
177 return __gthread_active_ptr != 0; | |
178 } | |
179 | |
180 #endif /* FreeBSD or Solaris */ | |
181 | |
182 #else /* not SUPPORTS_WEAK */ | |
183 | |
184 /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread | |
185 calls in shared flavors of the HP-UX C library. Most of the stubs | |
186 have no functionality. The details are described in the "libc cumulative | |
187 patch" for each subversion of HP-UX 11. There are two special interfaces | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
188 provided for checking whether an application is linked to a shared pthread |
0 | 189 library or not. However, these interfaces aren't available in early |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
190 pthread libraries. We also need a test that works for archive |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
191 libraries. We can't use pthread_once as some libc versions call the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
192 init function. We also can't use pthread_create or pthread_attr_init |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
193 as these create a thread and thereby prevent changing the default stack |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
194 size. The function pthread_default_stacksize_np is available in both |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
195 the archive and shared versions of libpthread. It can be used to |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
196 determine the default pthread stack size. There is a stub in some |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
197 shared libc versions which returns a zero size if pthreads are not |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
198 active. We provide an equivalent stub to handle cases where libc |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
199 doesn't provide one. */ |
0 | 200 |
201 #if defined(__hppa__) && defined(__hpux__) | |
202 | |
203 static volatile int __gthread_active = -1; | |
204 | |
205 static inline int | |
206 __gthread_active_p (void) | |
207 { | |
208 /* Avoid reading __gthread_active twice on the main code path. */ | |
209 int __gthread_active_latest_value = __gthread_active; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
210 size_t __s; |
0 | 211 |
212 if (__builtin_expect (__gthread_active_latest_value < 0, 0)) | |
213 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
214 pthread_default_stacksize_np (0, &__s); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
215 __gthread_active = __s ? 1 : 0; |
0 | 216 __gthread_active_latest_value = __gthread_active; |
217 } | |
218 | |
219 return __gthread_active_latest_value != 0; | |
220 } | |
221 | |
222 #else /* not hppa-hpux */ | |
223 | |
224 static inline int | |
225 __gthread_active_p (void) | |
226 { | |
227 return 1; | |
228 } | |
229 | |
230 #endif /* hppa-hpux */ | |
231 | |
232 #endif /* SUPPORTS_WEAK */ | |
233 | |
234 #ifdef _LIBOBJC | |
235 | |
236 /* This is the config.h file in libobjc/ */ | |
237 #include <config.h> | |
238 | |
239 #ifdef HAVE_SCHED_H | |
240 # include <sched.h> | |
241 #endif | |
242 | |
243 /* Key structure for maintaining thread specific storage */ | |
244 static pthread_key_t _objc_thread_storage; | |
245 static pthread_attr_t _objc_thread_attribs; | |
246 | |
247 /* Thread local storage for a single thread */ | |
248 static void *thread_local_storage = NULL; | |
249 | |
250 /* Backend initialization functions */ | |
251 | |
252 /* Initialize the threads subsystem. */ | |
253 static inline int | |
254 __gthread_objc_init_thread_system (void) | |
255 { | |
256 if (__gthread_active_p ()) | |
257 { | |
258 /* Initialize the thread storage key. */ | |
259 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) | |
260 { | |
261 /* The normal default detach state for threads is | |
262 * PTHREAD_CREATE_JOINABLE which causes threads to not die | |
263 * when you think they should. */ | |
264 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 | |
265 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, | |
266 PTHREAD_CREATE_DETACHED) == 0) | |
267 return 0; | |
268 } | |
269 } | |
270 | |
271 return -1; | |
272 } | |
273 | |
274 /* Close the threads subsystem. */ | |
275 static inline int | |
276 __gthread_objc_close_thread_system (void) | |
277 { | |
278 if (__gthread_active_p () | |
279 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 | |
280 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) | |
281 return 0; | |
282 | |
283 return -1; | |
284 } | |
285 | |
286 /* Backend thread functions */ | |
287 | |
288 /* Create a new thread of execution. */ | |
289 static inline objc_thread_t | |
290 __gthread_objc_thread_detach (void (*func)(void *), void *arg) | |
291 { | |
292 objc_thread_t thread_id; | |
293 pthread_t new_thread_handle; | |
294 | |
295 if (!__gthread_active_p ()) | |
296 return NULL; | |
297 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
298 if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
299 (void *) func, arg))) |
0 | 300 thread_id = (objc_thread_t) new_thread_handle; |
301 else | |
302 thread_id = NULL; | |
303 | |
304 return thread_id; | |
305 } | |
306 | |
307 /* Set the current thread's priority. */ | |
308 static inline int | |
309 __gthread_objc_thread_set_priority (int priority) | |
310 { | |
311 if (!__gthread_active_p ()) | |
312 return -1; | |
313 else | |
314 { | |
315 #ifdef _POSIX_PRIORITY_SCHEDULING | |
316 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
317 pthread_t thread_id = __gthrw_(pthread_self) (); | |
318 int policy; | |
319 struct sched_param params; | |
320 int priority_min, priority_max; | |
321 | |
322 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) | |
323 { | |
324 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) | |
325 return -1; | |
326 | |
327 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) | |
328 return -1; | |
329 | |
330 if (priority > priority_max) | |
331 priority = priority_max; | |
332 else if (priority < priority_min) | |
333 priority = priority_min; | |
334 params.sched_priority = priority; | |
335 | |
336 /* | |
337 * The solaris 7 and several other man pages incorrectly state that | |
338 * this should be a pointer to policy but pthread.h is universally | |
339 * at odds with this. | |
340 */ | |
341 if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) | |
342 return 0; | |
343 } | |
344 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ | |
345 #endif /* _POSIX_PRIORITY_SCHEDULING */ | |
346 return -1; | |
347 } | |
348 } | |
349 | |
350 /* Return the current thread's priority. */ | |
351 static inline int | |
352 __gthread_objc_thread_get_priority (void) | |
353 { | |
354 #ifdef _POSIX_PRIORITY_SCHEDULING | |
355 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
356 if (__gthread_active_p ()) | |
357 { | |
358 int policy; | |
359 struct sched_param params; | |
360 | |
361 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) | |
362 return params.sched_priority; | |
363 else | |
364 return -1; | |
365 } | |
366 else | |
367 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ | |
368 #endif /* _POSIX_PRIORITY_SCHEDULING */ | |
369 return OBJC_THREAD_INTERACTIVE_PRIORITY; | |
370 } | |
371 | |
372 /* Yield our process time to another thread. */ | |
373 static inline void | |
374 __gthread_objc_thread_yield (void) | |
375 { | |
376 if (__gthread_active_p ()) | |
377 __gthrw_(sched_yield) (); | |
378 } | |
379 | |
380 /* Terminate the current thread. */ | |
381 static inline int | |
382 __gthread_objc_thread_exit (void) | |
383 { | |
384 if (__gthread_active_p ()) | |
385 /* exit the thread */ | |
386 __gthrw_(pthread_exit) (&__objc_thread_exit_status); | |
387 | |
388 /* Failed if we reached here */ | |
389 return -1; | |
390 } | |
391 | |
392 /* Returns an integer value which uniquely describes a thread. */ | |
393 static inline objc_thread_t | |
394 __gthread_objc_thread_id (void) | |
395 { | |
396 if (__gthread_active_p ()) | |
397 return (objc_thread_t) __gthrw_(pthread_self) (); | |
398 else | |
399 return (objc_thread_t) 1; | |
400 } | |
401 | |
402 /* Sets the thread's local storage pointer. */ | |
403 static inline int | |
404 __gthread_objc_thread_set_data (void *value) | |
405 { | |
406 if (__gthread_active_p ()) | |
407 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); | |
408 else | |
409 { | |
410 thread_local_storage = value; | |
411 return 0; | |
412 } | |
413 } | |
414 | |
415 /* Returns the thread's local storage pointer. */ | |
416 static inline void * | |
417 __gthread_objc_thread_get_data (void) | |
418 { | |
419 if (__gthread_active_p ()) | |
420 return __gthrw_(pthread_getspecific) (_objc_thread_storage); | |
421 else | |
422 return thread_local_storage; | |
423 } | |
424 | |
425 /* Backend mutex functions */ | |
426 | |
427 /* Allocate a mutex. */ | |
428 static inline int | |
429 __gthread_objc_mutex_allocate (objc_mutex_t mutex) | |
430 { | |
431 if (__gthread_active_p ()) | |
432 { | |
433 mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); | |
434 | |
435 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) | |
436 { | |
437 objc_free (mutex->backend); | |
438 mutex->backend = NULL; | |
439 return -1; | |
440 } | |
441 } | |
442 | |
443 return 0; | |
444 } | |
445 | |
446 /* Deallocate a mutex. */ | |
447 static inline int | |
448 __gthread_objc_mutex_deallocate (objc_mutex_t mutex) | |
449 { | |
450 if (__gthread_active_p ()) | |
451 { | |
452 int count; | |
453 | |
454 /* | |
455 * Posix Threads specifically require that the thread be unlocked | |
456 * for __gthrw_(pthread_mutex_destroy) to work. | |
457 */ | |
458 | |
459 do | |
460 { | |
461 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); | |
462 if (count < 0) | |
463 return -1; | |
464 } | |
465 while (count); | |
466 | |
467 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) | |
468 return -1; | |
469 | |
470 objc_free (mutex->backend); | |
471 mutex->backend = NULL; | |
472 } | |
473 return 0; | |
474 } | |
475 | |
476 /* Grab a lock on a mutex. */ | |
477 static inline int | |
478 __gthread_objc_mutex_lock (objc_mutex_t mutex) | |
479 { | |
480 if (__gthread_active_p () | |
481 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) | |
482 { | |
483 return -1; | |
484 } | |
485 | |
486 return 0; | |
487 } | |
488 | |
489 /* Try to grab a lock on a mutex. */ | |
490 static inline int | |
491 __gthread_objc_mutex_trylock (objc_mutex_t mutex) | |
492 { | |
493 if (__gthread_active_p () | |
494 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) | |
495 { | |
496 return -1; | |
497 } | |
498 | |
499 return 0; | |
500 } | |
501 | |
502 /* Unlock the mutex */ | |
503 static inline int | |
504 __gthread_objc_mutex_unlock (objc_mutex_t mutex) | |
505 { | |
506 if (__gthread_active_p () | |
507 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) | |
508 { | |
509 return -1; | |
510 } | |
511 | |
512 return 0; | |
513 } | |
514 | |
515 /* Backend condition mutex functions */ | |
516 | |
517 /* Allocate a condition. */ | |
518 static inline int | |
519 __gthread_objc_condition_allocate (objc_condition_t condition) | |
520 { | |
521 if (__gthread_active_p ()) | |
522 { | |
523 condition->backend = objc_malloc (sizeof (pthread_cond_t)); | |
524 | |
525 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) | |
526 { | |
527 objc_free (condition->backend); | |
528 condition->backend = NULL; | |
529 return -1; | |
530 } | |
531 } | |
532 | |
533 return 0; | |
534 } | |
535 | |
536 /* Deallocate a condition. */ | |
537 static inline int | |
538 __gthread_objc_condition_deallocate (objc_condition_t condition) | |
539 { | |
540 if (__gthread_active_p ()) | |
541 { | |
542 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) | |
543 return -1; | |
544 | |
545 objc_free (condition->backend); | |
546 condition->backend = NULL; | |
547 } | |
548 return 0; | |
549 } | |
550 | |
551 /* Wait on the condition */ | |
552 static inline int | |
553 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) | |
554 { | |
555 if (__gthread_active_p ()) | |
556 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, | |
557 (pthread_mutex_t *) mutex->backend); | |
558 else | |
559 return 0; | |
560 } | |
561 | |
562 /* Wake up all threads waiting on this condition. */ | |
563 static inline int | |
564 __gthread_objc_condition_broadcast (objc_condition_t condition) | |
565 { | |
566 if (__gthread_active_p ()) | |
567 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); | |
568 else | |
569 return 0; | |
570 } | |
571 | |
572 /* Wake up one thread waiting on this condition. */ | |
573 static inline int | |
574 __gthread_objc_condition_signal (objc_condition_t condition) | |
575 { | |
576 if (__gthread_active_p ()) | |
577 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); | |
578 else | |
579 return 0; | |
580 } | |
581 | |
582 #else /* _LIBOBJC */ | |
583 | |
584 static inline int | |
585 __gthread_once (__gthread_once_t *__once, void (*__func) (void)) | |
586 { | |
587 if (__gthread_active_p ()) | |
588 return __gthrw_(pthread_once) (__once, __func); | |
589 else | |
590 return -1; | |
591 } | |
592 | |
593 static inline int | |
594 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) | |
595 { | |
596 return __gthrw_(pthread_key_create) (__key, __dtor); | |
597 } | |
598 | |
599 static inline int | |
600 __gthread_key_delete (__gthread_key_t __key) | |
601 { | |
602 return __gthrw_(pthread_key_delete) (__key); | |
603 } | |
604 | |
605 static inline void * | |
606 __gthread_getspecific (__gthread_key_t __key) | |
607 { | |
608 return __gthrw_(pthread_getspecific) (__key); | |
609 } | |
610 | |
611 static inline int | |
612 __gthread_setspecific (__gthread_key_t __key, const void *__ptr) | |
613 { | |
614 return __gthrw_(pthread_setspecific) (__key, __ptr); | |
615 } | |
616 | |
617 static inline int | |
618 __gthread_mutex_destroy (__gthread_mutex_t *__mutex) | |
619 { | |
620 if (__gthread_active_p ()) | |
621 return __gthrw_(pthread_mutex_destroy) (__mutex); | |
622 else | |
623 return 0; | |
624 } | |
625 | |
626 static inline int | |
627 __gthread_mutex_lock (__gthread_mutex_t *__mutex) | |
628 { | |
629 if (__gthread_active_p ()) | |
630 return __gthrw_(pthread_mutex_lock) (__mutex); | |
631 else | |
632 return 0; | |
633 } | |
634 | |
635 static inline int | |
636 __gthread_mutex_trylock (__gthread_mutex_t *__mutex) | |
637 { | |
638 if (__gthread_active_p ()) | |
639 return __gthrw_(pthread_mutex_trylock) (__mutex); | |
640 else | |
641 return 0; | |
642 } | |
643 | |
644 static inline int | |
645 __gthread_mutex_unlock (__gthread_mutex_t *__mutex) | |
646 { | |
647 if (__gthread_active_p ()) | |
648 return __gthrw_(pthread_mutex_unlock) (__mutex); | |
649 else | |
650 return 0; | |
651 } | |
652 | |
653 static inline int | |
654 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) | |
655 { | |
656 __mutex->depth = 0; | |
657 __mutex->owner = (pthread_t) 0; | |
658 return __gthrw_(pthread_mutex_init) (&__mutex->actual, NULL); | |
659 } | |
660 | |
661 static inline int | |
662 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) | |
663 { | |
664 if (__gthread_active_p ()) | |
665 { | |
666 pthread_t __me = __gthrw_(pthread_self) (); | |
667 | |
668 if (__mutex->owner != __me) | |
669 { | |
670 __gthrw_(pthread_mutex_lock) (&__mutex->actual); | |
671 __mutex->owner = __me; | |
672 } | |
673 | |
674 __mutex->depth++; | |
675 } | |
676 return 0; | |
677 } | |
678 | |
679 static inline int | |
680 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) | |
681 { | |
682 if (__gthread_active_p ()) | |
683 { | |
684 pthread_t __me = __gthrw_(pthread_self) (); | |
685 | |
686 if (__mutex->owner != __me) | |
687 { | |
688 if (__gthrw_(pthread_mutex_trylock) (&__mutex->actual)) | |
689 return 1; | |
690 __mutex->owner = __me; | |
691 } | |
692 | |
693 __mutex->depth++; | |
694 } | |
695 return 0; | |
696 } | |
697 | |
698 static inline int | |
699 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) | |
700 { | |
701 if (__gthread_active_p ()) | |
702 { | |
703 if (--__mutex->depth == 0) | |
704 { | |
705 __mutex->owner = (pthread_t) 0; | |
706 __gthrw_(pthread_mutex_unlock) (&__mutex->actual); | |
707 } | |
708 } | |
709 return 0; | |
710 } | |
711 | |
712 static inline int | |
713 __gthread_cond_broadcast (__gthread_cond_t *__cond) | |
714 { | |
715 return __gthrw_(pthread_cond_broadcast) (__cond); | |
716 } | |
717 | |
718 static inline int | |
719 __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) | |
720 { | |
721 return __gthrw_(pthread_cond_wait) (__cond, __mutex); | |
722 } | |
723 | |
724 static inline int | |
725 __gthread_cond_wait_recursive (__gthread_cond_t *__cond, | |
726 __gthread_recursive_mutex_t *__mutex) | |
727 { | |
728 return __gthrw_(pthread_cond_wait) (__cond, &__mutex->actual); | |
729 } | |
730 | |
731 #endif /* _LIBOBJC */ | |
732 | |
733 #endif /* ! GCC_GTHR_POSIX_H */ |