gthr-dce.h revision 117395
1
2/* Compile this one with gcc.  */
3/* Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING.  If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-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 GCC_GTHR_DCE_H
30#define GCC_GTHR_DCE_H
31
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.  */
35#ifndef _DCE_THREADS
36#include "gthr-single.h"
37#else
38/* DCE threads interface.
39   DCE threads are based on POSIX threads draft 4, and many things
40   have changed since then.  */
41
42#define __GTHREADS 1
43
44#include <pthread.h>
45
46#ifdef __cplusplus
47#define UNUSED(x) x
48#else
49#define UNUSED(x) x __attribute__((unused))
50#endif
51
52typedef pthread_key_t __gthread_key_t;
53typedef pthread_once_t __gthread_once_t;
54typedef pthread_mutex_t __gthread_mutex_t;
55
56#define __GTHREAD_ONCE_INIT pthread_once_init
57
58#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
59
60#define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
61
62#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
63
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
75
76#ifdef _LIBOBJC
77/* Objective-C.  */
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
88#endif
89
90static inline int
91__gthread_active_p (void)
92{
93  static void *const __gthread_active_ptr = (void *) &pthread_create;
94  return __gthread_active_ptr != 0;
95}
96
97#else /* not SUPPORTS_WEAK */
98
99static inline int
100__gthread_active_p (void)
101{
102  return 1;
103}
104
105#endif /* SUPPORTS_WEAK */
106
107#ifdef _LIBOBJC
108
109/* Key structure for maintaining thread specific storage */
110static pthread_key_t _objc_thread_storage;
111
112/* Thread local storage for a single thread */
113static void *thread_local_storage = NULL;
114
115/* Backend initialization functions */
116
117/* Initialize the threads subsystem.  */
118static inline int
119__gthread_objc_init_thread_system (void)
120{
121  if (__gthread_active_p ())
122    /* Initialize the thread storage key */
123    return pthread_keycreate (&_objc_thread_storage, NULL);
124  else
125    return -1;
126}
127
128/* Close the threads subsystem.  */
129static inline int
130__gthread_objc_close_thread_system (void)
131{
132  if (__gthread_active_p ())
133    return 0;
134  else
135    return -1;
136}
137
138/* Backend thread functions */
139
140/* Create a new thread of execution.  */
141static inline objc_thread_t
142__gthread_objc_thread_detach (void (*func)(void *), void *arg)
143{
144  objc_thread_t thread_id;
145  pthread_t new_thread_handle;
146
147  if (!__gthread_active_p ())
148    return NULL;
149
150  if (!(pthread_create (&new_thread_handle, pthread_attr_default,
151			(void *) func, arg)))
152    {
153      /* ??? May not work! (64bit) */
154      thread_id = *(objc_thread_t *) &new_thread_handle;
155      pthread_detach (&new_thread_handle); /* Fully detach thread.  */
156    }
157  else
158    thread_id = NULL;
159
160  return thread_id;
161}
162
163/* Set the current thread's priority.  */
164static inline int
165__gthread_objc_thread_set_priority (int priority)
166{
167  int sys_priority = 0;
168
169  if (!__gthread_active_p ())
170    return -1;
171
172  switch (priority)
173    {
174    case OBJC_THREAD_INTERACTIVE_PRIORITY:
175      sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2;
176      break;
177    default:
178    case OBJC_THREAD_BACKGROUND_PRIORITY:
179      sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
180      break;
181    case OBJC_THREAD_LOW_PRIORITY:
182      sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
183      break;
184    }
185
186  /* Change the priority.  */
187  if (pthread_setprio (pthread_self (), sys_priority) >= 0)
188    return 0;
189  else
190    /* Failed */
191    return -1;
192}
193
194/* Return the current thread's priority.  */
195static inline int
196__gthread_objc_thread_get_priority (void)
197{
198  int sys_priority;
199
200  if (__gthread_active_p ())
201    {
202      if ((sys_priority = pthread_getprio (pthread_self ())) >= 0)
203	{
204	  if (sys_priority >= PRI_FG_MIN_NP
205	      && sys_priority <= PRI_FG_MAX_NP)
206	    return OBJC_THREAD_INTERACTIVE_PRIORITY;
207	  if (sys_priority >= PRI_BG_MIN_NP
208	      && sys_priority <= PRI_BG_MAX_NP)
209	    return OBJC_THREAD_BACKGROUND_PRIORITY;
210	  return OBJC_THREAD_LOW_PRIORITY;
211	}
212
213      /* Failed */
214      return -1;
215    }
216  else
217    return OBJC_THREAD_INTERACTIVE_PRIORITY;
218}
219
220/* Yield our process time to another thread.  */
221static inline void
222__gthread_objc_thread_yield (void)
223{
224  if (__gthread_active_p ())
225    pthread_yield ();
226}
227
228/* Terminate the current thread.  */
229static inline int
230__gthread_objc_thread_exit (void)
231{
232  if (__gthread_active_p ())
233    /* exit the thread */
234    pthread_exit (&__objc_thread_exit_status);
235
236  /* Failed if we reached here */
237  return -1;
238}
239
240/* Returns an integer value which uniquely describes a thread.  */
241static inline objc_thread_t
242__gthread_objc_thread_id (void)
243{
244  if (__gthread_active_p ())
245    {
246      pthread_t self = pthread_self ();
247
248      return (objc_thread_t) pthread_getunique_np (&self);
249    }
250  else
251    return (objc_thread_t) 1;
252}
253
254/* Sets the thread's local storage pointer.  */
255static inline int
256__gthread_objc_thread_set_data (void *value)
257{
258  if (__gthread_active_p ())
259    return pthread_setspecific (_objc_thread_storage, value);
260  else
261    {
262      thread_local_storage = value;
263      return 0;
264    }
265}
266
267/* Returns the thread's local storage pointer.  */
268static inline void *
269__gthread_objc_thread_get_data (void)
270{
271  void *value = NULL;
272
273  if (__gthread_active_p ())
274    {
275      if (!(pthread_getspecific (_objc_thread_storage, &value)))
276	return value;
277
278      return NULL;
279    }
280  else
281    return thread_local_storage;
282}
283
284/* Backend mutex functions */
285
286/* Allocate a mutex.  */
287static inline int
288__gthread_objc_mutex_allocate (objc_mutex_t mutex)
289{
290  if (__gthread_active_p ())
291    {
292      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
293
294      if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend,
295			      pthread_mutexattr_default))
296	{
297	  objc_free (mutex->backend);
298	  mutex->backend = NULL;
299	  return -1;
300	}
301    }
302
303  return 0;
304}
305
306/* Deallocate a mutex.  */
307static inline int
308__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
309{
310  if (__gthread_active_p ())
311    {
312      if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
313	return -1;
314
315      objc_free (mutex->backend);
316      mutex->backend = NULL;
317    }
318
319  return 0;
320}
321
322/* Grab a lock on a mutex.  */
323static inline int
324__gthread_objc_mutex_lock (objc_mutex_t mutex)
325{
326  if (__gthread_active_p ())
327    return pthread_mutex_lock ((pthread_mutex_t *) mutex->backend);
328  else
329    return 0;
330}
331
332/* Try to grab a lock on a mutex.  */
333static inline int
334__gthread_objc_mutex_trylock (objc_mutex_t mutex)
335{
336  if (__gthread_active_p ()
337      && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 1)
338    return -1;
339
340  return 0;
341}
342
343/* Unlock the mutex */
344static inline int
345__gthread_objc_mutex_unlock (objc_mutex_t mutex)
346{
347  if (__gthread_active_p ())
348    return pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
349  else
350    return 0;
351}
352
353/* Backend condition mutex functions */
354
355/* Allocate a condition.  */
356static inline int
357__gthread_objc_condition_allocate (objc_condition_t condition)
358{
359  if (__gthread_active_p ())
360    /* Unimplemented.  */
361    return -1;
362  else
363    return 0;
364}
365
366/* Deallocate a condition.  */
367static inline int
368__gthread_objc_condition_deallocate (objc_condition_t condition)
369{
370  if (__gthread_active_p ())
371    /* Unimplemented.  */
372    return -1;
373  else
374    return 0;
375}
376
377/* Wait on the condition */
378static inline int
379__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
380{
381  if (__gthread_active_p ())
382    /* Unimplemented.  */
383    return -1;
384  else
385    return 0;
386}
387
388/* Wake up all threads waiting on this condition.  */
389static inline int
390__gthread_objc_condition_broadcast (objc_condition_t condition)
391{
392  if (__gthread_active_p ())
393    /* Unimplemented.  */
394    return -1;
395  else
396    return 0;
397}
398
399/* Wake up one thread waiting on this condition.  */
400static inline int
401__gthread_objc_condition_signal (objc_condition_t condition)
402{
403  if (__gthread_active_p ())
404    /* Unimplemented.  */
405    return -1;
406  else
407    return 0;
408}
409
410#else /* _LIBOBJC */
411
412static inline int
413__gthread_once (__gthread_once_t *once, void (*func) (void))
414{
415  if (__gthread_active_p ())
416    return pthread_once (once, func);
417  else
418    return -1;
419}
420
421static inline int
422__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
423{
424  return pthread_keycreate (key, dtor);
425}
426
427static inline int
428__gthread_key_dtor (UNUSED (__gthread_key_t key), UNUSED (void *ptr))
429{
430  /* Nothing needed.  */
431  return 0;
432}
433
434static inline int
435__gthread_key_delete (UNUSED (__gthread_key_t key))
436{
437  /* Operation is not supported.  */
438  return -1;
439}
440
441static inline void *
442__gthread_getspecific (__gthread_key_t key)
443{
444  void *ptr;
445  if (pthread_getspecific (key, &ptr) == 0)
446    return ptr;
447  else
448    return 0;
449}
450
451static inline int
452__gthread_setspecific (__gthread_key_t key, const void *ptr)
453{
454  return pthread_setspecific (key, (void *) ptr);
455}
456
457static inline void
458__gthread_mutex_init_function (__gthread_mutex_t *mutex)
459{
460  if (__gthread_active_p ())
461    pthread_mutex_init (mutex, pthread_mutexattr_default);
462}
463
464static inline int
465__gthread_mutex_lock (__gthread_mutex_t *mutex)
466{
467  if (__gthread_active_p ())
468    return pthread_mutex_lock (mutex);
469  else
470    return 0;
471}
472
473static inline int
474__gthread_mutex_trylock (__gthread_mutex_t *mutex)
475{
476  if (__gthread_active_p ())
477    return pthread_mutex_trylock (mutex);
478  else
479    return 0;
480}
481
482static inline int
483__gthread_mutex_unlock (__gthread_mutex_t *mutex)
484{
485  if (__gthread_active_p ())
486    return pthread_mutex_unlock (mutex);
487  else
488    return 0;
489}
490
491#endif /* _LIBOBJC */
492
493#undef UNUSED
494
495#endif
496#endif /* ! GCC_GTHR_DCE_H */
497