Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 1999-2006 Brian Paul
  4.  * Copyright 2008 VMware, Inc.
  5.  * All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * OTHER DEALINGS IN THE SOFTWARE.
  24.  *
  25.  **************************************************************************/
  26.  
  27.  
  28. /**
  29.  * @file
  30.  *
  31.  * Thread, mutex, condition variable, barrier, semaphore and
  32.  * thread-specific data functions.
  33.  */
  34.  
  35.  
  36. #ifndef OS_THREAD_H_
  37. #define OS_THREAD_H_
  38.  
  39.  
  40. #include "pipe/p_compiler.h"
  41. #include "util/u_debug.h" /* for assert */
  42.  
  43. #include "c11/threads.h"
  44.  
  45. #ifdef HAVE_PTHREAD
  46. #include <signal.h>
  47. #endif
  48.  
  49.  
  50. /* pipe_thread
  51.  */
  52. typedef thrd_t pipe_thread;
  53.  
  54. #define PIPE_THREAD_ROUTINE( name, param ) \
  55.    int name( void *param )
  56.  
  57. static INLINE pipe_thread pipe_thread_create( PIPE_THREAD_ROUTINE((*routine), ), void *param )
  58. {
  59.    pipe_thread thread;
  60. #ifdef HAVE_PTHREAD
  61.    sigset_t saved_set, new_set;
  62.    int ret;
  63.  
  64.    sigfillset(&new_set);
  65.    pthread_sigmask(SIG_SETMASK, &new_set, &saved_set);
  66.    ret = thrd_create( &thread, routine, param );
  67.    pthread_sigmask(SIG_SETMASK, &saved_set, NULL);
  68. #else
  69.    int ret;
  70.    ret = thrd_create( &thread, routine, param );
  71. #endif
  72.    if (ret)
  73.       return 0;
  74.  
  75.    return thread;
  76. }
  77.  
  78. static INLINE int pipe_thread_wait( pipe_thread thread )
  79. {
  80.    return thrd_join( thread, NULL );
  81. }
  82.  
  83. static INLINE int pipe_thread_destroy( pipe_thread thread )
  84. {
  85.    return thrd_detach( thread );
  86. }
  87.  
  88. static INLINE void pipe_thread_setname( const char *name )
  89. {
  90. #if defined(HAVE_PTHREAD)
  91. #  if defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
  92.       (__GLIBC__ >= 3 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
  93.    pthread_setname_np(pthread_self(), name);
  94. #  endif
  95. #endif
  96.    (void)name;
  97. }
  98.  
  99.  
  100. /* pipe_mutex
  101.  */
  102. typedef mtx_t pipe_mutex;
  103.  
  104. #define pipe_static_mutex(mutex) \
  105.    static pipe_mutex mutex = _MTX_INITIALIZER_NP
  106.  
  107. #define pipe_mutex_init(mutex) \
  108.    (void) mtx_init(&(mutex), mtx_plain)
  109.  
  110. #define pipe_mutex_destroy(mutex) \
  111.    mtx_destroy(&(mutex))
  112.  
  113. #define pipe_mutex_lock(mutex) \
  114.    (void) mtx_lock(&(mutex))
  115.  
  116. #define pipe_mutex_unlock(mutex) \
  117.    (void) mtx_unlock(&(mutex))
  118.  
  119.  
  120. /* pipe_condvar
  121.  */
  122. typedef cnd_t pipe_condvar;
  123.  
  124. #define pipe_condvar_init(cond) \
  125.    cnd_init(&(cond))
  126.  
  127. #define pipe_condvar_destroy(cond) \
  128.    cnd_destroy(&(cond))
  129.  
  130. #define pipe_condvar_wait(cond, mutex) \
  131.    cnd_wait(&(cond), &(mutex))
  132.  
  133. #define pipe_condvar_signal(cond) \
  134.    cnd_signal(&(cond))
  135.  
  136. #define pipe_condvar_broadcast(cond) \
  137.    cnd_broadcast(&(cond))
  138.  
  139.  
  140. /*
  141.  * pipe_barrier
  142.  */
  143.  
  144. #if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HURD)) && !defined(PIPE_OS_ANDROID)
  145.  
  146. typedef pthread_barrier_t pipe_barrier;
  147.  
  148. static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
  149. {
  150.    pthread_barrier_init(barrier, NULL, count);
  151. }
  152.  
  153. static INLINE void pipe_barrier_destroy(pipe_barrier *barrier)
  154. {
  155.    pthread_barrier_destroy(barrier);
  156. }
  157.  
  158. static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
  159. {
  160.    pthread_barrier_wait(barrier);
  161. }
  162.  
  163.  
  164. #else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
  165.  
  166. typedef struct {
  167.    unsigned count;
  168.    unsigned waiters;
  169.    uint64_t sequence;
  170.    pipe_mutex mutex;
  171.    pipe_condvar condvar;
  172. } pipe_barrier;
  173.  
  174. static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
  175. {
  176.    barrier->count = count;
  177.    barrier->waiters = 0;
  178.    barrier->sequence = 0;
  179.    pipe_mutex_init(barrier->mutex);
  180.    pipe_condvar_init(barrier->condvar);
  181. }
  182.  
  183. static INLINE void pipe_barrier_destroy(pipe_barrier *barrier)
  184. {
  185.    assert(barrier->waiters == 0);
  186.    pipe_mutex_destroy(barrier->mutex);
  187.    pipe_condvar_destroy(barrier->condvar);
  188. }
  189.  
  190. static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
  191. {
  192.    pipe_mutex_lock(barrier->mutex);
  193.  
  194.    assert(barrier->waiters < barrier->count);
  195.    barrier->waiters++;
  196.  
  197.    if (barrier->waiters < barrier->count) {
  198.       uint64_t sequence = barrier->sequence;
  199.  
  200.       do {
  201.          pipe_condvar_wait(barrier->condvar, barrier->mutex);
  202.       } while (sequence == barrier->sequence);
  203.    } else {
  204.       barrier->waiters = 0;
  205.       barrier->sequence++;
  206.       pipe_condvar_broadcast(barrier->condvar);
  207.    }
  208.  
  209.    pipe_mutex_unlock(barrier->mutex);
  210. }
  211.  
  212.  
  213. #endif
  214.  
  215.  
  216. /*
  217.  * Semaphores
  218.  */
  219.  
  220. typedef struct
  221. {
  222.    pipe_mutex mutex;
  223.    pipe_condvar cond;
  224.    int counter;
  225. } pipe_semaphore;
  226.  
  227.  
  228. static INLINE void
  229. pipe_semaphore_init(pipe_semaphore *sema, int init_val)
  230. {
  231.    pipe_mutex_init(sema->mutex);
  232.    pipe_condvar_init(sema->cond);
  233.    sema->counter = init_val;
  234. }
  235.  
  236. static INLINE void
  237. pipe_semaphore_destroy(pipe_semaphore *sema)
  238. {
  239.    pipe_mutex_destroy(sema->mutex);
  240.    pipe_condvar_destroy(sema->cond);
  241. }
  242.  
  243. /** Signal/increment semaphore counter */
  244. static INLINE void
  245. pipe_semaphore_signal(pipe_semaphore *sema)
  246. {
  247.    pipe_mutex_lock(sema->mutex);
  248.    sema->counter++;
  249.    pipe_condvar_signal(sema->cond);
  250.    pipe_mutex_unlock(sema->mutex);
  251. }
  252.  
  253. /** Wait for semaphore counter to be greater than zero */
  254. static INLINE void
  255. pipe_semaphore_wait(pipe_semaphore *sema)
  256. {
  257.    pipe_mutex_lock(sema->mutex);
  258.    while (sema->counter <= 0) {
  259.       pipe_condvar_wait(sema->cond, sema->mutex);
  260.    }
  261.    sema->counter--;
  262.    pipe_mutex_unlock(sema->mutex);
  263. }
  264.  
  265.  
  266.  
  267. /*
  268.  * Thread-specific data.
  269.  */
  270.  
  271. typedef struct {
  272.    tss_t key;
  273.    int initMagic;
  274. } pipe_tsd;
  275.  
  276.  
  277. #define PIPE_TSD_INIT_MAGIC 0xff8adc98
  278.  
  279.  
  280. static INLINE void
  281. pipe_tsd_init(pipe_tsd *tsd)
  282. {
  283.    if (tss_create(&tsd->key, NULL/*free*/) != 0) {
  284.       exit(-1);
  285.    }
  286.    tsd->initMagic = PIPE_TSD_INIT_MAGIC;
  287. }
  288.  
  289. static INLINE void *
  290. pipe_tsd_get(pipe_tsd *tsd)
  291. {
  292.    if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
  293.       pipe_tsd_init(tsd);
  294.    }
  295.    return tss_get(tsd->key);
  296. }
  297.  
  298. static INLINE void
  299. pipe_tsd_set(pipe_tsd *tsd, void *value)
  300. {
  301.    if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
  302.       pipe_tsd_init(tsd);
  303.    }
  304.    if (tss_set(tsd->key, value) != 0) {
  305.       exit(-1);
  306.    }
  307. }
  308.  
  309.  
  310.  
  311. #endif /* OS_THREAD_H_ */
  312.