darwin_semaphore.h raw

   1  /*
   2   * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
   3   * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
   4   * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
   5   * Copyright (c) 2000-2009 by Hewlett-Packard Development Company.
   6   * All rights reserved.
   7   *
   8   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   9   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  10   *
  11   * Permission is hereby granted to use or copy this program
  12   * for any purpose, provided the above notices are retained on all copies.
  13   * Permission to modify the code and to distribute modified code is granted,
  14   * provided the above notices are retained, and a notice that the code was
  15   * modified is included with the above copyright notice.
  16   */
  17  
  18  #ifndef GC_DARWIN_SEMAPHORE_H
  19  #define GC_DARWIN_SEMAPHORE_H
  20  
  21  #include "gc_priv.h"
  22  
  23  /*
  24   * This is a very simple semaphore implementation based on `pthreads`.
  25   * It is not async-signal safe.  But this is not a problem because
  26   * signals are not used to suspend threads on the target.
  27   */
  28  
  29  #if !defined(DARWIN) && !defined(GC_WIN32_THREADS) || !defined(GC_PTHREADS)
  30  #  error darwin_semaphore.h included for improper target
  31  #endif
  32  
  33  #include <errno.h>
  34  
  35  #ifdef __cplusplus
  36  extern "C" {
  37  #endif
  38  
  39  typedef struct {
  40    pthread_mutex_t mutex;
  41    pthread_cond_t cond;
  42    int value;
  43  } sem_t;
  44  
  45  GC_INLINE int
  46  sem_init(sem_t *sem, int pshared, int value)
  47  {
  48    int err;
  49  
  50    if (UNLIKELY(pshared != 0)) {
  51      errno = EPERM; /*< unsupported */
  52      return -1;
  53    }
  54    sem->value = value;
  55    err = pthread_mutex_init(&sem->mutex, NULL);
  56    if (UNLIKELY(err != 0)) {
  57      errno = err;
  58      return -1;
  59    }
  60    err = pthread_cond_init(&sem->cond, NULL);
  61    if (UNLIKELY(err != 0)) {
  62      (void)pthread_mutex_destroy(&sem->mutex);
  63      errno = err;
  64      return -1;
  65    }
  66    return 0;
  67  }
  68  
  69  GC_INLINE int
  70  sem_post(sem_t *sem)
  71  {
  72    int err = pthread_mutex_lock(&sem->mutex);
  73  
  74    if (UNLIKELY(err != 0)) {
  75      errno = err;
  76      return -1;
  77    }
  78    sem->value++;
  79    err = pthread_cond_signal(&sem->cond);
  80    if (UNLIKELY(err != 0)) {
  81      (void)pthread_mutex_unlock(&sem->mutex);
  82      errno = err;
  83      return -1;
  84    }
  85    err = pthread_mutex_unlock(&sem->mutex);
  86    if (UNLIKELY(err != 0)) {
  87      errno = err;
  88      return -1;
  89    }
  90    return 0;
  91  }
  92  
  93  GC_INLINE int
  94  sem_wait(sem_t *sem)
  95  {
  96    int err = pthread_mutex_lock(&sem->mutex);
  97  
  98    if (UNLIKELY(err != 0)) {
  99      errno = err;
 100      return -1;
 101    }
 102    while (0 == sem->value) {
 103      err = pthread_cond_wait(&sem->cond, &sem->mutex);
 104      if (UNLIKELY(err != 0)) {
 105        (void)pthread_mutex_unlock(&sem->mutex);
 106        errno = err;
 107        return -1;
 108      }
 109    }
 110    sem->value--;
 111    err = pthread_mutex_unlock(&sem->mutex);
 112    if (UNLIKELY(err != 0)) {
 113      errno = err;
 114      return -1;
 115    }
 116    return 0;
 117  }
 118  
 119  GC_INLINE int
 120  sem_destroy(sem_t *sem)
 121  {
 122    int err = pthread_cond_destroy(&sem->cond);
 123  
 124    if (UNLIKELY(err != 0)) {
 125      errno = err;
 126      return -1;
 127    }
 128    err = pthread_mutex_destroy(&sem->mutex);
 129    if (UNLIKELY(err != 0)) {
 130      errno = err;
 131      return -1;
 132    }
 133    return 0;
 134  }
 135  
 136  #ifdef __cplusplus
 137  } /* extern "C" */
 138  #endif
 139  
 140  #endif
 141