home *** CD-ROM | disk | FTP | other *** search
/ Beginning C++ Through Gam…rogramming (2nd Edition) / BCGP2E.ISO / bloodshed / devcpp-4.9.9.2_setup.exe / gthr-posix.h < prev    next >
C/C++ Source or Header  |  2005-01-29  |  12KB  |  518 lines

  1. /* Threads compatibility routines for libgcc2 and libobjc.  */
  2. /* Compile this one with gcc.  */
  3. /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003
  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, 59 Temple Place - Suite 330, Boston, MA
  21. 02111-1307, 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 _GLIBCXX_GCC_GTHR_POSIX_H
  31. #define _GLIBCXX_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. #ifndef _REENTRANT
  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.  
  50. #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
  51. #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
  52.  
  53. #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
  54.  
  55. #pragma weak pthread_once
  56. #pragma weak pthread_key_create
  57. #pragma weak pthread_key_delete
  58. #pragma weak pthread_getspecific
  59. #pragma weak pthread_setspecific
  60. #pragma weak pthread_create
  61.  
  62. #pragma weak pthread_mutex_lock
  63. #pragma weak pthread_mutex_trylock
  64. #pragma weak pthread_mutex_unlock
  65.  
  66. #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
  67. /* Objective-C.  */
  68. #pragma weak pthread_cond_broadcast
  69. #pragma weak pthread_cond_destroy
  70. #pragma weak pthread_cond_init
  71. #pragma weak pthread_cond_signal
  72. #pragma weak pthread_cond_wait
  73. #pragma weak pthread_exit
  74. #pragma weak pthread_mutex_init
  75. #pragma weak pthread_mutex_destroy
  76. #pragma weak pthread_self
  77. /* These really should be protected by _POSIX_PRIORITY_SCHEDULING, but
  78.    we use them inside a _POSIX_THREAD_PRIORITY_SCHEDULING block.  */
  79. #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
  80. #pragma weak sched_get_priority_max
  81. #pragma weak sched_get_priority_min
  82. #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
  83. #pragma weak sched_yield
  84. #pragma weak pthread_attr_destroy
  85. #pragma weak pthread_attr_init
  86. #pragma weak pthread_attr_setdetachstate
  87. #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
  88. #pragma weak pthread_getschedparam
  89. #pragma weak pthread_setschedparam
  90. #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
  91. #endif /* _LIBOBJC || _LIBOBJC_WEAK */
  92.  
  93. static inline int
  94. __gthread_active_p (void)
  95. {
  96.   static void *const __gthread_active_ptr = (void *) &pthread_create;
  97.   return __gthread_active_ptr != 0;
  98. }
  99.  
  100. #else /* not __GXX_WEAK__ */
  101.  
  102. static inline int
  103. __gthread_active_p (void)
  104. {
  105.   return 1;
  106. }
  107.  
  108. #endif /* __GXX_WEAK__ */
  109.  
  110. #ifdef _LIBOBJC
  111.  
  112. /* This is the config.h file in libobjc/ */
  113. #include <config.h>
  114.  
  115. #ifdef HAVE_SCHED_H
  116. # include <sched.h>
  117. #endif
  118.  
  119. /* Key structure for maintaining thread specific storage */
  120. static pthread_key_t _objc_thread_storage;
  121. static pthread_attr_t _objc_thread_attribs;
  122.  
  123. /* Thread local storage for a single thread */
  124. static void *thread_local_storage = NULL;
  125.  
  126. /* Backend initialization functions */
  127.  
  128. /* Initialize the threads subsystem.  */
  129. static inline int
  130. __gthread_objc_init_thread_system (void)
  131. {
  132.   if (__gthread_active_p ())
  133.     {
  134.       /* Initialize the thread storage key */
  135.       if (pthread_key_create (&_objc_thread_storage, NULL) == 0)
  136.     {
  137.       /* The normal default detach state for threads is
  138.        * PTHREAD_CREATE_JOINABLE which causes threads to not die
  139.        * when you think they should.  */
  140.       if (pthread_attr_init (&_objc_thread_attribs) == 0
  141.           && pthread_attr_setdetachstate (&_objc_thread_attribs,
  142.                           PTHREAD_CREATE_DETACHED) == 0)
  143.         return 0;
  144.     }
  145.     }
  146.  
  147.   return -1;
  148. }
  149.  
  150. /* Close the threads subsystem.  */
  151. static inline int
  152. __gthread_objc_close_thread_system (void)
  153. {
  154.   if (__gthread_active_p ()
  155.       && pthread_key_delete (_objc_thread_storage) == 0
  156.       && pthread_attr_destroy (&_objc_thread_attribs) == 0)
  157.     return 0;
  158.  
  159.   return -1;
  160. }
  161.  
  162. /* Backend thread functions */
  163.  
  164. /* Create a new thread of execution.  */
  165. static inline objc_thread_t
  166. __gthread_objc_thread_detach (void (*func)(void *), void *arg)
  167. {
  168.   objc_thread_t thread_id;
  169.   pthread_t new_thread_handle;
  170.  
  171.   if (!__gthread_active_p ())
  172.     return NULL;
  173.  
  174.   if (!(pthread_create (&new_thread_handle, NULL, (void *) func, arg)))
  175.     thread_id = (objc_thread_t) new_thread_handle;
  176.   else
  177.     thread_id = NULL;
  178.  
  179.   return thread_id;
  180. }
  181.  
  182. /* Set the current thread's priority.  */
  183. static inline int
  184. __gthread_objc_thread_set_priority (int priority)
  185. {
  186.   if (!__gthread_active_p ())
  187.     return -1;
  188.   else
  189.     {
  190. #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
  191.       pthread_t thread_id = pthread_self ();
  192.       int policy;
  193.       struct sched_param params;
  194.       int priority_min, priority_max;
  195.  
  196.       if (pthread_getschedparam (thread_id, &policy, ¶ms) == 0)
  197.     {
  198.       if ((priority_max = sched_get_priority_max (policy)) == -1)
  199.         return -1;
  200.  
  201.       if ((priority_min = sched_get_priority_min (policy)) == -1)
  202.         return -1;
  203.  
  204.       if (priority > priority_max)
  205.         priority = priority_max;
  206.       else if (priority < priority_min)
  207.         priority = priority_min;
  208.       params.sched_priority = priority;
  209.  
  210.       /*
  211.        * The solaris 7 and several other man pages incorrectly state that
  212.        * this should be a pointer to policy but pthread.h is universally
  213.        * at odds with this.
  214.        */
  215.       if (pthread_setschedparam (thread_id, policy, ¶ms) == 0)
  216.         return 0;
  217.     }
  218. #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
  219.       return -1;
  220.     }
  221. }
  222.  
  223. /* Return the current thread's priority.  */
  224. static inline int
  225. __gthread_objc_thread_get_priority (void)
  226. {
  227. #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
  228.   if (__gthread_active_p ())
  229.     {
  230.       int policy;
  231.       struct sched_param params;
  232.  
  233.       if (pthread_getschedparam (pthread_self (), &policy, ¶ms) == 0)
  234.     return params.sched_priority;
  235.       else
  236.     return -1;
  237.     }
  238.   else
  239. #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
  240.     return OBJC_THREAD_INTERACTIVE_PRIORITY;
  241. }
  242.  
  243. /* Yield our process time to another thread.  */
  244. static inline void
  245. __gthread_objc_thread_yield (void)
  246. {
  247.   if (__gthread_active_p ())
  248.     sched_yield ();
  249. }
  250.  
  251. /* Terminate the current thread.  */
  252. static inline int
  253. __gthread_objc_thread_exit (void)
  254. {
  255.   if (__gthread_active_p ())
  256.     /* exit the thread */
  257.     pthread_exit (&__objc_thread_exit_status);
  258.  
  259.   /* Failed if we reached here */
  260.   return -1;
  261. }
  262.  
  263. /* Returns an integer value which uniquely describes a thread.  */
  264. static inline objc_thread_t
  265. __gthread_objc_thread_id (void)
  266. {
  267.   if (__gthread_active_p ())
  268.     return (objc_thread_t) pthread_self ();
  269.   else
  270.     return (objc_thread_t) 1;
  271. }
  272.  
  273. /* Sets the thread's local storage pointer.  */
  274. static inline int
  275. __gthread_objc_thread_set_data (void *value)
  276. {
  277.   if (__gthread_active_p ())
  278.     return pthread_setspecific (_objc_thread_storage, value);
  279.   else
  280.     {
  281.       thread_local_storage = value;
  282.       return 0;
  283.     }
  284. }
  285.  
  286. /* Returns the thread's local storage pointer.  */
  287. static inline void *
  288. __gthread_objc_thread_get_data (void)
  289. {
  290.   if (__gthread_active_p ())
  291.     return pthread_getspecific (_objc_thread_storage);
  292.   else
  293.     return thread_local_storage;
  294. }
  295.  
  296. /* Backend mutex functions */
  297.  
  298. /* Allocate a mutex.  */
  299. static inline int
  300. __gthread_objc_mutex_allocate (objc_mutex_t mutex)
  301. {
  302.   if (__gthread_active_p ())
  303.     {
  304.       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
  305.  
  306.       if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL))
  307.     {
  308.       objc_free (mutex->backend);
  309.       mutex->backend = NULL;
  310.       return -1;
  311.     }
  312.     }
  313.  
  314.   return 0;
  315. }
  316.  
  317. /* Deallocate a mutex.  */
  318. static inline int
  319. __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
  320. {
  321.   if (__gthread_active_p ())
  322.     {
  323.       int count;
  324.  
  325.       /*
  326.        * Posix Threads specifically require that the thread be unlocked
  327.        * for pthread_mutex_destroy to work.
  328.        */
  329.  
  330.       do
  331.     {
  332.       count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
  333.       if (count < 0)
  334.         return -1;
  335.     }
  336.       while (count);
  337.  
  338.       if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
  339.     return -1;
  340.  
  341.       objc_free (mutex->backend);
  342.       mutex->backend = NULL;
  343.     }
  344.   return 0;
  345. }
  346.  
  347. /* Grab a lock on a mutex.  */
  348. static inline int
  349. __gthread_objc_mutex_lock (objc_mutex_t mutex)
  350. {
  351.   if (__gthread_active_p ()
  352.       && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0)
  353.     {
  354.       return -1;
  355.     }
  356.  
  357.   return 0;
  358. }
  359.  
  360. /* Try to grab a lock on a mutex.  */
  361. static inline int
  362. __gthread_objc_mutex_trylock (objc_mutex_t mutex)
  363. {
  364.   if (__gthread_active_p ()
  365.       && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0)
  366.     {
  367.       return -1;
  368.     }
  369.  
  370.   return 0;
  371. }
  372.  
  373. /* Unlock the mutex */
  374. static inline int
  375. __gthread_objc_mutex_unlock (objc_mutex_t mutex)
  376. {
  377.   if (__gthread_active_p ()
  378.       && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0)
  379.     {
  380.       return -1;
  381.     }
  382.  
  383.   return 0;
  384. }
  385.  
  386. /* Backend condition mutex functions */
  387.  
  388. /* Allocate a condition.  */
  389. static inline int
  390. __gthread_objc_condition_allocate (objc_condition_t condition)
  391. {
  392.   if (__gthread_active_p ())
  393.     {
  394.       condition->backend = objc_malloc (sizeof (pthread_cond_t));
  395.  
  396.       if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL))
  397.     {
  398.       objc_free (condition->backend);
  399.       condition->backend = NULL;
  400.       return -1;
  401.     }
  402.     }
  403.  
  404.   return 0;
  405. }
  406.  
  407. /* Deallocate a condition.  */
  408. static inline int
  409. __gthread_objc_condition_deallocate (objc_condition_t condition)
  410. {
  411.   if (__gthread_active_p ())
  412.     {
  413.       if (pthread_cond_destroy ((pthread_cond_t *) condition->backend))
  414.     return -1;
  415.  
  416.       objc_free (condition->backend);
  417.       condition->backend = NULL;
  418.     }
  419.   return 0;
  420. }
  421.  
  422. /* Wait on the condition */
  423. static inline int
  424. __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
  425. {
  426.   if (__gthread_active_p ())
  427.     return pthread_cond_wait ((pthread_cond_t *) condition->backend,
  428.                   (pthread_mutex_t *) mutex->backend);
  429.   else
  430.     return 0;
  431. }
  432.  
  433. /* Wake up all threads waiting on this condition.  */
  434. static inline int
  435. __gthread_objc_condition_broadcast (objc_condition_t condition)
  436. {
  437.   if (__gthread_active_p ())
  438.     return pthread_cond_broadcast ((pthread_cond_t *) condition->backend);
  439.   else
  440.     return 0;
  441. }
  442.  
  443. /* Wake up one thread waiting on this condition.  */
  444. static inline int
  445. __gthread_objc_condition_signal (objc_condition_t condition)
  446. {
  447.   if (__gthread_active_p ())
  448.     return pthread_cond_signal ((pthread_cond_t *) condition->backend);
  449.   else
  450.     return 0;
  451. }
  452.  
  453. #else /* _LIBOBJC */
  454.  
  455. static inline int
  456. __gthread_once (__gthread_once_t *once, void (*func) (void))
  457. {
  458.   if (__gthread_active_p ())
  459.     return pthread_once (once, func);
  460.   else
  461.     return -1;
  462. }
  463.  
  464. static inline int
  465. __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
  466. {
  467.   return pthread_key_create (key, dtor);
  468. }
  469.  
  470. static inline int
  471. __gthread_key_delete (__gthread_key_t key)
  472. {
  473.   return pthread_key_delete (key);
  474. }
  475.  
  476. static inline void *
  477. __gthread_getspecific (__gthread_key_t key)
  478. {
  479.   return pthread_getspecific (key);
  480. }
  481.  
  482. static inline int
  483. __gthread_setspecific (__gthread_key_t key, const void *ptr)
  484. {
  485.   return pthread_setspecific (key, ptr);
  486. }
  487.  
  488. static inline int
  489. __gthread_mutex_lock (__gthread_mutex_t *mutex)
  490. {
  491.   if (__gthread_active_p ())
  492.     return pthread_mutex_lock (mutex);
  493.   else
  494.     return 0;
  495. }
  496.  
  497. static inline int
  498. __gthread_mutex_trylock (__gthread_mutex_t *mutex)
  499. {
  500.   if (__gthread_active_p ())
  501.     return pthread_mutex_trylock (mutex);
  502.   else
  503.     return 0;
  504. }
  505.  
  506. static inline int
  507. __gthread_mutex_unlock (__gthread_mutex_t *mutex)
  508. {
  509.   if (__gthread_active_p ())
  510.     return pthread_mutex_unlock (mutex);
  511.   else
  512.     return 0;
  513. }
  514.  
  515. #endif /* _LIBOBJC */
  516.  
  517. #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
  518.