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