1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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 __gthr_posix_h
30 #define __gthr_posix_h
32 /* POSIX threads specific definitions.
33 Easy, since the interface is just one-to-one mapping. */
39 typedef pthread_key_t __gthread_key_t;
40 typedef pthread_once_t __gthread_once_t;
41 typedef pthread_mutex_t __gthread_mutex_t;
43 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
44 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
46 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
48 #pragma weak pthread_once
49 #pragma weak pthread_key_create
50 #pragma weak pthread_key_delete
51 #pragma weak pthread_getspecific
52 #pragma weak pthread_setspecific
53 #pragma weak pthread_create
55 #pragma weak pthread_mutex_lock
56 #pragma weak pthread_mutex_trylock
57 #pragma weak pthread_mutex_unlock
61 #pragma weak pthread_cond_broadcast
62 #pragma weak pthread_cond_destroy
63 #pragma weak pthread_cond_init
64 #pragma weak pthread_cond_signal
65 #pragma weak pthread_cond_wait
66 #pragma weak pthread_exit
67 #pragma weak pthread_mutex_init
68 #pragma weak pthread_mutex_destroy
69 #pragma weak pthread_self
70 #pragma weak sched_yield
73 static void *__gthread_active_ptr = &pthread_create;
76 __gthread_active_p (void)
78 return __gthread_active_ptr != 0;
81 #else /* not SUPPORTS_WEAK */
84 __gthread_active_p (void)
89 #endif /* SUPPORTS_WEAK */
93 /* Key structure for maintaining thread specific storage */
94 static pthread_key_t _objc_thread_storage;
96 /* Thread local storage for a single thread */
97 static void *thread_local_storage = NULL;
99 /* Backend initialization functions */
101 /* Initialize the threads subsystem. */
103 __gthread_objc_init_thread_system(void)
105 if (__gthread_active_p ())
106 /* Initialize the thread storage key */
107 return pthread_key_create(&_objc_thread_storage, NULL);
112 /* Close the threads subsystem. */
114 __gthread_objc_close_thread_system(void)
116 if (__gthread_active_p ())
122 /* Backend thread functions */
124 /* Create a new thread of execution. */
125 static inline objc_thread_t
126 __gthread_objc_thread_detach(void (*func)(void *), void *arg)
128 objc_thread_t thread_id;
129 pthread_t new_thread_handle;
131 if (!__gthread_active_p ())
134 if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) )
135 thread_id = *(objc_thread_t *)&new_thread_handle;
142 /* Set the current thread's priority. */
144 __gthread_objc_thread_set_priority(int priority)
146 /* Not implemented yet */
150 /* Return the current thread's priority. */
152 __gthread_objc_thread_get_priority(void)
154 if (__gthread_active_p ())
155 /* Not implemented yet */
158 return OBJC_THREAD_INTERACTIVE_PRIORITY;
161 /* Yield our process time to another thread. */
163 __gthread_objc_thread_yield(void)
165 if (__gthread_active_p ())
169 /* Terminate the current thread. */
171 __gthread_objc_thread_exit(void)
173 if (__gthread_active_p ())
174 /* exit the thread */
175 pthread_exit(&__objc_thread_exit_status);
177 /* Failed if we reached here */
181 /* Returns an integer value which uniquely describes a thread. */
182 static inline objc_thread_t
183 __gthread_objc_thread_id(void)
185 if (__gthread_active_p ())
187 pthread_t self = pthread_self();
189 return *(objc_thread_t *)&self;
192 return (objc_thread_t)1;
195 /* Sets the thread's local storage pointer. */
197 __gthread_objc_thread_set_data(void *value)
199 if (__gthread_active_p ())
200 return pthread_setspecific(_objc_thread_storage, value);
203 thread_local_storage = value;
208 /* Returns the thread's local storage pointer. */
210 __gthread_objc_thread_get_data(void)
212 if (__gthread_active_p ())
213 return pthread_getspecific(_objc_thread_storage);
215 return thread_local_storage;
218 /* Backend mutex functions */
220 /* Allocate a mutex. */
222 __gthread_objc_mutex_allocate(objc_mutex_t mutex)
224 if (__gthread_active_p ())
226 mutex->backend = objc_malloc(sizeof(pthread_mutex_t));
228 if (pthread_mutex_init((pthread_mutex_t *)mutex->backend, NULL))
230 objc_free(mutex->backend);
231 mutex->backend = NULL;
239 /* Deallocate a mutex. */
241 __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
243 if (__gthread_active_p ())
248 * Posix Threads specifically require that the thread be unlocked
249 * for pthread_mutex_destroy to work.
254 count = pthread_mutex_unlock((pthread_mutex_t *)mutex->backend);
260 if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend))
263 objc_free(mutex->backend);
264 mutex->backend = NULL;
269 /* Grab a lock on a mutex. */
271 __gthread_objc_mutex_lock(objc_mutex_t mutex)
273 if (__gthread_active_p ())
274 return pthread_mutex_lock((pthread_mutex_t *)mutex->backend);
279 /* Try to grab a lock on a mutex. */
281 __gthread_objc_mutex_trylock(objc_mutex_t mutex)
283 if (__gthread_active_p ())
284 return pthread_mutex_trylock((pthread_mutex_t *)mutex->backend);
289 /* Unlock the mutex */
291 __gthread_objc_mutex_unlock(objc_mutex_t mutex)
293 if (__gthread_active_p ())
294 return pthread_mutex_unlock((pthread_mutex_t *)mutex->backend);
299 /* Backend condition mutex functions */
301 /* Allocate a condition. */
303 __gthread_objc_condition_allocate(objc_condition_t condition)
305 if (__gthread_active_p ())
307 condition->backend = objc_malloc(sizeof(pthread_cond_t));
309 if (pthread_cond_init((pthread_cond_t *)condition->backend, NULL))
311 objc_free(condition->backend);
312 condition->backend = NULL;
320 /* Deallocate a condition. */
322 __gthread_objc_condition_deallocate(objc_condition_t condition)
324 if (__gthread_active_p ())
326 if (pthread_cond_destroy((pthread_cond_t *)condition->backend))
329 objc_free(condition->backend);
330 condition->backend = NULL;
335 /* Wait on the condition */
337 __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
339 if (__gthread_active_p ())
340 return pthread_cond_wait((pthread_cond_t *)condition->backend,
341 (pthread_mutex_t *)mutex->backend);
346 /* Wake up all threads waiting on this condition. */
348 __gthread_objc_condition_broadcast(objc_condition_t condition)
350 if (__gthread_active_p ())
351 return pthread_cond_broadcast((pthread_cond_t *)condition->backend);
356 /* Wake up one thread waiting on this condition. */
358 __gthread_objc_condition_signal(objc_condition_t condition)
360 if (__gthread_active_p ())
361 return pthread_cond_signal((pthread_cond_t *)condition->backend);
369 __gthread_once (__gthread_once_t *once, void (*func) (void))
371 if (__gthread_active_p ())
372 return pthread_once (once, func);
378 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
380 return pthread_key_create (key, dtor);
384 __gthread_key_dtor (__gthread_key_t key, void *ptr)
386 /* Just reset the key value to zero. */
388 return pthread_setspecific (key, 0);
394 __gthread_key_delete (__gthread_key_t key)
396 return pthread_key_delete (key);
400 __gthread_getspecific (__gthread_key_t key)
402 return pthread_getspecific (key);
406 __gthread_setspecific (__gthread_key_t key, const void *ptr)
408 return pthread_setspecific (key, ptr);
412 __gthread_mutex_lock (__gthread_mutex_t *mutex)
414 if (__gthread_active_p ())
415 return pthread_mutex_lock (mutex);
421 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
423 if (__gthread_active_p ())
424 return pthread_mutex_trylock (mutex);
430 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
432 if (__gthread_active_p ())
433 return pthread_mutex_unlock (mutex);
438 #endif /* _LIBOBJC */
440 #endif /* not __gthr_posix_h */