1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2001, 2004, 2005, 2008, 2009
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 3, 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 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.
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/>. */
27 #ifndef GCC_GTHR_DCE_H
28 #define GCC_GTHR_DCE_H
30 /* If _DCE_THREADS is not defined, then we're building the single
31 threaded version of the libraries and do not want to reference
32 anything related to pthreads or dce. */
34 #include "gthr-single.h"
36 /* DCE threads interface.
37 DCE threads are based on POSIX threads draft 4, and many things
38 have changed since then. */
44 typedef pthread_key_t __gthread_key_t
;
45 typedef pthread_once_t __gthread_once_t
;
46 typedef pthread_mutex_t __gthread_mutex_t
;
47 typedef pthread_mutex_t __gthread_recursive_mutex_t
;
49 #define __GTHREAD_ONCE_INIT pthread_once_init
51 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
52 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
54 #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
56 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
57 # define __gthrw(name) \
58 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
59 # define __gthrw_(name) __gthrw_ ## name
61 # define __gthrw(name)
62 # define __gthrw_(name) name
66 __gthrw(pthread_keycreate
)
67 __gthrw(pthread_getspecific
)
68 __gthrw(pthread_setspecific
)
69 __gthrw(pthread_create
)
70 __gthrw(pthread_mutex_init
)
71 __gthrw(pthread_mutex_destroy
)
72 __gthrw(pthread_mutex_lock
)
73 __gthrw(pthread_mutex_trylock
)
74 __gthrw(pthread_mutex_unlock
)
75 __gthrw(pthread_mutexattr_create
)
76 __gthrw(pthread_mutexattr_setkind_np
)
77 __gthrw(pthread_mutexattr_delete
)
81 __gthrw(pthread_cond_broadcast
)
82 __gthrw(pthread_cond_destroy
)
83 __gthrw(pthread_cond_init
)
84 __gthrw(pthread_cond_signal
)
85 __gthrw(pthread_cond_wait
)
88 #ifdef pthread_getunique_np
89 # define __gthrw_pthread_getunique_np pthread_getunique_np
91 __gthrw(pthread_getunique_np
)
92 # define __gthrw_pthread_getunique_np __gthrw_(pthread_getunique_np)
95 __gthrw(pthread_mutex_destroy
)
97 __gthrw(pthread_yield
)
100 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
103 __gthread_active_p (void)
105 static void *const __gthread_active_ptr
= (void *) &__gthrw_(pthread_create
);
106 return __gthread_active_ptr
!= 0;
109 #else /* not SUPPORTS_WEAK */
112 __gthread_active_p (void)
117 #endif /* SUPPORTS_WEAK */
121 /* Key structure for maintaining thread specific storage */
122 static pthread_key_t _objc_thread_storage
;
124 /* Thread local storage for a single thread */
125 static void *thread_local_storage
= NULL
;
127 /* Backend initialization functions */
129 /* Initialize the threads subsystem. */
131 __gthread_objc_init_thread_system (void)
133 if (__gthread_active_p ())
134 /* Initialize the thread storage key. */
135 return __gthrw_(pthread_keycreate
) (&_objc_thread_storage
, NULL
);
140 /* Close the threads subsystem. */
142 __gthread_objc_close_thread_system (void)
144 if (__gthread_active_p ())
150 /* Backend thread functions */
152 /* Create a new thread of execution. */
153 static inline objc_thread_t
154 __gthread_objc_thread_detach (void (*func
)(void *), void *arg
)
156 objc_thread_t thread_id
;
157 pthread_t new_thread_handle
;
159 if (!__gthread_active_p ())
162 if (!(__gthrw_(pthread_create
) (&new_thread_handle
, pthread_attr_default
,
163 (void *) func
, arg
)))
165 /* ??? May not work! (64bit) */
166 thread_id
= *(objc_thread_t
*) &new_thread_handle
;
167 pthread_detach (&new_thread_handle
); /* Fully detach thread. */
175 /* Set the current thread's priority. */
177 __gthread_objc_thread_set_priority (int priority
)
179 int sys_priority
= 0;
181 if (!__gthread_active_p ())
186 case OBJC_THREAD_INTERACTIVE_PRIORITY
:
187 sys_priority
= (PRI_FG_MIN_NP
+ PRI_FG_MAX_NP
) / 2;
190 case OBJC_THREAD_BACKGROUND_PRIORITY
:
191 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
193 case OBJC_THREAD_LOW_PRIORITY
:
194 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
198 /* Change the priority. */
199 if (pthread_setprio (__gthrw_(pthread_self
) (), sys_priority
) >= 0)
206 /* Return the current thread's priority. */
208 __gthread_objc_thread_get_priority (void)
212 if (__gthread_active_p ())
214 if ((sys_priority
= pthread_getprio (__gthrw_(pthread_self
) ())) >= 0)
216 if (sys_priority
>= PRI_FG_MIN_NP
217 && sys_priority
<= PRI_FG_MAX_NP
)
218 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
219 if (sys_priority
>= PRI_BG_MIN_NP
220 && sys_priority
<= PRI_BG_MAX_NP
)
221 return OBJC_THREAD_BACKGROUND_PRIORITY
;
222 return OBJC_THREAD_LOW_PRIORITY
;
229 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
232 /* Yield our process time to another thread. */
234 __gthread_objc_thread_yield (void)
236 if (__gthread_active_p ())
237 __gthrw_(pthread_yield
) ();
240 /* Terminate the current thread. */
242 __gthread_objc_thread_exit (void)
244 if (__gthread_active_p ())
245 /* exit the thread */
246 __gthrw_(pthread_exit
) (&__objc_thread_exit_status
);
248 /* Failed if we reached here */
252 /* Returns an integer value which uniquely describes a thread. */
253 static inline objc_thread_t
254 __gthread_objc_thread_id (void)
256 if (__gthread_active_p ())
258 pthread_t self
= __gthrw_(pthread_self
) ();
260 return (objc_thread_t
) __gthrw_pthread_getunique_np (&self
);
263 return (objc_thread_t
) 1;
266 /* Sets the thread's local storage pointer. */
268 __gthread_objc_thread_set_data (void *value
)
270 if (__gthread_active_p ())
271 return __gthrw_(pthread_setspecific
) (_objc_thread_storage
, value
);
274 thread_local_storage
= value
;
279 /* Returns the thread's local storage pointer. */
281 __gthread_objc_thread_get_data (void)
285 if (__gthread_active_p ())
287 if (!(__gthrw_(pthread_getspecific
) (_objc_thread_storage
, &value
)))
293 return thread_local_storage
;
296 /* Backend mutex functions */
298 /* Allocate a mutex. */
300 __gthread_objc_mutex_allocate (objc_mutex_t mutex
)
302 if (__gthread_active_p ())
304 mutex
->backend
= objc_malloc (sizeof (pthread_mutex_t
));
306 if (__gthrw_(pthread_mutex_init
) ((pthread_mutex_t
*) mutex
->backend
,
307 pthread_mutexattr_default
))
309 objc_free (mutex
->backend
);
310 mutex
->backend
= NULL
;
318 /* Deallocate a mutex. */
320 __gthread_objc_mutex_deallocate (objc_mutex_t mutex
)
322 if (__gthread_active_p ())
324 if (__gthrw_(pthread_mutex_destroy
) ((pthread_mutex_t
*) mutex
->backend
))
327 objc_free (mutex
->backend
);
328 mutex
->backend
= NULL
;
334 /* Grab a lock on a mutex. */
336 __gthread_objc_mutex_lock (objc_mutex_t mutex
)
338 if (__gthread_active_p ())
339 return __gthrw_(pthread_mutex_lock
) ((pthread_mutex_t
*) mutex
->backend
);
344 /* Try to grab a lock on a mutex. */
346 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
348 if (__gthread_active_p ()
349 && __gthrw_(pthread_mutex_trylock
) ((pthread_mutex_t
*) mutex
->backend
) != 1)
355 /* Unlock the mutex */
357 __gthread_objc_mutex_unlock (objc_mutex_t mutex
)
359 if (__gthread_active_p ())
360 return __gthrw_(pthread_mutex_unlock
) ((pthread_mutex_t
*) mutex
->backend
);
365 /* Backend condition mutex functions */
367 /* Allocate a condition. */
369 __gthread_objc_condition_allocate (objc_condition_t condition
370 __attribute__ ((__unused__
)))
372 if (__gthread_active_p ())
379 /* Deallocate a condition. */
381 __gthread_objc_condition_deallocate (objc_condition_t condition
382 __attribute__ ((__unused__
)))
384 if (__gthread_active_p ())
391 /* Wait on the condition */
393 __gthread_objc_condition_wait (objc_condition_t condition
394 __attribute__ ((__unused__
)),
395 objc_mutex_t mutex
__attribute__ ((__unused__
)))
397 if (__gthread_active_p ())
404 /* Wake up all threads waiting on this condition. */
406 __gthread_objc_condition_broadcast (objc_condition_t condition
407 __attribute__ ((__unused__
)))
409 if (__gthread_active_p ())
416 /* Wake up one thread waiting on this condition. */
418 __gthread_objc_condition_signal (objc_condition_t condition
419 __attribute__ ((__unused__
)))
421 if (__gthread_active_p ())
431 __gthread_once (__gthread_once_t
*__once
, void (*__func
) (void))
433 if (__gthread_active_p ())
434 return __gthrw_(pthread_once
) (__once
, __func
);
440 __gthread_key_create (__gthread_key_t
*__key
, void (*__dtor
) (void *))
442 return __gthrw_(pthread_keycreate
) (__key
, __dtor
);
446 __gthread_key_delete (__gthread_key_t __key
__attribute__ ((__unused__
)))
448 /* Operation is not supported. */
453 __gthread_getspecific (__gthread_key_t __key
)
456 if (__gthrw_(pthread_getspecific
) (__key
, &__ptr
) == 0)
463 __gthread_setspecific (__gthread_key_t __key
, const void *__ptr
)
465 return __gthrw_(pthread_setspecific
) (__key
, (void *) __ptr
);
469 __gthread_mutex_init_function (__gthread_mutex_t
*__mutex
)
471 if (__gthread_active_p ())
472 __gthrw_(pthread_mutex_init
) (__mutex
, pthread_mutexattr_default
);
476 __gthread_mutx_destroy (__gthread_mutex_t
*__mutex
)
478 if (__gthread_active_p ())
479 return __gthrw_(pthread_mutex_destroy
) (__mutex
);
485 __gthread_mutex_lock (__gthread_mutex_t
*__mutex
)
487 if (__gthread_active_p ())
488 return __gthrw_(pthread_mutex_lock
) (__mutex
);
494 __gthread_mutex_trylock (__gthread_mutex_t
*__mutex
)
496 if (__gthread_active_p ())
497 return __gthrw_(pthread_mutex_trylock
) (__mutex
);
503 __gthread_mutex_unlock (__gthread_mutex_t
*__mutex
)
505 if (__gthread_active_p ())
506 return __gthrw_(pthread_mutex_unlock
) (__mutex
);
512 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t
*__mutex
)
514 if (__gthread_active_p ())
516 pthread_mutexattr_t __attr
;
519 __r
= __gthrw_(pthread_mutexattr_create
) (&__attr
);
521 __r
= __gthrw_(pthread_mutexattr_setkind_np
) (&__attr
,
524 __r
= __gthrw_(pthread_mutex_init
) (__mutex
, __attr
);
526 __r
= __gthrw_(pthread_mutexattr_delete
) (&__attr
);
533 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t
*__mutex
)
535 return __gthread_mutex_lock (__mutex
);
539 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t
*__mutex
)
541 return __gthread_mutex_trylock (__mutex
);
545 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t
*__mutex
)
547 return __gthread_mutex_unlock (__mutex
);
550 #endif /* _LIBOBJC */
553 #endif /* ! GCC_GTHR_DCE_H */