source: trunk/third/gcc/gcc/gthr-solaris.h @ 18474

Revision 18474, 10.2 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18473, which included commits to RCS files with non-trunk default branches.
Line 
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
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_SOLARIS_H
30#define GCC_GTHR_SOLARIS_H
31
32/* Solaris threads as found in Solaris 2.[456].
33   Actually these are Unix International (UI) threads, but I don't
34   know if anyone else implements these.  */
35
36#define __GTHREADS 1
37
38#include <thread.h>
39#include <errno.h>
40
41typedef thread_key_t __gthread_key_t;
42typedef struct
43{
44  mutex_t mutex;
45  int once;
46} __gthread_once_t;
47typedef mutex_t __gthread_mutex_t;
48
49#define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
50#define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
51
52#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
53
54#pragma weak thr_keycreate
55#pragma weak thr_getspecific
56#pragma weak thr_setspecific
57#pragma weak thr_create
58
59#pragma weak mutex_lock
60#pragma weak mutex_trylock
61#pragma weak mutex_unlock
62
63#ifdef _LIBOBJC
64#pragma weak thr_exit
65#pragma weak thr_keycreate
66#pragma weak thr_getprio
67#pragma weak thr_self
68#pragma weak thr_setprio
69#pragma weak thr_yield
70
71#pragma weak cond_init
72#pragma weak cond_destroy
73#pragma weak cond_wait
74#pragma weak cond_broadcast
75#pragma weak cond_signal
76
77#pragma weak mutex_init
78#pragma weak mutex_destroy
79#endif
80
81/* This will not actually work in Solaris 2.5, since libc contains
82   dummy symbols of all thr_* routines.  */
83
84static inline int
85__gthread_active_p (void)
86{
87  static void *const __gthread_active_ptr = (void *) &thr_create;
88  return __gthread_active_ptr != 0;
89}
90
91#else /* not SUPPORTS_WEAK */
92
93static inline int
94__gthread_active_p (void)
95{
96  return 1;
97}
98
99#endif /* SUPPORTS_WEAK */
100
101#ifdef _LIBOBJC
102
103/* Key structure for maintaining thread specific storage */
104static thread_key_t _objc_thread_storage;
105
106/* Thread local storage for a single thread */
107static void *thread_local_storage = NULL;
108
109/* Backend initialization functions */
110
111/* Initialize the threads subsystem.  */
112static inline int
113__gthread_objc_init_thread_system(void)
114{
115  /* Initialize the thread storage key */
116  if (__gthread_active_p ()
117      && thr_keycreate(&_objc_thread_storage, NULL) == 0)
118    return 0;
119
120  return -1;
121}
122
123/* Close the threads subsystem.  */
124static inline int
125__gthread_objc_close_thread_system(void)
126{
127  if (__gthread_active_p ())
128    return 0;
129  else
130    return -1;
131}
132
133/* Backend thread functions */
134
135/* Create a new thread of execution.  */
136static inline objc_thread_t
137__gthread_objc_thread_detach(void (*func)(void *), void *arg)
138{
139  objc_thread_t thread_id;
140  thread_t new_thread_id = 0;
141
142  if (!__gthread_active_p ())
143    return NULL;
144 
145  if (thr_create(NULL, 0, (void *)func, arg,
146                 THR_DETACHED | THR_NEW_LWP,
147                 &new_thread_id) == 0)
148    thread_id = *(objc_thread_t *)&new_thread_id;
149  else
150    thread_id = NULL;
151 
152  return thread_id;
153}
154
155/* Set the current thread's priority.  */
156static inline int
157__gthread_objc_thread_set_priority(int priority)
158{
159  int sys_priority = 0;
160
161  if (!__gthread_active_p ())
162    return -1;
163
164  switch (priority)
165    {
166    case OBJC_THREAD_INTERACTIVE_PRIORITY:
167      sys_priority = 300;
168      break;
169    default:
170    case OBJC_THREAD_BACKGROUND_PRIORITY:
171      sys_priority = 200;
172      break;
173    case OBJC_THREAD_LOW_PRIORITY:
174      sys_priority = 1000;
175      break;
176    }
177
178  /* Change priority */
179  if (thr_setprio(thr_self(), sys_priority) == 0)
180    return 0;
181  else
182    return -1;
183}
184
185/* Return the current thread's priority.  */
186static inline int
187__gthread_objc_thread_get_priority(void)
188{
189  int sys_priority;
190
191  if (!__gthread_active_p ())
192    return OBJC_THREAD_INTERACTIVE_PRIORITY;
193                                                   
194  if (thr_getprio(thr_self(), &sys_priority) == 0)
195    {
196      if (sys_priority >= 250)
197        return OBJC_THREAD_INTERACTIVE_PRIORITY;
198      else if (sys_priority >= 150)
199        return OBJC_THREAD_BACKGROUND_PRIORITY;
200      return OBJC_THREAD_LOW_PRIORITY;
201    }
202
203  /* Couldn't get priority.  */
204  return -1;
205}
206
207/* Yield our process time to another thread.  */
208static inline void
209__gthread_objc_thread_yield(void)
210{
211  if (__gthread_active_p ())
212    thr_yield();
213}
214
215/* Terminate the current thread.  */
216static inline int
217__gthread_objc_thread_exit(void)
218{
219  if (__gthread_active_p ())
220    /* exit the thread */
221    thr_exit(&__objc_thread_exit_status);
222
223  /* Failed if we reached here */
224  return -1;
225}
226
227/* Returns an integer value which uniquely describes a thread.  */
228static inline objc_thread_t
229__gthread_objc_thread_id(void)
230{
231  if (__gthread_active_p ())
232    return (objc_thread_t)thr_self();
233  else
234    return (objc_thread_t)1;
235}
236
237/* Sets the thread's local storage pointer.  */
238static inline int
239__gthread_objc_thread_set_data(void *value)
240{
241  if (__gthread_active_p ())
242    {
243      if (thr_setspecific(_objc_thread_storage, value) == 0)
244        return 0;
245      else
246        return -1;
247    }
248  else
249    {
250      thread_local_storage = value;
251      return 0;
252    }
253}
254
255/* Returns the thread's local storage pointer.  */
256static inline void *
257__gthread_objc_thread_get_data(void)
258{
259  void *value = NULL;
260
261  if (__gthread_active_p ())
262    {
263      if (thr_getspecific(_objc_thread_storage, &value) == 0)
264        return value;
265      else
266        return NULL;
267    }
268  else
269    return thread_local_storage;
270}
271
272/* Backend mutex functions */
273
274/* Allocate a mutex.  */
275static inline int
276__gthread_objc_mutex_allocate(objc_mutex_t mutex)
277{
278  if (__gthread_active_p ()
279      && mutex_init( (mutex_t *)(&(mutex->backend)), USYNC_THREAD, 0))
280    return -1;
281
282  return 0;
283}
284
285/* Deallocate a mutex.  */
286static inline int
287__gthread_objc_mutex_deallocate(objc_mutex_t mutex)
288{
289  if (__gthread_active_p ())
290    mutex_destroy((mutex_t *)(&(mutex->backend)));
291
292  return 0;
293}
294
295/* Grab a lock on a mutex.  */
296static inline int
297__gthread_objc_mutex_lock(objc_mutex_t mutex)
298{
299  if (__gthread_active_p ()
300      && mutex_lock((mutex_t *)(&(mutex->backend))) != 0)
301    return -1;
302
303  return 0;
304}
305
306/* Try to grab a lock on a mutex.  */
307static inline int
308__gthread_objc_mutex_trylock(objc_mutex_t mutex)
309{
310  if (__gthread_active_p ()
311      && mutex_trylock((mutex_t *)(&(mutex->backend))) != 0)
312    return -1;
313
314  return 0;
315}
316
317/* Unlock the mutex */
318static inline int
319__gthread_objc_mutex_unlock(objc_mutex_t mutex)
320{
321  if (__gthread_active_p ()
322      && mutex_unlock((mutex_t *)(&(mutex->backend))) != 0)
323    return -1;
324
325  return 0;
326}
327
328/* Backend condition mutex functions */
329
330/* Allocate a condition.  */
331static inline int
332__gthread_objc_condition_allocate(objc_condition_t condition)
333{
334  if (__gthread_active_p ())
335    return cond_init((cond_t *)(&(condition->backend)), USYNC_THREAD,
336                     NULL);
337  else
338    return 0;
339}
340
341/* Deallocate a condition.  */
342static inline int
343__gthread_objc_condition_deallocate(objc_condition_t condition)
344{
345  if (__gthread_active_p ())
346    return cond_destroy((cond_t *)(&(condition->backend)));
347  else
348    return 0;
349}
350
351/* Wait on the condition */
352static inline int
353__gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
354{
355  if (__gthread_active_p ())
356    return cond_wait((cond_t *)(&(condition->backend)),
357                     (mutex_t *)(&(mutex->backend)));
358  else
359    return 0;
360}
361
362/* Wake up all threads waiting on this condition.  */
363static inline int
364__gthread_objc_condition_broadcast(objc_condition_t condition)
365{
366  if (__gthread_active_p ())
367    return cond_broadcast((cond_t *)(&(condition->backend)));
368  else
369    return 0;
370}
371
372/* Wake up one thread waiting on this condition.  */
373static inline int
374__gthread_objc_condition_signal(objc_condition_t condition)
375{
376  if (__gthread_active_p ())
377    return cond_signal((cond_t *)(&(condition->backend)));
378  else
379    return 0;
380}
381
382#else /* _LIBOBJC */
383
384static inline int
385__gthread_once (__gthread_once_t *once, void (*func) (void))
386{
387  if (! __gthread_active_p ())
388    return -1;
389
390  if (once == 0 || func == 0)
391    return EINVAL;
392
393  if (once->once == 0)
394    {
395      int status = mutex_lock (&once->mutex);
396      if (status != 0)
397        return status;
398      if (once->once == 0)
399        {
400          (*func) ();
401          once->once ++;
402        }
403      mutex_unlock (&once->mutex);
404    }
405  return 0;
406}
407
408static inline int
409__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
410{
411  /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
412     got a reasonable key value, and if not, fail.  */
413  *key = -1;
414  if (thr_keycreate (key, dtor) != 0 || *key == -1)
415    return -1;
416  else
417    return 0;
418}
419
420static inline int
421__gthread_key_dtor (__gthread_key_t key, void *ptr)
422{
423  /* Nothing needed.  */
424  return 0;
425}
426
427static inline int
428__gthread_key_delete (__gthread_key_t key)
429{
430  /* Not possible.  */
431  return -1;
432}
433
434static inline void *
435__gthread_getspecific (__gthread_key_t key)
436{
437  void *ptr;
438  if (thr_getspecific (key, &ptr) == 0)
439    return ptr;
440  else
441    return 0;
442}
443
444static inline int
445__gthread_setspecific (__gthread_key_t key, const void *ptr)
446{
447  return thr_setspecific (key, (void *) ptr);
448}
449
450static inline int
451__gthread_mutex_lock (__gthread_mutex_t *mutex)
452{
453  if (__gthread_active_p ())
454    return mutex_lock (mutex);
455  else
456    return 0;
457}
458
459static inline int
460__gthread_mutex_trylock (__gthread_mutex_t *mutex)
461{
462  if (__gthread_active_p ())
463    return mutex_trylock (mutex);
464  else
465    return 0;
466}
467
468static inline int
469__gthread_mutex_unlock (__gthread_mutex_t *mutex)
470{
471  if (__gthread_active_p ())
472    return mutex_unlock (mutex);
473  else
474    return 0;
475}
476
477#endif /* _LIBOBJC */
478
479#endif /* ! GCC_GTHR_SOLARIS_H */
Note: See TracBrowser for help on using the repository browser.