2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2001 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 2, 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 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
29 #ifndef GCC_GTHR_DCE_H
30 #define GCC_GTHR_DCE_H
32 /* If _DCE_THREADS is not defined, then we're building the single
33 threaded version of the libraries and do not want to reference
34 anything related to pthreads or dce. */
36 #include "gthr-single.h"
38 /* DCE threads interface.
39 DCE threads are based on POSIX threads draft 4, and many things
40 have changed since then. */
49 #define UNUSED(x) x __attribute__((unused))
52 typedef pthread_key_t __gthread_key_t
;
53 typedef pthread_once_t __gthread_once_t
;
54 typedef pthread_mutex_t __gthread_mutex_t
;
56 #define __GTHREAD_ONCE_INIT pthread_once_init
58 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
60 #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
62 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
64 #pragma weak pthread_once
65 #pragma weak pthread_once_init
66 #pragma weak pthread_keycreate
67 #pragma weak pthread_key_delete
68 #pragma weak pthread_getspecific
69 #pragma weak pthread_setspecific
70 #pragma weak pthread_create
71 #pragma weak pthread_mutex_init
72 #pragma weak pthread_mutex_lock
73 #pragma weak pthread_mutex_trylock
74 #pragma weak pthread_mutex_unlock
78 #pragma weak pthread_cond_broadcast
79 #pragma weak pthread_cond_destroy
80 #pragma weak pthread_cond_init
81 #pragma weak pthread_cond_signal
82 #pragma weak pthread_cond_wait
83 #pragma weak pthread_exit
84 #pragma weak pthread_getunique_np
85 #pragma weak pthread_mutex_destroy
86 #pragma weak pthread_self
87 #pragma weak pthread_yield
90 static void *__gthread_active_ptr
= (void *) &pthread_create
;
93 __gthread_active_p (void)
95 return __gthread_active_ptr
!= 0;
98 #else /* not SUPPORTS_WEAK */
101 __gthread_active_p (void)
106 #endif /* SUPPORTS_WEAK */
110 /* Key structure for maintaining thread specific storage */
111 static pthread_key_t _objc_thread_storage
;
113 /* Thread local storage for a single thread */
114 static void *thread_local_storage
= NULL
;
116 /* Backend initialization functions */
118 /* Initialize the threads subsystem. */
120 __gthread_objc_init_thread_system(void)
122 if (__gthread_active_p ())
123 /* Initialize the thread storage key */
124 return pthread_keycreate (&_objc_thread_storage
, NULL
);
129 /* Close the threads subsystem. */
131 __gthread_objc_close_thread_system(void)
133 if (__gthread_active_p ())
139 /* Backend thread functions */
141 /* Create a new thread of execution. */
142 static inline objc_thread_t
143 __gthread_objc_thread_detach(void (*func
)(void *), void *arg
)
145 objc_thread_t thread_id
;
146 pthread_t new_thread_handle
;
148 if (!__gthread_active_p ())
151 if ( !(pthread_create(&new_thread_handle
, pthread_attr_default
,
152 (void *)func
, arg
)) )
154 /* ??? May not work! (64bit) */
155 thread_id
= *(objc_thread_t
*)&new_thread_handle
;
156 pthread_detach(&new_thread_handle
); /* Fully detach thread. */
164 /* Set the current thread's priority. */
166 __gthread_objc_thread_set_priority(int priority
)
168 int sys_priority
= 0;
170 if (!__gthread_active_p ())
175 case OBJC_THREAD_INTERACTIVE_PRIORITY
:
176 sys_priority
= (PRI_FG_MIN_NP
+ PRI_FG_MAX_NP
) / 2;
179 case OBJC_THREAD_BACKGROUND_PRIORITY
:
180 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
182 case OBJC_THREAD_LOW_PRIORITY
:
183 sys_priority
= (PRI_BG_MIN_NP
+ PRI_BG_MAX_NP
) / 2;
187 /* Change the priority. */
188 if (pthread_setprio(pthread_self(), sys_priority
) >= 0)
195 /* Return the current thread's priority. */
197 __gthread_objc_thread_get_priority(void)
201 if (__gthread_active_p ())
203 if ((sys_priority
= pthread_getprio(pthread_self())) >= 0)
205 if (sys_priority
>= PRI_FG_MIN_NP
206 && sys_priority
<= PRI_FG_MAX_NP
)
207 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
208 if (sys_priority
>= PRI_BG_MIN_NP
209 && sys_priority
<= PRI_BG_MAX_NP
)
210 return OBJC_THREAD_BACKGROUND_PRIORITY
;
211 return OBJC_THREAD_LOW_PRIORITY
;
218 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
221 /* Yield our process time to another thread. */
223 __gthread_objc_thread_yield(void)
225 if (__gthread_active_p ())
229 /* Terminate the current thread. */
231 __gthread_objc_thread_exit(void)
233 if (__gthread_active_p ())
234 /* exit the thread */
235 pthread_exit(&__objc_thread_exit_status
);
237 /* Failed if we reached here */
241 /* Returns an integer value which uniquely describes a thread. */
242 static inline objc_thread_t
243 __gthread_objc_thread_id(void)
245 if (__gthread_active_p ())
247 pthread_t self
= pthread_self();
249 return (objc_thread_t
) pthread_getunique_np (&self
);
252 return (objc_thread_t
)1;
255 /* Sets the thread's local storage pointer. */
257 __gthread_objc_thread_set_data(void *value
)
259 if (__gthread_active_p ())
260 return pthread_setspecific(_objc_thread_storage
, value
);
263 thread_local_storage
= value
;
268 /* Returns the thread's local storage pointer. */
270 __gthread_objc_thread_get_data(void)
274 if (__gthread_active_p ())
276 if ( !(pthread_getspecific(_objc_thread_storage
, &value
)) )
282 return thread_local_storage
;
285 /* Backend mutex functions */
287 /* Allocate a mutex. */
289 __gthread_objc_mutex_allocate(objc_mutex_t mutex
)
291 if (__gthread_active_p ())
293 mutex
->backend
= objc_malloc(sizeof(pthread_mutex_t
));
295 if (pthread_mutex_init((pthread_mutex_t
*)mutex
->backend
,
296 pthread_mutexattr_default
))
298 objc_free(mutex
->backend
);
299 mutex
->backend
= NULL
;
307 /* Deallocate a mutex. */
309 __gthread_objc_mutex_deallocate(objc_mutex_t mutex
)
311 if (__gthread_active_p ())
313 if (pthread_mutex_destroy((pthread_mutex_t
*)mutex
->backend
))
316 objc_free(mutex
->backend
);
317 mutex
->backend
= NULL
;
323 /* Grab a lock on a mutex. */
325 __gthread_objc_mutex_lock(objc_mutex_t mutex
)
327 if (__gthread_active_p ())
328 return pthread_mutex_lock((pthread_mutex_t
*)mutex
->backend
);
333 /* Try to grab a lock on a mutex. */
335 __gthread_objc_mutex_trylock(objc_mutex_t mutex
)
337 if (__gthread_active_p ()
338 && pthread_mutex_trylock((pthread_mutex_t
*)mutex
->backend
) != 1)
344 /* Unlock the mutex */
346 __gthread_objc_mutex_unlock(objc_mutex_t mutex
)
348 if (__gthread_active_p ())
349 return pthread_mutex_unlock((pthread_mutex_t
*)mutex
->backend
);
354 /* Backend condition mutex functions */
356 /* Allocate a condition. */
358 __gthread_objc_condition_allocate(objc_condition_t condition
)
360 if (__gthread_active_p ())
367 /* Deallocate a condition. */
369 __gthread_objc_condition_deallocate(objc_condition_t condition
)
371 if (__gthread_active_p ())
378 /* Wait on the condition */
380 __gthread_objc_condition_wait(objc_condition_t condition
, objc_mutex_t mutex
)
382 if (__gthread_active_p ())
389 /* Wake up all threads waiting on this condition. */
391 __gthread_objc_condition_broadcast(objc_condition_t condition
)
393 if (__gthread_active_p ())
400 /* Wake up one thread waiting on this condition. */
402 __gthread_objc_condition_signal(objc_condition_t condition
)
404 if (__gthread_active_p ())
414 __gthread_once (__gthread_once_t
*once
, void (*func
) (void))
416 if (__gthread_active_p ())
417 return pthread_once (once
, func
);
423 __gthread_key_create (__gthread_key_t
*key
, void (*dtor
) (void *))
425 return pthread_keycreate (key
, dtor
);
429 __gthread_key_dtor (UNUSED (__gthread_key_t key
), UNUSED (void *ptr
))
431 /* Nothing needed. */
436 __gthread_key_delete (UNUSED (__gthread_key_t key
))
438 /* Operation is not supported. */
443 __gthread_getspecific (__gthread_key_t key
)
446 if (pthread_getspecific (key
, &ptr
) == 0)
453 __gthread_setspecific (__gthread_key_t key
, const void *ptr
)
455 return pthread_setspecific (key
, (void *) ptr
);
459 __gthread_mutex_init_function (__gthread_mutex_t
*mutex
)
461 if (__gthread_active_p ())
462 pthread_mutex_init (mutex
, pthread_mutexattr_default
);
466 __gthread_mutex_lock (__gthread_mutex_t
*mutex
)
468 if (__gthread_active_p ())
469 return pthread_mutex_lock (mutex
);
475 __gthread_mutex_trylock (__gthread_mutex_t
*mutex
)
477 if (__gthread_active_p ())
478 return pthread_mutex_trylock (mutex
);
484 __gthread_mutex_unlock (__gthread_mutex_t
*mutex
)
486 if (__gthread_active_p ())
487 return pthread_mutex_unlock (mutex
);
492 #endif /* _LIBOBJC */
497 #endif /* ! GCC_GTHR_DCE_H */