• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "iwth.h"
2 #include "iwp.h"
3 #include "iwlog.h"
4 
5 #include <errno.h>
6 #include <time.h>
7 
iw_cond_timed_wait_ms(pthread_cond_t * cond,pthread_mutex_t * mtx,long timeout_ms,bool * out_is_timeout)8 iwrc iw_cond_timed_wait_ms(pthread_cond_t *cond, pthread_mutex_t *mtx, long timeout_ms, bool *out_is_timeout) {
9   iwrc rc;
10   int rci;
11   struct timespec tp;
12   *out_is_timeout = false;
13 
14 #if defined(IW_HAVE_CLOCK_MONOTONIC) && defined(IW_HAVE_PTHREAD_CONDATTR_SETCLOCK)
15   rc = iwp_clock_get_time(CLOCK_MONOTONIC, &tp);
16 #else
17   rc = iwp_clock_get_time(CLOCK_REALTIME, &tp);
18 #endif
19   RCRET(rc);
20   tp.tv_sec += timeout_ms / 1000;
21   tp.tv_nsec += (timeout_ms % 1000) * 1000000;
22   do {
23     rci = pthread_cond_timedwait(cond, mtx, &tp);
24   } while (rci == EINTR);
25   if (rci) {
26     if (rci == ETIMEDOUT) {
27       *out_is_timeout = true;
28     } else {
29       rc = iwrc_set_errno(IW_ERROR_THREADING_ERRNO, rci);
30     }
31   }
32 
33   return rc;
34 }
35 
36 #ifdef __APPLE__
37 
38 #ifndef __unused
39 #define __unused __attribute__((unused))
40 #endif
41 
pthread_barrierattr_init(pthread_barrierattr_t * attr __unused)42 int pthread_barrierattr_init(pthread_barrierattr_t *attr __unused) {
43   return 0;
44 }
45 
pthread_barrierattr_destroy(pthread_barrierattr_t * attr __unused)46 int pthread_barrierattr_destroy(pthread_barrierattr_t *attr __unused) {
47   return 0;
48 }
49 
pthread_barrierattr_getpshared(const pthread_barrierattr_t * restrict attr __unused,int * restrict pshared)50 int pthread_barrierattr_getpshared(
51   const pthread_barrierattr_t* restrict attr __unused,
52   int* restrict                         pshared
53   ) {
54   *pshared = PTHREAD_PROCESS_PRIVATE;
55   return 0;
56 }
57 
pthread_barrierattr_setpshared(pthread_barrierattr_t * attr __unused,int pshared)58 int pthread_barrierattr_setpshared(
59   pthread_barrierattr_t *attr __unused,
60   int                    pshared
61   ) {
62   if (pshared != PTHREAD_PROCESS_PRIVATE) {
63     errno = EINVAL;
64     return -1;
65   }
66   return 0;
67 }
68 
pthread_barrier_init(pthread_barrier_t * restrict barrier,const pthread_barrierattr_t * restrict attr __unused,unsigned count)69 int pthread_barrier_init(
70   pthread_barrier_t* restrict           barrier,
71   const pthread_barrierattr_t* restrict attr __unused,
72   unsigned                              count
73   ) {
74   if (count == 0) {
75     errno = EINVAL;
76     return -1;
77   }
78 
79   if (pthread_mutex_init(&barrier->mutex, 0) < 0) {
80     return -1;
81   }
82   if (pthread_cond_init(&barrier->cond, 0) < 0) {
83     int errno_save = errno;
84     pthread_mutex_destroy(&barrier->mutex);
85     errno = errno_save;
86     return -1;
87   }
88 
89   barrier->limit = count;
90   barrier->count = 0;
91   barrier->phase = 0;
92 
93   return 0;
94 }
95 
pthread_barrier_destroy(pthread_barrier_t * barrier)96 int pthread_barrier_destroy(pthread_barrier_t *barrier) {
97   pthread_mutex_destroy(&barrier->mutex);
98   pthread_cond_destroy(&barrier->cond);
99   return 0;
100 }
101 
pthread_barrier_wait(pthread_barrier_t * barrier)102 int pthread_barrier_wait(pthread_barrier_t *barrier) {
103   pthread_mutex_lock(&barrier->mutex);
104   barrier->count++;
105   if (barrier->count >= barrier->limit) {
106     barrier->phase++;
107     barrier->count = 0;
108     pthread_cond_broadcast(&barrier->cond);
109     pthread_mutex_unlock(&barrier->mutex);
110     return PTHREAD_BARRIER_SERIAL_THREAD;
111   } else {
112     unsigned phase = barrier->phase;
113     do {
114       pthread_cond_wait(&barrier->cond, &barrier->mutex);
115     } while (phase == barrier->phase);
116     pthread_mutex_unlock(&barrier->mutex);
117     return 0;
118   }
119 }
120 
121 #endif /* __APPLE__ */
122