1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2001, 2004, 2005
4 Free Software Foundation, Inc.
6 This file is part of GCC.
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 2, or (at your option) any later
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
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23 /* As a special exception, if you link this library with other files,
24 some of which are compiled with GCC, to produce an executable,
25 this library does not by itself cause the resulting executable
26 to be covered by the GNU General Public License.
27 This exception does not however invalidate any other reasons why
28 the executable file might be covered by the GNU General Public License. */
30 #ifndef GCC_GTHR_DCE_H
31 #define GCC_GTHR_DCE_H
33 /* If _DCE_THREADS is not defined, then we're building the single
34 threaded version of the libraries and do not want to reference
35 anything related to pthreads or dce. */
37 #include "gthr-single.h"
39 /* DCE threads interface.
40 DCE threads are based on POSIX threads draft 4, and many things
41 have changed since then. */
47 typedef pthread_key_t __gthread_key_t
;
48 typedef pthread_once_t __gthread_once_t
;
49 typedef pthread_mutex_t __gthread_mutex_t
;
50 typedef pthread_mutex_t __gthread_recursive_mutex_t
;
52 #define __GTHREAD_ONCE_INIT pthread_once_init
54 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
55 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
57 #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
59 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
60 # define __gthrw(name) \
61 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
62 # define __gthrw_(name) __gthrw_ ## name
64 # define __gthrw(name)
65 # define __gthrw_(name) name
69 __gthrw(pthread_keycreate
)
70 __gthrw(pthread_getspecific
)
71 __gthrw(pthread_setspecific
)
72 __gthrw(pthread_create
)
73 __gthrw(pthread_mutex_init
)
74 __gthrw(pthread_mutex_destroy
)
75 __gthrw(pthread_mutex_lock
)
76 __gthrw(pthread_mutex_trylock
)
77 __gthrw(pthread_mutex_unlock
)
78 __gthrw(pthread_mutexattr_create
)
79 __gthrw(pthread_mutexattr_setkind_np
)
80 __gthrw(pthread_mutexattr_delete
)
84 __gthrw(pthread_cond_broadcast
)
85 __gthrw(pthread_cond_destroy
)
86 __gthrw(pthread_cond_init
)
87 __gthrw(pthread_cond_signal
)
88 __gthrw(pthread_cond_wait
)
91 #ifdef pthread_getunique_np
92 # define __gthrw_pthread_getunique_np pthread_getunique_np
94 __gthrw(pthread_getunique_np
)
95 # define __gthrw_pthread_getunique_np __gthrw_(pthread_getunique_np)
98 __gthrw(pthread_mutex_destroy
)
100 __gthrw(pthread_yield
)
103 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
106 __gthread_active_p (void)
108 static void *const __gthread_active_ptr
= (void *) &__gthrw_(pthread_create
);
109 return __gthread_active_ptr
!= 0;
112 #else /* not SUPPORTS_WEAK */
115 __gthread_active_p (void)
120 #endif /* SUPPORTS_WEAK */
124 /* Key structure for maintaining thread specific storage */
125 static pthread_key_t _objc_thread_storage
;
127 /* Thread local storage for a single thread */
128 static void *thread_local_storage
= NULL
;
130 /* Backend initialization functions */
132 /* Initialize the threads subsystem. */
134 __gthread_objc_init_thread_system (void)
136 if (__gthread_active_p ())
137 /* Initialize the thread storage key. */
138 return __gthrw_(pthread_keycreate
) (&_objc_thread_storage
, NULL
);
143 /* Close the threads subsystem. */
145 __gthread_objc_close_thread_system (void)
147 if (__gthread_active_p ())
153 /* Backend thread functions */
155 /* Create a new thread of execution. */
156 static inline objc_thread_t
157 __gthread_objc_thread_detach (void (*func
)(void *), void *arg
)
159 objc_thread_t thread_id
;
160 pthread_t new_thread_handle
;
162 if (!__gthread_active_p ())
165 if (!(__gthrw_(pthread_create
) (&new_thread_handle
, pthread_attr_default
,
166 (void *) func
, arg
)))
168 /* ??? May not work! (64bit) */
169 thread_id
= *(objc_thread_t
*) &new_thread_handle
;
170 pthread_detach (&new_thread_handle
); /* Fully detach thread. */
178 /* Set the current thread's priority. */
180 __gthread_objc_thread_set_priority (int priority
)
182 int sys_priority
= 0;
184 if (!__gthread_active_p ())
189 case OBJC_THREAD_INTERACTIVE_PRIORITY
:
190 sys_priority
= (PRI_FG_MIN_NP
+ PRI_FG_MAX_NP
) / 2;
193 case OBJC_THREAD_BACKGROUND_PRIORITY
:
194 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
196 case OBJC_THREAD_LOW_PRIORITY
:
197 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
201 /* Change the priority. */
202 if (pthread_setprio (__gthrw_(pthread_self
) (), sys_priority
) >= 0)
209 /* Return the current thread's priority. */
211 __gthread_objc_thread_get_priority (void)
215 if (__gthread_active_p ())
217 if ((sys_priority
= pthread_getprio (__gthrw_(pthread_self
) ())) >= 0)
219 if (sys_priority
>= PRI_FG_MIN_NP
220 && sys_priority
<= PRI_FG_MAX_NP
)
221 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
222 if (sys_priority
>= PRI_BG_MIN_NP
223 && sys_priority
<= PRI_BG_MAX_NP
)
224 return OBJC_THREAD_BACKGROUND_PRIORITY
;
225 return OBJC_THREAD_LOW_PRIORITY
;
232 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
235 /* Yield our process time to another thread. */
237 __gthread_objc_thread_yield (void)
239 if (__gthread_active_p ())
240 __gthrw_(pthread_yield
) ();
243 /* Terminate the current thread. */
245 __gthread_objc_thread_exit (void)
247 if (__gthread_active_p ())
248 /* exit the thread */
249 __gthrw_(pthread_exit
) (&__objc_thread_exit_status
);
251 /* Failed if we reached here */
255 /* Returns an integer value which uniquely describes a thread. */
256 static inline objc_thread_t
257 __gthread_objc_thread_id (void)
259 if (__gthread_active_p ())
261 pthread_t self
= __gthrw_(pthread_self
) ();
263 return (objc_thread_t
) __gthrw_pthread_getunique_np (&self
);
266 return (objc_thread_t
) 1;
269 /* Sets the thread's local storage pointer. */
271 __gthread_objc_thread_set_data (void *value
)
273 if (__gthread_active_p ())
274 return __gthrw_(pthread_setspecific
) (_objc_thread_storage
, value
);
277 thread_local_storage
= value
;
282 /* Returns the thread's local storage pointer. */
284 __gthread_objc_thread_get_data (void)
288 if (__gthread_active_p ())
290 if (!(__gthrw_(pthread_getspecific
) (_objc_thread_storage
, &value
)))
296 return thread_local_storage
;
299 /* Backend mutex functions */
301 /* Allocate a mutex. */
303 __gthread_objc_mutex_allocate (objc_mutex_t mutex
)
305 if (__gthread_active_p ())
307 mutex
->backend
= objc_malloc (sizeof (pthread_mutex_t
));
309 if (__gthrw_(pthread_mutex_init
) ((pthread_mutex_t
*) mutex
->backend
,
310 pthread_mutexattr_default
))
312 objc_free (mutex
->backend
);
313 mutex
->backend
= NULL
;
321 /* Deallocate a mutex. */
323 __gthread_objc_mutex_deallocate (objc_mutex_t mutex
)
325 if (__gthread_active_p ())
327 if (__gthrw_(pthread_mutex_destroy
) ((pthread_mutex_t
*) mutex
->backend
))
330 objc_free (mutex
->backend
);
331 mutex
->backend
= NULL
;
337 /* Grab a lock on a mutex. */
339 __gthread_objc_mutex_lock (objc_mutex_t mutex
)
341 if (__gthread_active_p ())
342 return __gthrw_(pthread_mutex_lock
) ((pthread_mutex_t
*) mutex
->backend
);
347 /* Try to grab a lock on a mutex. */
349 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
351 if (__gthread_active_p ()
352 && __gthrw_(pthread_mutex_trylock
) ((pthread_mutex_t
*) mutex
->backend
) != 1)
358 /* Unlock the mutex */
360 __gthread_objc_mutex_unlock (objc_mutex_t mutex
)
362 if (__gthread_active_p ())
363 return __gthrw_(pthread_mutex_unlock
) ((pthread_mutex_t
*) mutex
->backend
);
368 /* Backend condition mutex functions */
370 /* Allocate a condition. */
372 __gthread_objc_condition_allocate (objc_condition_t condition
373 __attribute__ ((__unused__
)))
375 if (__gthread_active_p ())
382 /* Deallocate a condition. */
384 __gthread_objc_condition_deallocate (objc_condition_t condition
385 __attribute__ ((__unused__
)))
387 if (__gthread_active_p ())
394 /* Wait on the condition */
396 __gthread_objc_condition_wait (objc_condition_t condition
397 __attribute__ ((__unused__
)),
398 objc_mutex_t mutex
__attribute__ ((__unused__
)))
400 if (__gthread_active_p ())
407 /* Wake up all threads waiting on this condition. */
409 __gthread_objc_condition_broadcast (objc_condition_t condition
410 __attribute__ ((__unused__
)))
412 if (__gthread_active_p ())
419 /* Wake up one thread waiting on this condition. */
421 __gthread_objc_condition_signal (objc_condition_t condition
422 __attribute__ ((__unused__
)))
424 if (__gthread_active_p ())
434 __gthread_once (__gthread_once_t
*once
, void (*func
) (void))
436 if (__gthread_active_p ())
437 return __gthrw_(pthread_once
) (once
, func
);
443 __gthread_key_create (__gthread_key_t
*key
, void (*dtor
) (void *))
445 return __gthrw_(pthread_keycreate
) (key
, dtor
);
449 __gthread_key_delete (__gthread_key_t key
__attribute__ ((__unused__
)))
451 /* Operation is not supported. */
456 __gthread_getspecific (__gthread_key_t key
)
459 if (__gthrw_(pthread_getspecific
) (key
, &ptr
) == 0)
466 __gthread_setspecific (__gthread_key_t key
, const void *ptr
)
468 return __gthrw_(pthread_setspecific
) (key
, (void *) ptr
);
472 __gthread_mutex_init_function (__gthread_mutex_t
*mutex
)
474 if (__gthread_active_p ())
475 __gthrw_(pthread_mutex_init
) (mutex
, pthread_mutexattr_default
);
479 __gthread_mutx_destroy (__gthread_mutex_t
*mutex
)
481 if (__gthread_active_p ())
482 return __gthrw_(pthread_mutex_destroy
) (mutex
);
488 __gthread_mutex_lock (__gthread_mutex_t
*mutex
)
490 if (__gthread_active_p ())
491 return __gthrw_(pthread_mutex_lock
) (mutex
);
497 __gthread_mutex_trylock (__gthread_mutex_t
*mutex
)
499 if (__gthread_active_p ())
500 return __gthrw_(pthread_mutex_trylock
) (mutex
);
506 __gthread_mutex_unlock (__gthread_mutex_t
*mutex
)
508 if (__gthread_active_p ())
509 return __gthrw_(pthread_mutex_unlock
) (mutex
);
515 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t
*mutex
)
517 if (__gthread_active_p ())
519 pthread_mutexattr_t attr
;
522 r
= __gthrw_(pthread_mutexattr_create
) (&attr
);
524 r
= __gthrw_(pthread_mutexattr_setkind_np
) (&attr
, MUTEX_RECURSIVE_NP
);
526 r
= __gthrw_(pthread_mutex_init
) (mutex
, attr
);
528 r
= __gthrw_(pthread_mutexattr_delete
) (&attr
);
535 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t
*mutex
)
537 return __gthread_mutex_lock (mutex
);
541 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t
*mutex
)
543 return __gthread_mutex_trylock (mutex
);
547 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t
*mutex
)
549 return __gthread_mutex_unlock (mutex
);
552 #endif /* _LIBOBJC */
555 #endif /* ! GCC_GTHR_DCE_H */