]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/gcc/gthr-posix.h
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / gcc / gthr-posix.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA.  */
22
23 /* As a special exception, if you link this library with other files,
24    some of which are compiled with GCC, to produce an executable,
25    this library does not by itself cause the resulting executable
26    to be covered by the GNU General Public License.
27    This exception does not however invalidate any other reasons why
28    the executable file might be covered by the GNU General Public License.  */
29
30 #ifndef GCC_GTHR_POSIX_H
31 #define GCC_GTHR_POSIX_H
32
33 /* POSIX threads specific definitions.
34    Easy, since the interface is just one-to-one mapping.  */
35
36 #define __GTHREADS 1
37
38 /* Some implementations of <pthread.h> require this to be defined.  */
39 #if !defined(_REENTRANT) && defined(__osf__)
40 #define _REENTRANT 1
41 #endif
42
43 #include <pthread.h>
44 #include <unistd.h>
45
46 typedef pthread_key_t __gthread_key_t;
47 typedef pthread_once_t __gthread_once_t;
48 typedef pthread_mutex_t __gthread_mutex_t;
49 typedef pthread_mutex_t __gthread_recursive_mutex_t;
50
51 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
52 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
53 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
54 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
55 #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
56 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
57 #else
58 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
59 #endif
60
61 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
62 # ifndef __gthrw_pragma
63 #  define __gthrw_pragma(pragma)
64 # endif
65 # define __gthrw2(name,name2,type) \
66   static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
67   __gthrw_pragma(weak type)
68 # define __gthrw_(name) __gthrw_ ## name
69 #else
70 # define __gthrw2(name,name2,type)
71 # define __gthrw_(name) name
72 #endif
73
74 /* Typically, __gthrw_foo is a weak reference to symbol foo.  */
75 #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
76
77 /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
78    map a subset of the POSIX pthread API to mangled versions of their
79    names.  */
80 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
81 #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
82 __gthrw3(pthread_once)
83 __gthrw3(pthread_getspecific)
84 __gthrw3(pthread_setspecific)
85 __gthrw3(pthread_create)
86 __gthrw3(pthread_cancel)
87 __gthrw3(pthread_mutex_lock)
88 __gthrw3(pthread_mutex_trylock)
89 __gthrw3(pthread_mutex_unlock)
90 __gthrw3(pthread_mutex_init)
91 #else
92 __gthrw(pthread_once)
93 __gthrw(pthread_getspecific)
94 __gthrw(pthread_setspecific)
95 __gthrw(pthread_create)
96 __gthrw(pthread_cancel)
97 __gthrw(pthread_mutex_lock)
98 __gthrw(pthread_mutex_trylock)
99 __gthrw(pthread_mutex_unlock)
100 __gthrw(pthread_mutex_init)
101 #endif
102
103 __gthrw(pthread_key_create)
104 __gthrw(pthread_key_delete)
105 __gthrw(pthread_mutexattr_init)
106 __gthrw(pthread_mutexattr_settype)
107 __gthrw(pthread_mutexattr_destroy)
108
109
110 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
111 /* Objective-C.  */
112 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
113 __gthrw3(pthread_cond_broadcast)
114 __gthrw3(pthread_cond_destroy)
115 __gthrw3(pthread_cond_init)
116 __gthrw3(pthread_cond_signal)
117 __gthrw3(pthread_cond_wait)
118 __gthrw3(pthread_exit)
119 __gthrw3(pthread_mutex_destroy)
120 __gthrw3(pthread_self)
121 #else
122 __gthrw(pthread_cond_broadcast)
123 __gthrw(pthread_cond_destroy)
124 __gthrw(pthread_cond_init)
125 __gthrw(pthread_cond_signal)
126 __gthrw(pthread_cond_wait)
127 __gthrw(pthread_exit)
128 __gthrw(pthread_mutex_destroy)
129 __gthrw(pthread_self)
130 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
131 #ifdef _POSIX_PRIORITY_SCHEDULING
132 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
133 __gthrw(sched_get_priority_max)
134 __gthrw(sched_get_priority_min)
135 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
136 #endif /* _POSIX_PRIORITY_SCHEDULING */
137 __gthrw(sched_yield)
138 __gthrw(pthread_attr_destroy)
139 __gthrw(pthread_attr_init)
140 __gthrw(pthread_attr_setdetachstate)
141 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
142 __gthrw(pthread_getschedparam)
143 __gthrw(pthread_setschedparam)
144 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
145 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
146
147 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
148
149 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
150    -pthreads is not specified.  The functions are dummies and most return an
151    error value.  However pthread_once returns 0 without invoking the routine
152    it is passed so we cannot pretend that the interface is active if -pthreads
153    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
154    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
155    working interface is always exposed.  On FreeBSD 6 and later, libc also
156    exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
157    to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
158    which means the alternate __gthread_active_p below cannot be used there.  */
159
160 #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
161
162 static volatile int __gthread_active = -1;
163
164 static void
165 __gthread_trigger (void)
166 {
167   __gthread_active = 1;
168 }
169
170 static inline int
171 __gthread_active_p (void)
172 {
173   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
174   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
175
176   /* Avoid reading __gthread_active twice on the main code path.  */
177   int __gthread_active_latest_value = __gthread_active;
178
179   /* This test is not protected to avoid taking a lock on the main code
180      path so every update of __gthread_active in a threaded program must
181      be atomic with regard to the result of the test.  */
182   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
183     {
184       if (__gthrw_(pthread_once))
185         {
186           /* If this really is a threaded program, then we must ensure that
187              __gthread_active has been set to 1 before exiting this block.  */
188           __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
189           __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
190           __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
191         }
192
193       /* Make sure we'll never enter this block again.  */
194       if (__gthread_active < 0)
195         __gthread_active = 0;
196
197       __gthread_active_latest_value = __gthread_active;
198     }
199
200   return __gthread_active_latest_value != 0;
201 }
202
203 #else /* neither FreeBSD nor Solaris */
204
205 static inline int
206 __gthread_active_p (void)
207 {
208   static void *const __gthread_active_ptr 
209     = __extension__ (void *) &__gthrw_(pthread_cancel);
210   return __gthread_active_ptr != 0;
211 }
212
213 #endif /* FreeBSD or Solaris */
214
215 #else /* not SUPPORTS_WEAK */
216
217 static inline int
218 __gthread_active_p (void)
219 {
220   return 1;
221 }
222
223 #endif /* SUPPORTS_WEAK */
224
225 #ifdef _LIBOBJC
226
227 /* This is the config.h file in libobjc/ */
228 #include <config.h>
229
230 #ifdef HAVE_SCHED_H
231 # include <sched.h>
232 #endif
233
234 /* Key structure for maintaining thread specific storage */
235 static pthread_key_t _objc_thread_storage;
236 static pthread_attr_t _objc_thread_attribs;
237
238 /* Thread local storage for a single thread */
239 static void *thread_local_storage = NULL;
240
241 /* Backend initialization functions */
242
243 /* Initialize the threads subsystem.  */
244 static inline int
245 __gthread_objc_init_thread_system (void)
246 {
247   if (__gthread_active_p ())
248     {
249       /* Initialize the thread storage key.  */
250       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
251         {
252           /* The normal default detach state for threads is
253            * PTHREAD_CREATE_JOINABLE which causes threads to not die
254            * when you think they should.  */
255           if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
256               && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
257                                               PTHREAD_CREATE_DETACHED) == 0)
258             return 0;
259         }
260     }
261
262   return -1;
263 }
264
265 /* Close the threads subsystem.  */
266 static inline int
267 __gthread_objc_close_thread_system (void)
268 {
269   if (__gthread_active_p ()
270       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
271       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
272     return 0;
273
274   return -1;
275 }
276
277 /* Backend thread functions */
278
279 /* Create a new thread of execution.  */
280 static inline objc_thread_t
281 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
282 {
283   objc_thread_t thread_id;
284   pthread_t new_thread_handle;
285
286   if (!__gthread_active_p ())
287     return NULL;
288
289   if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
290     thread_id = (objc_thread_t) new_thread_handle;
291   else
292     thread_id = NULL;
293
294   return thread_id;
295 }
296
297 /* Set the current thread's priority.  */
298 static inline int
299 __gthread_objc_thread_set_priority (int priority)
300 {
301   if (!__gthread_active_p ())
302     return -1;
303   else
304     {
305 #ifdef _POSIX_PRIORITY_SCHEDULING
306 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
307       pthread_t thread_id = __gthrw_(pthread_self) ();
308       int policy;
309       struct sched_param params;
310       int priority_min, priority_max;
311
312       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
313         {
314           if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
315             return -1;
316
317           if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
318             return -1;
319
320           if (priority > priority_max)
321             priority = priority_max;
322           else if (priority < priority_min)
323             priority = priority_min;
324           params.sched_priority = priority;
325
326           /*
327            * The solaris 7 and several other man pages incorrectly state that
328            * this should be a pointer to policy but pthread.h is universally
329            * at odds with this.
330            */
331           if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
332             return 0;
333         }
334 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
335 #endif /* _POSIX_PRIORITY_SCHEDULING */
336       return -1;
337     }
338 }
339
340 /* Return the current thread's priority.  */
341 static inline int
342 __gthread_objc_thread_get_priority (void)
343 {
344 #ifdef _POSIX_PRIORITY_SCHEDULING
345 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
346   if (__gthread_active_p ())
347     {
348       int policy;
349       struct sched_param params;
350
351       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
352         return params.sched_priority;
353       else
354         return -1;
355     }
356   else
357 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
358 #endif /* _POSIX_PRIORITY_SCHEDULING */
359     return OBJC_THREAD_INTERACTIVE_PRIORITY;
360 }
361
362 /* Yield our process time to another thread.  */
363 static inline void
364 __gthread_objc_thread_yield (void)
365 {
366   if (__gthread_active_p ())
367     __gthrw_(sched_yield) ();
368 }
369
370 /* Terminate the current thread.  */
371 static inline int
372 __gthread_objc_thread_exit (void)
373 {
374   if (__gthread_active_p ())
375     /* exit the thread */
376     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
377
378   /* Failed if we reached here */
379   return -1;
380 }
381
382 /* Returns an integer value which uniquely describes a thread.  */
383 static inline objc_thread_t
384 __gthread_objc_thread_id (void)
385 {
386   if (__gthread_active_p ())
387     return (objc_thread_t) __gthrw_(pthread_self) ();
388   else
389     return (objc_thread_t) 1;
390 }
391
392 /* Sets the thread's local storage pointer.  */
393 static inline int
394 __gthread_objc_thread_set_data (void *value)
395 {
396   if (__gthread_active_p ())
397     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
398   else
399     {
400       thread_local_storage = value;
401       return 0;
402     }
403 }
404
405 /* Returns the thread's local storage pointer.  */
406 static inline void *
407 __gthread_objc_thread_get_data (void)
408 {
409   if (__gthread_active_p ())
410     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
411   else
412     return thread_local_storage;
413 }
414
415 /* Backend mutex functions */
416
417 /* Allocate a mutex.  */
418 static inline int
419 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
420 {
421   if (__gthread_active_p ())
422     {
423       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
424
425       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
426         {
427           objc_free (mutex->backend);
428           mutex->backend = NULL;
429           return -1;
430         }
431     }
432
433   return 0;
434 }
435
436 /* Deallocate a mutex.  */
437 static inline int
438 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
439 {
440   if (__gthread_active_p ())
441     {
442       int count;
443
444       /*
445        * Posix Threads specifically require that the thread be unlocked
446        * for __gthrw_(pthread_mutex_destroy) to work.
447        */
448
449       do
450         {
451           count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
452           if (count < 0)
453             return -1;
454         }
455       while (count);
456
457       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
458         return -1;
459
460       objc_free (mutex->backend);
461       mutex->backend = NULL;
462     }
463   return 0;
464 }
465
466 /* Grab a lock on a mutex.  */
467 static inline int
468 __gthread_objc_mutex_lock (objc_mutex_t mutex)
469 {
470   if (__gthread_active_p ()
471       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
472     {
473       return -1;
474     }
475
476   return 0;
477 }
478
479 /* Try to grab a lock on a mutex.  */
480 static inline int
481 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
482 {
483   if (__gthread_active_p ()
484       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
485     {
486       return -1;
487     }
488
489   return 0;
490 }
491
492 /* Unlock the mutex */
493 static inline int
494 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
495 {
496   if (__gthread_active_p ()
497       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
498     {
499       return -1;
500     }
501
502   return 0;
503 }
504
505 /* Backend condition mutex functions */
506
507 /* Allocate a condition.  */
508 static inline int
509 __gthread_objc_condition_allocate (objc_condition_t condition)
510 {
511   if (__gthread_active_p ())
512     {
513       condition->backend = objc_malloc (sizeof (pthread_cond_t));
514
515       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
516         {
517           objc_free (condition->backend);
518           condition->backend = NULL;
519           return -1;
520         }
521     }
522
523   return 0;
524 }
525
526 /* Deallocate a condition.  */
527 static inline int
528 __gthread_objc_condition_deallocate (objc_condition_t condition)
529 {
530   if (__gthread_active_p ())
531     {
532       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
533         return -1;
534
535       objc_free (condition->backend);
536       condition->backend = NULL;
537     }
538   return 0;
539 }
540
541 /* Wait on the condition */
542 static inline int
543 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
544 {
545   if (__gthread_active_p ())
546     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
547                               (pthread_mutex_t *) mutex->backend);
548   else
549     return 0;
550 }
551
552 /* Wake up all threads waiting on this condition.  */
553 static inline int
554 __gthread_objc_condition_broadcast (objc_condition_t condition)
555 {
556   if (__gthread_active_p ())
557     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
558   else
559     return 0;
560 }
561
562 /* Wake up one thread waiting on this condition.  */
563 static inline int
564 __gthread_objc_condition_signal (objc_condition_t condition)
565 {
566   if (__gthread_active_p ())
567     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
568   else
569     return 0;
570 }
571
572 #else /* _LIBOBJC */
573
574 static inline int
575 __gthread_once (__gthread_once_t *once, void (*func) (void))
576 {
577   if (__gthread_active_p ())
578     return __gthrw_(pthread_once) (once, func);
579   else
580     return -1;
581 }
582
583 static inline int
584 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
585 {
586   return __gthrw_(pthread_key_create) (key, dtor);
587 }
588
589 static inline int
590 __gthread_key_delete (__gthread_key_t key)
591 {
592   return __gthrw_(pthread_key_delete) (key);
593 }
594
595 static inline void *
596 __gthread_getspecific (__gthread_key_t key)
597 {
598   return __gthrw_(pthread_getspecific) (key);
599 }
600
601 static inline int
602 __gthread_setspecific (__gthread_key_t key, const void *ptr)
603 {
604   return __gthrw_(pthread_setspecific) (key, ptr);
605 }
606
607 static inline int
608 __gthread_mutex_lock (__gthread_mutex_t *mutex)
609 {
610   if (__gthread_active_p ())
611     return __gthrw_(pthread_mutex_lock) (mutex);
612   else
613     return 0;
614 }
615
616 static inline int
617 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
618 {
619   if (__gthread_active_p ())
620     return __gthrw_(pthread_mutex_trylock) (mutex);
621   else
622     return 0;
623 }
624
625 static inline int
626 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
627 {
628   if (__gthread_active_p ())
629     return __gthrw_(pthread_mutex_unlock) (mutex);
630   else
631     return 0;
632 }
633
634 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
635 static inline int
636 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
637 {
638   if (__gthread_active_p ())
639     {
640       pthread_mutexattr_t attr;
641       int r;
642
643       r = __gthrw_(pthread_mutexattr_init) (&attr);
644       if (!r)
645         r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
646       if (!r)
647         r = __gthrw_(pthread_mutex_init) (mutex, &attr);
648       if (!r)
649         r = __gthrw_(pthread_mutexattr_destroy) (&attr);
650       return r;
651     }
652   return 0;
653 }
654 #endif
655
656 static inline int
657 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
658 {
659   return __gthread_mutex_lock (mutex);
660 }
661
662 static inline int
663 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
664 {
665   return __gthread_mutex_trylock (mutex);
666 }
667
668 static inline int
669 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
670 {
671   return __gthread_mutex_unlock (mutex);
672 }
673
674 #endif /* _LIBOBJC */
675
676 #endif /* ! GCC_GTHR_POSIX_H */