OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / gthr-posix.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
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)
10 any later version.
11
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.
16
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.  */
21
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.  */
28
29 #ifndef __gthr_posix_h
30 #define __gthr_posix_h
31
32 /* POSIX threads specific definitions.
33    Easy, since the interface is just one-to-one mapping. */
34
35 #define __GTHREADS 1
36
37 #include <pthread.h>
38
39 typedef pthread_key_t __gthread_key_t;
40 typedef pthread_once_t __gthread_once_t;
41 typedef pthread_mutex_t __gthread_mutex_t;
42
43 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
44 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
45
46 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
47
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
54
55 #pragma weak pthread_mutex_lock 
56 #pragma weak pthread_mutex_trylock 
57 #pragma weak pthread_mutex_unlock 
58
59 #ifdef _LIBOBJC
60 /* Objective C. */
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
71 #endif
72
73 static void *__gthread_active_ptr = &pthread_create;
74
75 static inline int
76 __gthread_active_p (void)
77 {
78   return __gthread_active_ptr != 0;
79 }
80
81 #else /* not SUPPORTS_WEAK */
82
83 static inline int
84 __gthread_active_p (void)
85 {
86   return 1;
87 }
88
89 #endif /* SUPPORTS_WEAK */
90
91 #ifdef _LIBOBJC
92
93 /* Key structure for maintaining thread specific storage */
94 static pthread_key_t _objc_thread_storage;
95
96 /* Thread local storage for a single thread */
97 static void *thread_local_storage = NULL;
98
99 /* Backend initialization functions */
100
101 /* Initialize the threads subsystem. */
102 static inline int
103 __gthread_objc_init_thread_system(void)
104 {
105   if (__gthread_active_p ())
106     /* Initialize the thread storage key */
107     return pthread_key_create(&_objc_thread_storage, NULL);
108   else
109     return -1;
110 }
111
112 /* Close the threads subsystem. */
113 static inline int
114 __gthread_objc_close_thread_system(void)
115 {
116   if (__gthread_active_p ())
117     return 0;
118   else
119     return -1;
120 }
121
122 /* Backend thread functions */
123
124 /* Create a new thread of execution. */
125 static inline objc_thread_t
126 __gthread_objc_thread_detach(void (*func)(void *), void *arg)
127 {
128   objc_thread_t thread_id;
129   pthread_t new_thread_handle;
130
131   if (!__gthread_active_p ())
132     return NULL;
133  
134   if ( !(pthread_create(&new_thread_handle, NULL, (void *)func, arg)) )
135     thread_id = *(objc_thread_t *)&new_thread_handle;
136   else
137     thread_id = NULL;
138   
139   return thread_id;
140 }
141
142 /* Set the current thread's priority. */
143 static inline int
144 __gthread_objc_thread_set_priority(int priority)
145 {
146   /* Not implemented yet */
147   return -1;
148 }
149
150 /* Return the current thread's priority. */
151 static inline int
152 __gthread_objc_thread_get_priority(void)
153 {
154   if (__gthread_active_p ())
155     /* Not implemented yet */
156     return -1;
157   else
158     return OBJC_THREAD_INTERACTIVE_PRIORITY;
159 }
160
161 /* Yield our process time to another thread. */
162 static inline void
163 __gthread_objc_thread_yield(void)
164 {
165   if (__gthread_active_p ())
166     sched_yield();
167 }
168
169 /* Terminate the current thread. */
170 static inline int
171 __gthread_objc_thread_exit(void)
172 {
173   if (__gthread_active_p ())
174     /* exit the thread */
175     pthread_exit(&__objc_thread_exit_status);
176
177   /* Failed if we reached here */
178   return -1;
179 }
180
181 /* Returns an integer value which uniquely describes a thread. */
182 static inline objc_thread_t
183 __gthread_objc_thread_id(void)
184 {
185   if (__gthread_active_p ())
186     {
187       pthread_t self = pthread_self();
188
189       return *(objc_thread_t *)&self;
190     }
191   else
192     return (objc_thread_t)1;
193 }
194
195 /* Sets the thread's local storage pointer. */
196 static inline int
197 __gthread_objc_thread_set_data(void *value)
198 {
199   if (__gthread_active_p ())
200     return pthread_setspecific(_objc_thread_storage, value);
201   else
202     {
203       thread_local_storage = value;
204       return 0;
205     }
206 }
207
208 /* Returns the thread's local storage pointer. */
209 static inline void *
210 __gthread_objc_thread_get_data(void)
211 {
212   if (__gthread_active_p ())
213     return pthread_getspecific(_objc_thread_storage);
214   else
215     return thread_local_storage;
216 }
217
218 /* Backend mutex functions */
219
220 /* Allocate a mutex. */
221 static inline int
222 __gthread_objc_mutex_allocate(objc_mutex_t mutex)
223 {
224   if (__gthread_active_p ())
225     {
226       mutex->backend = objc_malloc(sizeof(pthread_mutex_t));
227
228       if (pthread_mutex_init((pthread_mutex_t *)mutex->backend, NULL))
229         {
230           objc_free(mutex->backend);
231           mutex->backend = NULL;
232           return -1;
233         }
234     }
235
236   return 0;
237 }
238
239 /* Deallocate a mutex. */
240 static inline int
241 __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
242 {
243   if (__gthread_active_p ())
244     {
245       int count;
246
247       /*
248        * Posix Threads specifically require that the thread be unlocked
249        * for pthread_mutex_destroy to work.
250        */
251
252       do
253         {
254           count = pthread_mutex_unlock((pthread_mutex_t *)mutex->backend);
255           if (count < 0)
256             return -1;
257         }
258       while (count);
259
260       if (pthread_mutex_destroy((pthread_mutex_t *)mutex->backend))
261         return -1;
262
263       objc_free(mutex->backend);
264       mutex->backend = NULL;
265     }
266   return 0;
267 }
268
269 /* Grab a lock on a mutex. */
270 static inline int
271 __gthread_objc_mutex_lock(objc_mutex_t mutex)
272 {
273   if (__gthread_active_p ())
274     return pthread_mutex_lock((pthread_mutex_t *)mutex->backend);
275   else
276     return 0;
277 }
278
279 /* Try to grab a lock on a mutex. */
280 static inline int
281 __gthread_objc_mutex_trylock(objc_mutex_t mutex)
282 {
283   if (__gthread_active_p ())
284     return pthread_mutex_trylock((pthread_mutex_t *)mutex->backend);
285   else
286     return 0;
287 }
288
289 /* Unlock the mutex */
290 static inline int
291 __gthread_objc_mutex_unlock(objc_mutex_t mutex)
292 {
293   if (__gthread_active_p ())
294     return pthread_mutex_unlock((pthread_mutex_t *)mutex->backend);
295   else
296     return 0;
297 }
298
299 /* Backend condition mutex functions */
300
301 /* Allocate a condition. */
302 static inline int
303 __gthread_objc_condition_allocate(objc_condition_t condition)
304 {
305   if (__gthread_active_p ())
306     {
307       condition->backend = objc_malloc(sizeof(pthread_cond_t));
308
309       if (pthread_cond_init((pthread_cond_t *)condition->backend, NULL))
310         {
311           objc_free(condition->backend);
312           condition->backend = NULL;
313           return -1;
314         }
315     }
316
317   return 0;
318 }
319
320 /* Deallocate a condition. */
321 static inline int
322 __gthread_objc_condition_deallocate(objc_condition_t condition)
323 {
324   if (__gthread_active_p ())
325     {
326       if (pthread_cond_destroy((pthread_cond_t *)condition->backend))
327         return -1;
328
329       objc_free(condition->backend);
330       condition->backend = NULL;
331     }
332   return 0;
333 }
334
335 /* Wait on the condition */
336 static inline int
337 __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
338 {
339   if (__gthread_active_p ())
340     return pthread_cond_wait((pthread_cond_t *)condition->backend,
341                            (pthread_mutex_t *)mutex->backend);
342   else
343     return 0;
344 }
345
346 /* Wake up all threads waiting on this condition. */
347 static inline int
348 __gthread_objc_condition_broadcast(objc_condition_t condition)
349 {
350   if (__gthread_active_p ())
351     return pthread_cond_broadcast((pthread_cond_t *)condition->backend);
352   else
353     return 0;
354 }
355
356 /* Wake up one thread waiting on this condition. */
357 static inline int
358 __gthread_objc_condition_signal(objc_condition_t condition)
359 {
360   if (__gthread_active_p ())
361     return pthread_cond_signal((pthread_cond_t *)condition->backend);
362   else
363     return 0;
364 }
365
366 #else /* _LIBOBJC */
367
368 static inline int
369 __gthread_once (__gthread_once_t *once, void (*func) (void))
370 {
371   if (__gthread_active_p ())
372     return pthread_once (once, func);
373   else
374     return -1;
375 }
376
377 static inline int
378 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
379 {
380   return pthread_key_create (key, dtor);
381 }
382
383 static inline int
384 __gthread_key_dtor (__gthread_key_t key, void *ptr)
385 {
386   /* Just reset the key value to zero. */
387   if (ptr)
388     return pthread_setspecific (key, 0);
389   else
390     return 0;
391 }
392
393 static inline int
394 __gthread_key_delete (__gthread_key_t key)
395 {
396   return pthread_key_delete (key);
397 }
398
399 static inline void *
400 __gthread_getspecific (__gthread_key_t key)
401 {
402   return pthread_getspecific (key);
403 }
404
405 static inline int
406 __gthread_setspecific (__gthread_key_t key, const void *ptr)
407 {
408   return pthread_setspecific (key, ptr);
409 }
410
411 static inline int
412 __gthread_mutex_lock (__gthread_mutex_t *mutex)
413 {
414   if (__gthread_active_p ())
415     return pthread_mutex_lock (mutex);
416   else
417     return 0;
418 }
419
420 static inline int
421 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
422 {
423   if (__gthread_active_p ())
424     return pthread_mutex_trylock (mutex);
425   else
426     return 0;
427 }
428
429 static inline int
430 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
431 {
432   if (__gthread_active_p ())
433     return pthread_mutex_unlock (mutex);
434   else
435     return 0;
436 }
437
438 #endif /* _LIBOBJC */
439
440 #endif /* not __gthr_posix_h */