1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997-2024 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #ifndef GCC_GTHR_DCE_H
27 #define GCC_GTHR_DCE_H
29 /* If _DCE_THREADS is not defined, then we're building the single
30 threaded version of the libraries and do not want to reference
31 anything related to pthreads or dce. */
33 #include "gthr-single.h"
35 /* DCE threads interface.
36 DCE threads are based on POSIX threads draft 4, and many things
37 have changed since then. */
39 /* Make sure CONST_CAST2 (original in system.h) is defined. */
42 #define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast<TOTYPE> (X))
44 #define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
52 typedef pthread_key_t __gthread_key_t
;
53 typedef pthread_once_t __gthread_once_t
;
54 typedef pthread_mutex_t __gthread_mutex_t
;
55 typedef pthread_mutex_t __gthread_recursive_mutex_t
;
57 #define __GTHREAD_ONCE_INIT pthread_once_init
59 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
60 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
62 #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
64 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
65 # define __gthrw(name) \
66 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
67 # define __gthrw_(name) __gthrw_ ## name
69 # define __gthrw(name)
70 # define __gthrw_(name) name
74 __gthrw(pthread_keycreate
)
75 __gthrw(pthread_getspecific
)
76 __gthrw(pthread_setspecific
)
77 __gthrw(pthread_create
)
78 __gthrw(pthread_mutex_init
)
79 __gthrw(pthread_mutex_destroy
)
80 __gthrw(pthread_mutex_lock
)
81 __gthrw(pthread_mutex_trylock
)
82 __gthrw(pthread_mutex_unlock
)
83 __gthrw(pthread_mutexattr_create
)
84 __gthrw(pthread_mutexattr_setkind_np
)
85 __gthrw(pthread_mutexattr_delete
)
89 __gthrw(pthread_cond_broadcast
)
90 __gthrw(pthread_cond_destroy
)
91 __gthrw(pthread_cond_init
)
92 __gthrw(pthread_cond_signal
)
93 __gthrw(pthread_cond_wait
)
96 #ifdef pthread_getunique_np
97 # define __gthrw_pthread_getunique_np pthread_getunique_np
99 __gthrw(pthread_getunique_np
)
100 # define __gthrw_pthread_getunique_np __gthrw_(pthread_getunique_np)
103 __gthrw(pthread_mutex_destroy
)
104 __gthrw(pthread_self
)
105 __gthrw(pthread_yield
)
108 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
111 __gthread_active_p (void)
113 static void *const __gthread_active_ptr
= (void *) &__gthrw_(pthread_create
);
114 return __gthread_active_ptr
!= 0;
117 #else /* not SUPPORTS_WEAK */
120 __gthread_active_p (void)
125 #endif /* SUPPORTS_WEAK */
129 /* Key structure for maintaining thread specific storage */
130 static pthread_key_t _objc_thread_storage
;
132 /* Thread local storage for a single thread */
133 static void *thread_local_storage
= NULL
;
135 /* Backend initialization functions */
137 /* Initialize the threads subsystem. */
139 __gthread_objc_init_thread_system (void)
141 if (__gthread_active_p ())
142 /* Initialize the thread storage key. */
143 return __gthrw_(pthread_keycreate
) (&_objc_thread_storage
, NULL
);
148 /* Close the threads subsystem. */
150 __gthread_objc_close_thread_system (void)
152 if (__gthread_active_p ())
158 /* Backend thread functions */
160 /* Create a new thread of execution. */
161 static inline objc_thread_t
162 __gthread_objc_thread_detach (void (*func
)(void *), void *arg
)
164 objc_thread_t thread_id
;
165 pthread_t new_thread_handle
;
167 if (!__gthread_active_p ())
170 if (!(__gthrw_(pthread_create
) (&new_thread_handle
, pthread_attr_default
,
171 (void *) func
, arg
)))
173 /* ??? May not work! (64bit) */
174 thread_id
= *(objc_thread_t
*) &new_thread_handle
;
175 pthread_detach (&new_thread_handle
); /* Fully detach thread. */
183 /* Set the current thread's priority. */
185 __gthread_objc_thread_set_priority (int priority
)
187 int sys_priority
= 0;
189 if (!__gthread_active_p ())
194 case OBJC_THREAD_INTERACTIVE_PRIORITY
:
195 sys_priority
= (PRI_FG_MIN_NP
+ PRI_FG_MAX_NP
) / 2;
198 case OBJC_THREAD_BACKGROUND_PRIORITY
:
199 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
201 case OBJC_THREAD_LOW_PRIORITY
:
202 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
206 /* Change the priority. */
207 if (pthread_setprio (__gthrw_(pthread_self
) (), sys_priority
) >= 0)
214 /* Return the current thread's priority. */
216 __gthread_objc_thread_get_priority (void)
220 if (__gthread_active_p ())
222 if ((sys_priority
= pthread_getprio (__gthrw_(pthread_self
) ())) >= 0)
224 if (sys_priority
>= PRI_FG_MIN_NP
225 && sys_priority
<= PRI_FG_MAX_NP
)
226 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
227 if (sys_priority
>= PRI_BG_MIN_NP
228 && sys_priority
<= PRI_BG_MAX_NP
)
229 return OBJC_THREAD_BACKGROUND_PRIORITY
;
230 return OBJC_THREAD_LOW_PRIORITY
;
237 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
240 /* Yield our process time to another thread. */
242 __gthread_objc_thread_yield (void)
244 if (__gthread_active_p ())
245 __gthrw_(pthread_yield
) ();
248 /* Terminate the current thread. */
250 __gthread_objc_thread_exit (void)
252 if (__gthread_active_p ())
253 /* exit the thread */
254 __gthrw_(pthread_exit
) (&__objc_thread_exit_status
);
256 /* Failed if we reached here */
260 /* Returns an integer value which uniquely describes a thread. */
261 static inline objc_thread_t
262 __gthread_objc_thread_id (void)
264 if (__gthread_active_p ())
266 pthread_t self
= __gthrw_(pthread_self
) ();
268 return (objc_thread_t
) __gthrw_pthread_getunique_np (&self
);
271 return (objc_thread_t
) 1;
274 /* Sets the thread's local storage pointer. */
276 __gthread_objc_thread_set_data (void *value
)
278 if (__gthread_active_p ())
279 return __gthrw_(pthread_setspecific
) (_objc_thread_storage
, value
);
282 thread_local_storage
= value
;
287 /* Returns the thread's local storage pointer. */
289 __gthread_objc_thread_get_data (void)
293 if (__gthread_active_p ())
295 if (!(__gthrw_(pthread_getspecific
) (_objc_thread_storage
, &value
)))
301 return thread_local_storage
;
304 /* Backend mutex functions */
306 /* Allocate a mutex. */
308 __gthread_objc_mutex_allocate (objc_mutex_t mutex
)
310 if (__gthread_active_p ())
312 mutex
->backend
= objc_malloc (sizeof (pthread_mutex_t
));
314 if (__gthrw_(pthread_mutex_init
) ((pthread_mutex_t
*) mutex
->backend
,
315 pthread_mutexattr_default
))
317 objc_free (mutex
->backend
);
318 mutex
->backend
= NULL
;
326 /* Deallocate a mutex. */
328 __gthread_objc_mutex_deallocate (objc_mutex_t mutex
)
330 if (__gthread_active_p ())
332 if (__gthrw_(pthread_mutex_destroy
) ((pthread_mutex_t
*) mutex
->backend
))
335 objc_free (mutex
->backend
);
336 mutex
->backend
= NULL
;
342 /* Grab a lock on a mutex. */
344 __gthread_objc_mutex_lock (objc_mutex_t mutex
)
346 if (__gthread_active_p ())
347 return __gthrw_(pthread_mutex_lock
) ((pthread_mutex_t
*) mutex
->backend
);
352 /* Try to grab a lock on a mutex. */
354 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
356 if (__gthread_active_p ()
357 && __gthrw_(pthread_mutex_trylock
) ((pthread_mutex_t
*) mutex
->backend
) != 1)
363 /* Unlock the mutex */
365 __gthread_objc_mutex_unlock (objc_mutex_t mutex
)
367 if (__gthread_active_p ())
368 return __gthrw_(pthread_mutex_unlock
) ((pthread_mutex_t
*) mutex
->backend
);
373 /* Backend condition mutex functions */
375 /* Allocate a condition. */
377 __gthread_objc_condition_allocate (objc_condition_t condition
378 __attribute__ ((__unused__
)))
380 if (__gthread_active_p ())
387 /* Deallocate a condition. */
389 __gthread_objc_condition_deallocate (objc_condition_t condition
390 __attribute__ ((__unused__
)))
392 if (__gthread_active_p ())
399 /* Wait on the condition */
401 __gthread_objc_condition_wait (objc_condition_t condition
402 __attribute__ ((__unused__
)),
403 objc_mutex_t mutex
__attribute__ ((__unused__
)))
405 if (__gthread_active_p ())
412 /* Wake up all threads waiting on this condition. */
414 __gthread_objc_condition_broadcast (objc_condition_t condition
415 __attribute__ ((__unused__
)))
417 if (__gthread_active_p ())
424 /* Wake up one thread waiting on this condition. */
426 __gthread_objc_condition_signal (objc_condition_t condition
427 __attribute__ ((__unused__
)))
429 if (__gthread_active_p ())
439 __gthread_once (__gthread_once_t
*__once
, void (*__func
) (void))
441 if (__gthread_active_p ())
442 return __gthrw_(pthread_once
) (__once
, __func
);
448 __gthread_key_create (__gthread_key_t
*__key
, void (*__dtor
) (void *))
450 return __gthrw_(pthread_keycreate
) (__key
, __dtor
);
454 __gthread_key_delete (__gthread_key_t __key
__attribute__ ((__unused__
)))
456 /* Operation is not supported. */
461 __gthread_getspecific (__gthread_key_t __key
)
464 if (__gthrw_(pthread_getspecific
) (__key
, &__ptr
) == 0)
471 __gthread_setspecific (__gthread_key_t __key
, const void *__ptr
)
473 return __gthrw_(pthread_setspecific
)
474 (__key
, CONST_CAST2(void *, const void *, __ptr
));
478 __gthread_mutex_init_function (__gthread_mutex_t
*__mutex
)
480 if (__gthread_active_p ())
481 __gthrw_(pthread_mutex_init
) (__mutex
, pthread_mutexattr_default
);
485 __gthread_mutex_destroy (__gthread_mutex_t
*__mutex
)
487 if (__gthread_active_p ())
488 return __gthrw_(pthread_mutex_destroy
) (__mutex
);
494 __gthread_mutex_lock (__gthread_mutex_t
*__mutex
)
496 if (__gthread_active_p ())
497 return __gthrw_(pthread_mutex_lock
) (__mutex
);
503 __gthread_mutex_trylock (__gthread_mutex_t
*__mutex
)
505 if (__gthread_active_p ())
506 return __gthrw_(pthread_mutex_trylock
) (__mutex
);
512 __gthread_mutex_unlock (__gthread_mutex_t
*__mutex
)
514 if (__gthread_active_p ())
515 return __gthrw_(pthread_mutex_unlock
) (__mutex
);
521 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t
*__mutex
)
523 if (__gthread_active_p ())
525 pthread_mutexattr_t __attr
;
528 __r
= __gthrw_(pthread_mutexattr_create
) (&__attr
);
530 __r
= __gthrw_(pthread_mutexattr_setkind_np
) (&__attr
,
533 __r
= __gthrw_(pthread_mutex_init
) (__mutex
, __attr
);
535 __r
= __gthrw_(pthread_mutexattr_delete
) (&__attr
);
542 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t
*__mutex
)
544 return __gthread_mutex_lock (__mutex
);
548 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t
*__mutex
)
550 return __gthread_mutex_trylock (__mutex
);
554 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t
*__mutex
)
556 return __gthread_mutex_unlock (__mutex
);
560 __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t
*__mutex
)
562 return __gthread_mutex_destroy (__mutex
);
565 #endif /* _LIBOBJC */
568 #endif /* ! GCC_GTHR_DCE_H */