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