xref: /third_party/libuv/src/unix/thread.c (revision e66f31c5)
1e66f31c5Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2e66f31c5Sopenharmony_ci *
3e66f31c5Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
4e66f31c5Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
5e66f31c5Sopenharmony_ci * deal in the Software without restriction, including without limitation the
6e66f31c5Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7e66f31c5Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
8e66f31c5Sopenharmony_ci * furnished to do so, subject to the following conditions:
9e66f31c5Sopenharmony_ci *
10e66f31c5Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
11e66f31c5Sopenharmony_ci * all copies or substantial portions of the Software.
12e66f31c5Sopenharmony_ci *
13e66f31c5Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14e66f31c5Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15e66f31c5Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16e66f31c5Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17e66f31c5Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18e66f31c5Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19e66f31c5Sopenharmony_ci * IN THE SOFTWARE.
20e66f31c5Sopenharmony_ci */
21e66f31c5Sopenharmony_ci
22e66f31c5Sopenharmony_ci#include "uv.h"
23e66f31c5Sopenharmony_ci#include "internal.h"
24e66f31c5Sopenharmony_ci
25e66f31c5Sopenharmony_ci#include <pthread.h>
26e66f31c5Sopenharmony_ci#include <assert.h>
27e66f31c5Sopenharmony_ci#include <errno.h>
28e66f31c5Sopenharmony_ci
29e66f31c5Sopenharmony_ci#include <sys/time.h>
30e66f31c5Sopenharmony_ci#include <sys/resource.h>  /* getrlimit() */
31e66f31c5Sopenharmony_ci#include <unistd.h>  /* getpagesize() */
32e66f31c5Sopenharmony_ci
33e66f31c5Sopenharmony_ci#include <limits.h>
34e66f31c5Sopenharmony_ci
35e66f31c5Sopenharmony_ci#ifdef __MVS__
36e66f31c5Sopenharmony_ci#include <sys/ipc.h>
37e66f31c5Sopenharmony_ci#include <sys/sem.h>
38e66f31c5Sopenharmony_ci#endif
39e66f31c5Sopenharmony_ci
40e66f31c5Sopenharmony_ci#if defined(__GLIBC__) && !defined(__UCLIBC__)
41e66f31c5Sopenharmony_ci#include <gnu/libc-version.h>  /* gnu_get_libc_version() */
42e66f31c5Sopenharmony_ci#endif
43e66f31c5Sopenharmony_ci
44e66f31c5Sopenharmony_ci#if defined(__linux__)
45e66f31c5Sopenharmony_ci# include <sched.h>
46e66f31c5Sopenharmony_ci# define uv__cpu_set_t cpu_set_t
47e66f31c5Sopenharmony_ci#elif defined(__FreeBSD__)
48e66f31c5Sopenharmony_ci# include <sys/param.h>
49e66f31c5Sopenharmony_ci# include <sys/cpuset.h>
50e66f31c5Sopenharmony_ci# include <pthread_np.h>
51e66f31c5Sopenharmony_ci# define uv__cpu_set_t cpuset_t
52e66f31c5Sopenharmony_ci#endif
53e66f31c5Sopenharmony_ci
54e66f31c5Sopenharmony_ci
55e66f31c5Sopenharmony_ci#undef NANOSEC
56e66f31c5Sopenharmony_ci#define NANOSEC ((uint64_t) 1e9)
57e66f31c5Sopenharmony_ci
58e66f31c5Sopenharmony_ci/* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
59e66f31c5Sopenharmony_ci * too small to safely receive signals on.
60e66f31c5Sopenharmony_ci *
61e66f31c5Sopenharmony_ci * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
62e66f31c5Sopenharmony_ci * the largest MINSIGSTKSZ of the architectures that musl supports) so
63e66f31c5Sopenharmony_ci * let's use that as a lower bound.
64e66f31c5Sopenharmony_ci *
65e66f31c5Sopenharmony_ci * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
66e66f31c5Sopenharmony_ci * is between 28 and 133 KB when compiling against glibc, depending
67e66f31c5Sopenharmony_ci * on the architecture.
68e66f31c5Sopenharmony_ci */
69e66f31c5Sopenharmony_cistatic size_t uv__min_stack_size(void) {
70e66f31c5Sopenharmony_ci  static const size_t min = 8192;
71e66f31c5Sopenharmony_ci
72e66f31c5Sopenharmony_ci#ifdef PTHREAD_STACK_MIN  /* Not defined on NetBSD. */
73e66f31c5Sopenharmony_ci  if (min < (size_t) PTHREAD_STACK_MIN)
74e66f31c5Sopenharmony_ci    return PTHREAD_STACK_MIN;
75e66f31c5Sopenharmony_ci#endif  /* PTHREAD_STACK_MIN */
76e66f31c5Sopenharmony_ci
77e66f31c5Sopenharmony_ci  return min;
78e66f31c5Sopenharmony_ci}
79e66f31c5Sopenharmony_ci
80e66f31c5Sopenharmony_ci
81e66f31c5Sopenharmony_ci/* On Linux, threads created by musl have a much smaller stack than threads
82e66f31c5Sopenharmony_ci * created by glibc (80 vs. 2048 or 4096 kB.)  Follow glibc for consistency.
83e66f31c5Sopenharmony_ci */
84e66f31c5Sopenharmony_cistatic size_t uv__default_stack_size(void) {
85e66f31c5Sopenharmony_ci#if !defined(__linux__)
86e66f31c5Sopenharmony_ci  return 0;
87e66f31c5Sopenharmony_ci#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
88e66f31c5Sopenharmony_ci  return 4 << 20;  /* glibc default. */
89e66f31c5Sopenharmony_ci#else
90e66f31c5Sopenharmony_ci  return 2 << 20;  /* glibc default. */
91e66f31c5Sopenharmony_ci#endif
92e66f31c5Sopenharmony_ci}
93e66f31c5Sopenharmony_ci
94e66f31c5Sopenharmony_ci
95e66f31c5Sopenharmony_ci/* On MacOS, threads other than the main thread are created with a reduced
96e66f31c5Sopenharmony_ci * stack size by default.  Adjust to RLIMIT_STACK aligned to the page size.
97e66f31c5Sopenharmony_ci */
98e66f31c5Sopenharmony_cisize_t uv__thread_stack_size(void) {
99e66f31c5Sopenharmony_ci#if defined(__APPLE__) || defined(__linux__)
100e66f31c5Sopenharmony_ci  struct rlimit lim;
101e66f31c5Sopenharmony_ci
102e66f31c5Sopenharmony_ci  /* getrlimit() can fail on some aarch64 systems due to a glibc bug where
103e66f31c5Sopenharmony_ci   * the system call wrapper invokes the wrong system call. Don't treat
104e66f31c5Sopenharmony_ci   * that as fatal, just use the default stack size instead.
105e66f31c5Sopenharmony_ci   */
106e66f31c5Sopenharmony_ci  if (getrlimit(RLIMIT_STACK, &lim))
107e66f31c5Sopenharmony_ci    return uv__default_stack_size();
108e66f31c5Sopenharmony_ci
109e66f31c5Sopenharmony_ci  if (lim.rlim_cur == RLIM_INFINITY)
110e66f31c5Sopenharmony_ci    return uv__default_stack_size();
111e66f31c5Sopenharmony_ci
112e66f31c5Sopenharmony_ci  /* pthread_attr_setstacksize() expects page-aligned values. */
113e66f31c5Sopenharmony_ci  lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
114e66f31c5Sopenharmony_ci
115e66f31c5Sopenharmony_ci  if (lim.rlim_cur >= (rlim_t) uv__min_stack_size())
116e66f31c5Sopenharmony_ci    return lim.rlim_cur;
117e66f31c5Sopenharmony_ci#endif
118e66f31c5Sopenharmony_ci
119e66f31c5Sopenharmony_ci  return uv__default_stack_size();
120e66f31c5Sopenharmony_ci}
121e66f31c5Sopenharmony_ci
122e66f31c5Sopenharmony_ci
123e66f31c5Sopenharmony_ciint uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
124e66f31c5Sopenharmony_ci  uv_thread_options_t params;
125e66f31c5Sopenharmony_ci  params.flags = UV_THREAD_NO_FLAGS;
126e66f31c5Sopenharmony_ci  return uv_thread_create_ex(tid, &params, entry, arg);
127e66f31c5Sopenharmony_ci}
128e66f31c5Sopenharmony_ci
129e66f31c5Sopenharmony_ciint uv_thread_create_ex(uv_thread_t* tid,
130e66f31c5Sopenharmony_ci                        const uv_thread_options_t* params,
131e66f31c5Sopenharmony_ci                        void (*entry)(void *arg),
132e66f31c5Sopenharmony_ci                        void *arg) {
133e66f31c5Sopenharmony_ci  int err;
134e66f31c5Sopenharmony_ci  pthread_attr_t* attr;
135e66f31c5Sopenharmony_ci  pthread_attr_t attr_storage;
136e66f31c5Sopenharmony_ci  size_t pagesize;
137e66f31c5Sopenharmony_ci  size_t stack_size;
138e66f31c5Sopenharmony_ci  size_t min_stack_size;
139e66f31c5Sopenharmony_ci
140e66f31c5Sopenharmony_ci  /* Used to squelch a -Wcast-function-type warning. */
141e66f31c5Sopenharmony_ci  union {
142e66f31c5Sopenharmony_ci    void (*in)(void*);
143e66f31c5Sopenharmony_ci    void* (*out)(void*);
144e66f31c5Sopenharmony_ci  } f;
145e66f31c5Sopenharmony_ci
146e66f31c5Sopenharmony_ci  stack_size =
147e66f31c5Sopenharmony_ci      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
148e66f31c5Sopenharmony_ci
149e66f31c5Sopenharmony_ci  attr = NULL;
150e66f31c5Sopenharmony_ci  if (stack_size == 0) {
151e66f31c5Sopenharmony_ci    stack_size = uv__thread_stack_size();
152e66f31c5Sopenharmony_ci  } else {
153e66f31c5Sopenharmony_ci    pagesize = (size_t)getpagesize();
154e66f31c5Sopenharmony_ci    /* Round up to the nearest page boundary. */
155e66f31c5Sopenharmony_ci    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
156e66f31c5Sopenharmony_ci    min_stack_size = uv__min_stack_size();
157e66f31c5Sopenharmony_ci    if (stack_size < min_stack_size)
158e66f31c5Sopenharmony_ci      stack_size = min_stack_size;
159e66f31c5Sopenharmony_ci  }
160e66f31c5Sopenharmony_ci
161e66f31c5Sopenharmony_ci  if (stack_size > 0) {
162e66f31c5Sopenharmony_ci    attr = &attr_storage;
163e66f31c5Sopenharmony_ci
164e66f31c5Sopenharmony_ci    if (pthread_attr_init(attr))
165e66f31c5Sopenharmony_ci      abort();
166e66f31c5Sopenharmony_ci
167e66f31c5Sopenharmony_ci    if (pthread_attr_setstacksize(attr, stack_size))
168e66f31c5Sopenharmony_ci      abort();
169e66f31c5Sopenharmony_ci  }
170e66f31c5Sopenharmony_ci
171e66f31c5Sopenharmony_ci  f.in = entry;
172e66f31c5Sopenharmony_ci  err = pthread_create(tid, attr, f.out, arg);
173e66f31c5Sopenharmony_ci
174e66f31c5Sopenharmony_ci  if (attr != NULL)
175e66f31c5Sopenharmony_ci    pthread_attr_destroy(attr);
176e66f31c5Sopenharmony_ci
177e66f31c5Sopenharmony_ci  return UV__ERR(err);
178e66f31c5Sopenharmony_ci}
179e66f31c5Sopenharmony_ci
180e66f31c5Sopenharmony_ci#if UV__CPU_AFFINITY_SUPPORTED
181e66f31c5Sopenharmony_ci
182e66f31c5Sopenharmony_ciint uv_thread_setaffinity(uv_thread_t* tid,
183e66f31c5Sopenharmony_ci                          char* cpumask,
184e66f31c5Sopenharmony_ci                          char* oldmask,
185e66f31c5Sopenharmony_ci                          size_t mask_size) {
186e66f31c5Sopenharmony_ci  int i;
187e66f31c5Sopenharmony_ci  int r;
188e66f31c5Sopenharmony_ci  uv__cpu_set_t cpuset;
189e66f31c5Sopenharmony_ci  int cpumasksize;
190e66f31c5Sopenharmony_ci
191e66f31c5Sopenharmony_ci  cpumasksize = uv_cpumask_size();
192e66f31c5Sopenharmony_ci  if (cpumasksize < 0)
193e66f31c5Sopenharmony_ci    return cpumasksize;
194e66f31c5Sopenharmony_ci  if (mask_size < (size_t)cpumasksize)
195e66f31c5Sopenharmony_ci    return UV_EINVAL;
196e66f31c5Sopenharmony_ci
197e66f31c5Sopenharmony_ci  if (oldmask != NULL) {
198e66f31c5Sopenharmony_ci    r = uv_thread_getaffinity(tid, oldmask, mask_size);
199e66f31c5Sopenharmony_ci    if (r < 0)
200e66f31c5Sopenharmony_ci      return r;
201e66f31c5Sopenharmony_ci  }
202e66f31c5Sopenharmony_ci
203e66f31c5Sopenharmony_ci  CPU_ZERO(&cpuset);
204e66f31c5Sopenharmony_ci  for (i = 0; i < cpumasksize; i++)
205e66f31c5Sopenharmony_ci    if (cpumask[i])
206e66f31c5Sopenharmony_ci      CPU_SET(i, &cpuset);
207e66f31c5Sopenharmony_ci
208e66f31c5Sopenharmony_ci#if defined(__ANDROID__)
209e66f31c5Sopenharmony_ci  if (sched_setaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset))
210e66f31c5Sopenharmony_ci    r = errno;
211e66f31c5Sopenharmony_ci  else
212e66f31c5Sopenharmony_ci    r = 0;
213e66f31c5Sopenharmony_ci#else
214e66f31c5Sopenharmony_ci  r = pthread_setaffinity_np(*tid, sizeof(cpuset), &cpuset);
215e66f31c5Sopenharmony_ci#endif
216e66f31c5Sopenharmony_ci
217e66f31c5Sopenharmony_ci  return UV__ERR(r);
218e66f31c5Sopenharmony_ci}
219e66f31c5Sopenharmony_ci
220e66f31c5Sopenharmony_ci
221e66f31c5Sopenharmony_ciint uv_thread_getaffinity(uv_thread_t* tid,
222e66f31c5Sopenharmony_ci                          char* cpumask,
223e66f31c5Sopenharmony_ci                          size_t mask_size) {
224e66f31c5Sopenharmony_ci  int r;
225e66f31c5Sopenharmony_ci  int i;
226e66f31c5Sopenharmony_ci  uv__cpu_set_t cpuset;
227e66f31c5Sopenharmony_ci  int cpumasksize;
228e66f31c5Sopenharmony_ci
229e66f31c5Sopenharmony_ci  cpumasksize = uv_cpumask_size();
230e66f31c5Sopenharmony_ci  if (cpumasksize < 0)
231e66f31c5Sopenharmony_ci    return cpumasksize;
232e66f31c5Sopenharmony_ci  if (mask_size < (size_t)cpumasksize)
233e66f31c5Sopenharmony_ci    return UV_EINVAL;
234e66f31c5Sopenharmony_ci
235e66f31c5Sopenharmony_ci  CPU_ZERO(&cpuset);
236e66f31c5Sopenharmony_ci#if defined(__ANDROID__)
237e66f31c5Sopenharmony_ci  if (sched_getaffinity(pthread_gettid_np(*tid), sizeof(cpuset), &cpuset))
238e66f31c5Sopenharmony_ci    r = errno;
239e66f31c5Sopenharmony_ci  else
240e66f31c5Sopenharmony_ci    r = 0;
241e66f31c5Sopenharmony_ci#else
242e66f31c5Sopenharmony_ci  r = pthread_getaffinity_np(*tid, sizeof(cpuset), &cpuset);
243e66f31c5Sopenharmony_ci#endif
244e66f31c5Sopenharmony_ci  if (r)
245e66f31c5Sopenharmony_ci    return UV__ERR(r);
246e66f31c5Sopenharmony_ci  for (i = 0; i < cpumasksize; i++)
247e66f31c5Sopenharmony_ci    cpumask[i] = !!CPU_ISSET(i, &cpuset);
248e66f31c5Sopenharmony_ci
249e66f31c5Sopenharmony_ci  return 0;
250e66f31c5Sopenharmony_ci}
251e66f31c5Sopenharmony_ci#else
252e66f31c5Sopenharmony_ciint uv_thread_setaffinity(uv_thread_t* tid,
253e66f31c5Sopenharmony_ci                          char* cpumask,
254e66f31c5Sopenharmony_ci                          char* oldmask,
255e66f31c5Sopenharmony_ci                          size_t mask_size) {
256e66f31c5Sopenharmony_ci  return UV_ENOTSUP;
257e66f31c5Sopenharmony_ci}
258e66f31c5Sopenharmony_ci
259e66f31c5Sopenharmony_ci
260e66f31c5Sopenharmony_ciint uv_thread_getaffinity(uv_thread_t* tid,
261e66f31c5Sopenharmony_ci                          char* cpumask,
262e66f31c5Sopenharmony_ci                          size_t mask_size) {
263e66f31c5Sopenharmony_ci  return UV_ENOTSUP;
264e66f31c5Sopenharmony_ci}
265e66f31c5Sopenharmony_ci#endif /* defined(__linux__) || defined(UV_BSD_H) */
266e66f31c5Sopenharmony_ci
267e66f31c5Sopenharmony_ciint uv_thread_getcpu(void) {
268e66f31c5Sopenharmony_ci#if UV__CPU_AFFINITY_SUPPORTED
269e66f31c5Sopenharmony_ci  int cpu;
270e66f31c5Sopenharmony_ci
271e66f31c5Sopenharmony_ci  cpu = sched_getcpu();
272e66f31c5Sopenharmony_ci  if (cpu < 0)
273e66f31c5Sopenharmony_ci    return UV__ERR(errno);
274e66f31c5Sopenharmony_ci
275e66f31c5Sopenharmony_ci  return cpu;
276e66f31c5Sopenharmony_ci#else
277e66f31c5Sopenharmony_ci  return UV_ENOTSUP;
278e66f31c5Sopenharmony_ci#endif
279e66f31c5Sopenharmony_ci}
280e66f31c5Sopenharmony_ci
281e66f31c5Sopenharmony_ciuv_thread_t uv_thread_self(void) {
282e66f31c5Sopenharmony_ci  return pthread_self();
283e66f31c5Sopenharmony_ci}
284e66f31c5Sopenharmony_ci
285e66f31c5Sopenharmony_ciint uv_thread_join(uv_thread_t *tid) {
286e66f31c5Sopenharmony_ci  return UV__ERR(pthread_join(*tid, NULL));
287e66f31c5Sopenharmony_ci}
288e66f31c5Sopenharmony_ci
289e66f31c5Sopenharmony_ci
290e66f31c5Sopenharmony_ciint uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
291e66f31c5Sopenharmony_ci  return pthread_equal(*t1, *t2);
292e66f31c5Sopenharmony_ci}
293e66f31c5Sopenharmony_ci
294e66f31c5Sopenharmony_ci
295e66f31c5Sopenharmony_ciint uv_mutex_init(uv_mutex_t* mutex) {
296e66f31c5Sopenharmony_ci#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
297e66f31c5Sopenharmony_ci  return UV__ERR(pthread_mutex_init(mutex, NULL));
298e66f31c5Sopenharmony_ci#else
299e66f31c5Sopenharmony_ci  pthread_mutexattr_t attr;
300e66f31c5Sopenharmony_ci  int err;
301e66f31c5Sopenharmony_ci
302e66f31c5Sopenharmony_ci  if (pthread_mutexattr_init(&attr))
303e66f31c5Sopenharmony_ci    abort();
304e66f31c5Sopenharmony_ci
305e66f31c5Sopenharmony_ci  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
306e66f31c5Sopenharmony_ci    abort();
307e66f31c5Sopenharmony_ci
308e66f31c5Sopenharmony_ci  err = pthread_mutex_init(mutex, &attr);
309e66f31c5Sopenharmony_ci
310e66f31c5Sopenharmony_ci  if (pthread_mutexattr_destroy(&attr))
311e66f31c5Sopenharmony_ci    abort();
312e66f31c5Sopenharmony_ci
313e66f31c5Sopenharmony_ci  return UV__ERR(err);
314e66f31c5Sopenharmony_ci#endif
315e66f31c5Sopenharmony_ci}
316e66f31c5Sopenharmony_ci
317e66f31c5Sopenharmony_ci
318e66f31c5Sopenharmony_ciint uv_mutex_init_recursive(uv_mutex_t* mutex) {
319e66f31c5Sopenharmony_ci  pthread_mutexattr_t attr;
320e66f31c5Sopenharmony_ci  int err;
321e66f31c5Sopenharmony_ci
322e66f31c5Sopenharmony_ci  if (pthread_mutexattr_init(&attr))
323e66f31c5Sopenharmony_ci    abort();
324e66f31c5Sopenharmony_ci
325e66f31c5Sopenharmony_ci  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
326e66f31c5Sopenharmony_ci    abort();
327e66f31c5Sopenharmony_ci
328e66f31c5Sopenharmony_ci  err = pthread_mutex_init(mutex, &attr);
329e66f31c5Sopenharmony_ci
330e66f31c5Sopenharmony_ci  if (pthread_mutexattr_destroy(&attr))
331e66f31c5Sopenharmony_ci    abort();
332e66f31c5Sopenharmony_ci
333e66f31c5Sopenharmony_ci  return UV__ERR(err);
334e66f31c5Sopenharmony_ci}
335e66f31c5Sopenharmony_ci
336e66f31c5Sopenharmony_ci
337e66f31c5Sopenharmony_civoid uv_mutex_destroy(uv_mutex_t* mutex) {
338e66f31c5Sopenharmony_ci  if (pthread_mutex_destroy(mutex))
339e66f31c5Sopenharmony_ci    abort();
340e66f31c5Sopenharmony_ci}
341e66f31c5Sopenharmony_ci
342e66f31c5Sopenharmony_ci
343e66f31c5Sopenharmony_civoid uv_mutex_lock(uv_mutex_t* mutex) {
344e66f31c5Sopenharmony_ci  if (pthread_mutex_lock(mutex))
345e66f31c5Sopenharmony_ci    abort();
346e66f31c5Sopenharmony_ci}
347e66f31c5Sopenharmony_ci
348e66f31c5Sopenharmony_ci
349e66f31c5Sopenharmony_ciint uv_mutex_trylock(uv_mutex_t* mutex) {
350e66f31c5Sopenharmony_ci  int err;
351e66f31c5Sopenharmony_ci
352e66f31c5Sopenharmony_ci  err = pthread_mutex_trylock(mutex);
353e66f31c5Sopenharmony_ci  if (err) {
354e66f31c5Sopenharmony_ci    if (err != EBUSY && err != EAGAIN)
355e66f31c5Sopenharmony_ci      abort();
356e66f31c5Sopenharmony_ci    return UV_EBUSY;
357e66f31c5Sopenharmony_ci  }
358e66f31c5Sopenharmony_ci
359e66f31c5Sopenharmony_ci  return 0;
360e66f31c5Sopenharmony_ci}
361e66f31c5Sopenharmony_ci
362e66f31c5Sopenharmony_ci
363e66f31c5Sopenharmony_civoid uv_mutex_unlock(uv_mutex_t* mutex) {
364e66f31c5Sopenharmony_ci  if (pthread_mutex_unlock(mutex))
365e66f31c5Sopenharmony_ci    abort();
366e66f31c5Sopenharmony_ci}
367e66f31c5Sopenharmony_ci
368e66f31c5Sopenharmony_ci
369e66f31c5Sopenharmony_ciint uv_rwlock_init(uv_rwlock_t* rwlock) {
370e66f31c5Sopenharmony_ci  return UV__ERR(pthread_rwlock_init(rwlock, NULL));
371e66f31c5Sopenharmony_ci}
372e66f31c5Sopenharmony_ci
373e66f31c5Sopenharmony_ci
374e66f31c5Sopenharmony_civoid uv_rwlock_destroy(uv_rwlock_t* rwlock) {
375e66f31c5Sopenharmony_ci  if (pthread_rwlock_destroy(rwlock))
376e66f31c5Sopenharmony_ci    abort();
377e66f31c5Sopenharmony_ci}
378e66f31c5Sopenharmony_ci
379e66f31c5Sopenharmony_ci
380e66f31c5Sopenharmony_civoid uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
381e66f31c5Sopenharmony_ci  if (pthread_rwlock_rdlock(rwlock))
382e66f31c5Sopenharmony_ci    abort();
383e66f31c5Sopenharmony_ci}
384e66f31c5Sopenharmony_ci
385e66f31c5Sopenharmony_ci
386e66f31c5Sopenharmony_ciint uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
387e66f31c5Sopenharmony_ci  int err;
388e66f31c5Sopenharmony_ci
389e66f31c5Sopenharmony_ci  err = pthread_rwlock_tryrdlock(rwlock);
390e66f31c5Sopenharmony_ci  if (err) {
391e66f31c5Sopenharmony_ci    if (err != EBUSY && err != EAGAIN)
392e66f31c5Sopenharmony_ci      abort();
393e66f31c5Sopenharmony_ci    return UV_EBUSY;
394e66f31c5Sopenharmony_ci  }
395e66f31c5Sopenharmony_ci
396e66f31c5Sopenharmony_ci  return 0;
397e66f31c5Sopenharmony_ci}
398e66f31c5Sopenharmony_ci
399e66f31c5Sopenharmony_ci
400e66f31c5Sopenharmony_civoid uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
401e66f31c5Sopenharmony_ci  if (pthread_rwlock_unlock(rwlock))
402e66f31c5Sopenharmony_ci    abort();
403e66f31c5Sopenharmony_ci}
404e66f31c5Sopenharmony_ci
405e66f31c5Sopenharmony_ci
406e66f31c5Sopenharmony_civoid uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
407e66f31c5Sopenharmony_ci  if (pthread_rwlock_wrlock(rwlock))
408e66f31c5Sopenharmony_ci    abort();
409e66f31c5Sopenharmony_ci}
410e66f31c5Sopenharmony_ci
411e66f31c5Sopenharmony_ci
412e66f31c5Sopenharmony_ciint uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
413e66f31c5Sopenharmony_ci  int err;
414e66f31c5Sopenharmony_ci
415e66f31c5Sopenharmony_ci  err = pthread_rwlock_trywrlock(rwlock);
416e66f31c5Sopenharmony_ci  if (err) {
417e66f31c5Sopenharmony_ci    if (err != EBUSY && err != EAGAIN)
418e66f31c5Sopenharmony_ci      abort();
419e66f31c5Sopenharmony_ci    return UV_EBUSY;
420e66f31c5Sopenharmony_ci  }
421e66f31c5Sopenharmony_ci
422e66f31c5Sopenharmony_ci  return 0;
423e66f31c5Sopenharmony_ci}
424e66f31c5Sopenharmony_ci
425e66f31c5Sopenharmony_ci
426e66f31c5Sopenharmony_civoid uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
427e66f31c5Sopenharmony_ci  if (pthread_rwlock_unlock(rwlock))
428e66f31c5Sopenharmony_ci    abort();
429e66f31c5Sopenharmony_ci}
430e66f31c5Sopenharmony_ci
431e66f31c5Sopenharmony_ci
432e66f31c5Sopenharmony_civoid uv_once(uv_once_t* guard, void (*callback)(void)) {
433e66f31c5Sopenharmony_ci  if (pthread_once(guard, callback))
434e66f31c5Sopenharmony_ci    abort();
435e66f31c5Sopenharmony_ci}
436e66f31c5Sopenharmony_ci
437e66f31c5Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
438e66f31c5Sopenharmony_ci
439e66f31c5Sopenharmony_ciint uv_sem_init(uv_sem_t* sem, unsigned int value) {
440e66f31c5Sopenharmony_ci  kern_return_t err;
441e66f31c5Sopenharmony_ci
442e66f31c5Sopenharmony_ci  err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
443e66f31c5Sopenharmony_ci  if (err == KERN_SUCCESS)
444e66f31c5Sopenharmony_ci    return 0;
445e66f31c5Sopenharmony_ci  if (err == KERN_INVALID_ARGUMENT)
446e66f31c5Sopenharmony_ci    return UV_EINVAL;
447e66f31c5Sopenharmony_ci  if (err == KERN_RESOURCE_SHORTAGE)
448e66f31c5Sopenharmony_ci    return UV_ENOMEM;
449e66f31c5Sopenharmony_ci
450e66f31c5Sopenharmony_ci  abort();
451e66f31c5Sopenharmony_ci  return UV_EINVAL;  /* Satisfy the compiler. */
452e66f31c5Sopenharmony_ci}
453e66f31c5Sopenharmony_ci
454e66f31c5Sopenharmony_ci
455e66f31c5Sopenharmony_civoid uv_sem_destroy(uv_sem_t* sem) {
456e66f31c5Sopenharmony_ci  if (semaphore_destroy(mach_task_self(), *sem))
457e66f31c5Sopenharmony_ci    abort();
458e66f31c5Sopenharmony_ci}
459e66f31c5Sopenharmony_ci
460e66f31c5Sopenharmony_ci
461e66f31c5Sopenharmony_civoid uv_sem_post(uv_sem_t* sem) {
462e66f31c5Sopenharmony_ci  if (semaphore_signal(*sem))
463e66f31c5Sopenharmony_ci    abort();
464e66f31c5Sopenharmony_ci}
465e66f31c5Sopenharmony_ci
466e66f31c5Sopenharmony_ci
467e66f31c5Sopenharmony_civoid uv_sem_wait(uv_sem_t* sem) {
468e66f31c5Sopenharmony_ci  int r;
469e66f31c5Sopenharmony_ci
470e66f31c5Sopenharmony_ci  do
471e66f31c5Sopenharmony_ci    r = semaphore_wait(*sem);
472e66f31c5Sopenharmony_ci  while (r == KERN_ABORTED);
473e66f31c5Sopenharmony_ci
474e66f31c5Sopenharmony_ci  if (r != KERN_SUCCESS)
475e66f31c5Sopenharmony_ci    abort();
476e66f31c5Sopenharmony_ci}
477e66f31c5Sopenharmony_ci
478e66f31c5Sopenharmony_ci
479e66f31c5Sopenharmony_ciint uv_sem_trywait(uv_sem_t* sem) {
480e66f31c5Sopenharmony_ci  mach_timespec_t interval;
481e66f31c5Sopenharmony_ci  kern_return_t err;
482e66f31c5Sopenharmony_ci
483e66f31c5Sopenharmony_ci  interval.tv_sec = 0;
484e66f31c5Sopenharmony_ci  interval.tv_nsec = 0;
485e66f31c5Sopenharmony_ci
486e66f31c5Sopenharmony_ci  err = semaphore_timedwait(*sem, interval);
487e66f31c5Sopenharmony_ci  if (err == KERN_SUCCESS)
488e66f31c5Sopenharmony_ci    return 0;
489e66f31c5Sopenharmony_ci  if (err == KERN_OPERATION_TIMED_OUT)
490e66f31c5Sopenharmony_ci    return UV_EAGAIN;
491e66f31c5Sopenharmony_ci
492e66f31c5Sopenharmony_ci  abort();
493e66f31c5Sopenharmony_ci  return UV_EINVAL;  /* Satisfy the compiler. */
494e66f31c5Sopenharmony_ci}
495e66f31c5Sopenharmony_ci
496e66f31c5Sopenharmony_ci#else /* !(defined(__APPLE__) && defined(__MACH__)) */
497e66f31c5Sopenharmony_ci
498e66f31c5Sopenharmony_ci#if defined(__GLIBC__) && !defined(__UCLIBC__)
499e66f31c5Sopenharmony_ci
500e66f31c5Sopenharmony_ci/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
501e66f31c5Sopenharmony_ci * by providing a custom implementation for glibc < 2.21 in terms of other
502e66f31c5Sopenharmony_ci * concurrency primitives.
503e66f31c5Sopenharmony_ci * Refs: https://github.com/nodejs/node/issues/19903 */
504e66f31c5Sopenharmony_ci
505e66f31c5Sopenharmony_ci/* To preserve ABI compatibility, we treat the uv_sem_t as storage for
506e66f31c5Sopenharmony_ci * a pointer to the actual struct we're using underneath. */
507e66f31c5Sopenharmony_ci
508e66f31c5Sopenharmony_cistatic uv_once_t glibc_version_check_once = UV_ONCE_INIT;
509e66f31c5Sopenharmony_cistatic int platform_needs_custom_semaphore = 0;
510e66f31c5Sopenharmony_ci
511e66f31c5Sopenharmony_cistatic void glibc_version_check(void) {
512e66f31c5Sopenharmony_ci  const char* version = gnu_get_libc_version();
513e66f31c5Sopenharmony_ci  platform_needs_custom_semaphore =
514e66f31c5Sopenharmony_ci      version[0] == '2' && version[1] == '.' &&
515e66f31c5Sopenharmony_ci      atoi(version + 2) < 21;
516e66f31c5Sopenharmony_ci}
517e66f31c5Sopenharmony_ci
518e66f31c5Sopenharmony_ci#elif defined(__MVS__)
519e66f31c5Sopenharmony_ci
520e66f31c5Sopenharmony_ci#define platform_needs_custom_semaphore 1
521e66f31c5Sopenharmony_ci
522e66f31c5Sopenharmony_ci#else /* !defined(__GLIBC__) && !defined(__MVS__) */
523e66f31c5Sopenharmony_ci
524e66f31c5Sopenharmony_ci#define platform_needs_custom_semaphore 0
525e66f31c5Sopenharmony_ci
526e66f31c5Sopenharmony_ci#endif
527e66f31c5Sopenharmony_ci
528e66f31c5Sopenharmony_citypedef struct uv_semaphore_s {
529e66f31c5Sopenharmony_ci  uv_mutex_t mutex;
530e66f31c5Sopenharmony_ci  uv_cond_t cond;
531e66f31c5Sopenharmony_ci  unsigned int value;
532e66f31c5Sopenharmony_ci} uv_semaphore_t;
533e66f31c5Sopenharmony_ci
534e66f31c5Sopenharmony_ci#if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
535e66f31c5Sopenharmony_ci    platform_needs_custom_semaphore
536e66f31c5Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
537e66f31c5Sopenharmony_ci#endif
538e66f31c5Sopenharmony_ci
539e66f31c5Sopenharmony_cistatic int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
540e66f31c5Sopenharmony_ci  int err;
541e66f31c5Sopenharmony_ci  uv_semaphore_t* sem;
542e66f31c5Sopenharmony_ci
543e66f31c5Sopenharmony_ci  sem = uv__malloc(sizeof(*sem));
544e66f31c5Sopenharmony_ci  if (sem == NULL)
545e66f31c5Sopenharmony_ci    return UV_ENOMEM;
546e66f31c5Sopenharmony_ci
547e66f31c5Sopenharmony_ci  if ((err = uv_mutex_init(&sem->mutex)) != 0) {
548e66f31c5Sopenharmony_ci    uv__free(sem);
549e66f31c5Sopenharmony_ci    return err;
550e66f31c5Sopenharmony_ci  }
551e66f31c5Sopenharmony_ci
552e66f31c5Sopenharmony_ci  if ((err = uv_cond_init(&sem->cond)) != 0) {
553e66f31c5Sopenharmony_ci    uv_mutex_destroy(&sem->mutex);
554e66f31c5Sopenharmony_ci    uv__free(sem);
555e66f31c5Sopenharmony_ci    return err;
556e66f31c5Sopenharmony_ci  }
557e66f31c5Sopenharmony_ci
558e66f31c5Sopenharmony_ci  sem->value = value;
559e66f31c5Sopenharmony_ci  *(uv_semaphore_t**)sem_ = sem;
560e66f31c5Sopenharmony_ci  return 0;
561e66f31c5Sopenharmony_ci}
562e66f31c5Sopenharmony_ci
563e66f31c5Sopenharmony_ci
564e66f31c5Sopenharmony_cistatic void uv__custom_sem_destroy(uv_sem_t* sem_) {
565e66f31c5Sopenharmony_ci  uv_semaphore_t* sem;
566e66f31c5Sopenharmony_ci
567e66f31c5Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
568e66f31c5Sopenharmony_ci  uv_cond_destroy(&sem->cond);
569e66f31c5Sopenharmony_ci  uv_mutex_destroy(&sem->mutex);
570e66f31c5Sopenharmony_ci  uv__free(sem);
571e66f31c5Sopenharmony_ci}
572e66f31c5Sopenharmony_ci
573e66f31c5Sopenharmony_ci
574e66f31c5Sopenharmony_cistatic void uv__custom_sem_post(uv_sem_t* sem_) {
575e66f31c5Sopenharmony_ci  uv_semaphore_t* sem;
576e66f31c5Sopenharmony_ci
577e66f31c5Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
578e66f31c5Sopenharmony_ci  uv_mutex_lock(&sem->mutex);
579e66f31c5Sopenharmony_ci  sem->value++;
580e66f31c5Sopenharmony_ci  if (sem->value == 1)
581e66f31c5Sopenharmony_ci    uv_cond_signal(&sem->cond); /* Release one to replace us. */
582e66f31c5Sopenharmony_ci  uv_mutex_unlock(&sem->mutex);
583e66f31c5Sopenharmony_ci}
584e66f31c5Sopenharmony_ci
585e66f31c5Sopenharmony_ci
586e66f31c5Sopenharmony_cistatic void uv__custom_sem_wait(uv_sem_t* sem_) {
587e66f31c5Sopenharmony_ci  uv_semaphore_t* sem;
588e66f31c5Sopenharmony_ci
589e66f31c5Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
590e66f31c5Sopenharmony_ci  uv_mutex_lock(&sem->mutex);
591e66f31c5Sopenharmony_ci  while (sem->value == 0)
592e66f31c5Sopenharmony_ci    uv_cond_wait(&sem->cond, &sem->mutex);
593e66f31c5Sopenharmony_ci  sem->value--;
594e66f31c5Sopenharmony_ci  uv_mutex_unlock(&sem->mutex);
595e66f31c5Sopenharmony_ci}
596e66f31c5Sopenharmony_ci
597e66f31c5Sopenharmony_ci
598e66f31c5Sopenharmony_cistatic int uv__custom_sem_trywait(uv_sem_t* sem_) {
599e66f31c5Sopenharmony_ci  uv_semaphore_t* sem;
600e66f31c5Sopenharmony_ci
601e66f31c5Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
602e66f31c5Sopenharmony_ci  if (uv_mutex_trylock(&sem->mutex) != 0)
603e66f31c5Sopenharmony_ci    return UV_EAGAIN;
604e66f31c5Sopenharmony_ci
605e66f31c5Sopenharmony_ci  if (sem->value == 0) {
606e66f31c5Sopenharmony_ci    uv_mutex_unlock(&sem->mutex);
607e66f31c5Sopenharmony_ci    return UV_EAGAIN;
608e66f31c5Sopenharmony_ci  }
609e66f31c5Sopenharmony_ci
610e66f31c5Sopenharmony_ci  sem->value--;
611e66f31c5Sopenharmony_ci  uv_mutex_unlock(&sem->mutex);
612e66f31c5Sopenharmony_ci
613e66f31c5Sopenharmony_ci  return 0;
614e66f31c5Sopenharmony_ci}
615e66f31c5Sopenharmony_ci
616e66f31c5Sopenharmony_cistatic int uv__sem_init(uv_sem_t* sem, unsigned int value) {
617e66f31c5Sopenharmony_ci  if (sem_init(sem, 0, value))
618e66f31c5Sopenharmony_ci    return UV__ERR(errno);
619e66f31c5Sopenharmony_ci  return 0;
620e66f31c5Sopenharmony_ci}
621e66f31c5Sopenharmony_ci
622e66f31c5Sopenharmony_ci
623e66f31c5Sopenharmony_cistatic void uv__sem_destroy(uv_sem_t* sem) {
624e66f31c5Sopenharmony_ci  if (sem_destroy(sem))
625e66f31c5Sopenharmony_ci    abort();
626e66f31c5Sopenharmony_ci}
627e66f31c5Sopenharmony_ci
628e66f31c5Sopenharmony_ci
629e66f31c5Sopenharmony_cistatic void uv__sem_post(uv_sem_t* sem) {
630e66f31c5Sopenharmony_ci  if (sem_post(sem))
631e66f31c5Sopenharmony_ci    abort();
632e66f31c5Sopenharmony_ci}
633e66f31c5Sopenharmony_ci
634e66f31c5Sopenharmony_ci
635e66f31c5Sopenharmony_cistatic void uv__sem_wait(uv_sem_t* sem) {
636e66f31c5Sopenharmony_ci  int r;
637e66f31c5Sopenharmony_ci
638e66f31c5Sopenharmony_ci  do
639e66f31c5Sopenharmony_ci    r = sem_wait(sem);
640e66f31c5Sopenharmony_ci  while (r == -1 && errno == EINTR);
641e66f31c5Sopenharmony_ci
642e66f31c5Sopenharmony_ci  if (r)
643e66f31c5Sopenharmony_ci    abort();
644e66f31c5Sopenharmony_ci}
645e66f31c5Sopenharmony_ci
646e66f31c5Sopenharmony_ci
647e66f31c5Sopenharmony_cistatic int uv__sem_trywait(uv_sem_t* sem) {
648e66f31c5Sopenharmony_ci  int r;
649e66f31c5Sopenharmony_ci
650e66f31c5Sopenharmony_ci  do
651e66f31c5Sopenharmony_ci    r = sem_trywait(sem);
652e66f31c5Sopenharmony_ci  while (r == -1 && errno == EINTR);
653e66f31c5Sopenharmony_ci
654e66f31c5Sopenharmony_ci  if (r) {
655e66f31c5Sopenharmony_ci    if (errno == EAGAIN)
656e66f31c5Sopenharmony_ci      return UV_EAGAIN;
657e66f31c5Sopenharmony_ci    abort();
658e66f31c5Sopenharmony_ci  }
659e66f31c5Sopenharmony_ci
660e66f31c5Sopenharmony_ci  return 0;
661e66f31c5Sopenharmony_ci}
662e66f31c5Sopenharmony_ci
663e66f31c5Sopenharmony_ciint uv_sem_init(uv_sem_t* sem, unsigned int value) {
664e66f31c5Sopenharmony_ci#if defined(__GLIBC__) && !defined(__UCLIBC__)
665e66f31c5Sopenharmony_ci  uv_once(&glibc_version_check_once, glibc_version_check);
666e66f31c5Sopenharmony_ci#endif
667e66f31c5Sopenharmony_ci
668e66f31c5Sopenharmony_ci  if (platform_needs_custom_semaphore)
669e66f31c5Sopenharmony_ci    return uv__custom_sem_init(sem, value);
670e66f31c5Sopenharmony_ci  else
671e66f31c5Sopenharmony_ci    return uv__sem_init(sem, value);
672e66f31c5Sopenharmony_ci}
673e66f31c5Sopenharmony_ci
674e66f31c5Sopenharmony_ci
675e66f31c5Sopenharmony_civoid uv_sem_destroy(uv_sem_t* sem) {
676e66f31c5Sopenharmony_ci  if (platform_needs_custom_semaphore)
677e66f31c5Sopenharmony_ci    uv__custom_sem_destroy(sem);
678e66f31c5Sopenharmony_ci  else
679e66f31c5Sopenharmony_ci    uv__sem_destroy(sem);
680e66f31c5Sopenharmony_ci}
681e66f31c5Sopenharmony_ci
682e66f31c5Sopenharmony_ci
683e66f31c5Sopenharmony_civoid uv_sem_post(uv_sem_t* sem) {
684e66f31c5Sopenharmony_ci  if (platform_needs_custom_semaphore)
685e66f31c5Sopenharmony_ci    uv__custom_sem_post(sem);
686e66f31c5Sopenharmony_ci  else
687e66f31c5Sopenharmony_ci    uv__sem_post(sem);
688e66f31c5Sopenharmony_ci}
689e66f31c5Sopenharmony_ci
690e66f31c5Sopenharmony_ci
691e66f31c5Sopenharmony_civoid uv_sem_wait(uv_sem_t* sem) {
692e66f31c5Sopenharmony_ci  if (platform_needs_custom_semaphore)
693e66f31c5Sopenharmony_ci    uv__custom_sem_wait(sem);
694e66f31c5Sopenharmony_ci  else
695e66f31c5Sopenharmony_ci    uv__sem_wait(sem);
696e66f31c5Sopenharmony_ci}
697e66f31c5Sopenharmony_ci
698e66f31c5Sopenharmony_ci
699e66f31c5Sopenharmony_ciint uv_sem_trywait(uv_sem_t* sem) {
700e66f31c5Sopenharmony_ci  if (platform_needs_custom_semaphore)
701e66f31c5Sopenharmony_ci    return uv__custom_sem_trywait(sem);
702e66f31c5Sopenharmony_ci  else
703e66f31c5Sopenharmony_ci    return uv__sem_trywait(sem);
704e66f31c5Sopenharmony_ci}
705e66f31c5Sopenharmony_ci
706e66f31c5Sopenharmony_ci#endif /* defined(__APPLE__) && defined(__MACH__) */
707e66f31c5Sopenharmony_ci
708e66f31c5Sopenharmony_ci
709e66f31c5Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
710e66f31c5Sopenharmony_ci
711e66f31c5Sopenharmony_ciint uv_cond_init(uv_cond_t* cond) {
712e66f31c5Sopenharmony_ci  return UV__ERR(pthread_cond_init(cond, NULL));
713e66f31c5Sopenharmony_ci}
714e66f31c5Sopenharmony_ci
715e66f31c5Sopenharmony_ci#else /* !(defined(__APPLE__) && defined(__MACH__)) */
716e66f31c5Sopenharmony_ci
717e66f31c5Sopenharmony_ciint uv_cond_init(uv_cond_t* cond) {
718e66f31c5Sopenharmony_ci  pthread_condattr_t attr;
719e66f31c5Sopenharmony_ci  int err;
720e66f31c5Sopenharmony_ci
721e66f31c5Sopenharmony_ci  err = pthread_condattr_init(&attr);
722e66f31c5Sopenharmony_ci  if (err)
723e66f31c5Sopenharmony_ci    return UV__ERR(err);
724e66f31c5Sopenharmony_ci
725e66f31c5Sopenharmony_ci  err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
726e66f31c5Sopenharmony_ci  if (err)
727e66f31c5Sopenharmony_ci    goto error2;
728e66f31c5Sopenharmony_ci
729e66f31c5Sopenharmony_ci  err = pthread_cond_init(cond, &attr);
730e66f31c5Sopenharmony_ci  if (err)
731e66f31c5Sopenharmony_ci    goto error2;
732e66f31c5Sopenharmony_ci
733e66f31c5Sopenharmony_ci  err = pthread_condattr_destroy(&attr);
734e66f31c5Sopenharmony_ci  if (err)
735e66f31c5Sopenharmony_ci    goto error;
736e66f31c5Sopenharmony_ci
737e66f31c5Sopenharmony_ci  return 0;
738e66f31c5Sopenharmony_ci
739e66f31c5Sopenharmony_cierror:
740e66f31c5Sopenharmony_ci  pthread_cond_destroy(cond);
741e66f31c5Sopenharmony_cierror2:
742e66f31c5Sopenharmony_ci  pthread_condattr_destroy(&attr);
743e66f31c5Sopenharmony_ci  return UV__ERR(err);
744e66f31c5Sopenharmony_ci}
745e66f31c5Sopenharmony_ci
746e66f31c5Sopenharmony_ci#endif /* defined(__APPLE__) && defined(__MACH__) */
747e66f31c5Sopenharmony_ci
748e66f31c5Sopenharmony_civoid uv_cond_destroy(uv_cond_t* cond) {
749e66f31c5Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
750e66f31c5Sopenharmony_ci  /* It has been reported that destroying condition variables that have been
751e66f31c5Sopenharmony_ci   * signalled but not waited on can sometimes result in application crashes.
752e66f31c5Sopenharmony_ci   * See https://codereview.chromium.org/1323293005.
753e66f31c5Sopenharmony_ci   */
754e66f31c5Sopenharmony_ci  pthread_mutex_t mutex;
755e66f31c5Sopenharmony_ci  struct timespec ts;
756e66f31c5Sopenharmony_ci  int err;
757e66f31c5Sopenharmony_ci
758e66f31c5Sopenharmony_ci  if (pthread_mutex_init(&mutex, NULL))
759e66f31c5Sopenharmony_ci    abort();
760e66f31c5Sopenharmony_ci
761e66f31c5Sopenharmony_ci  if (pthread_mutex_lock(&mutex))
762e66f31c5Sopenharmony_ci    abort();
763e66f31c5Sopenharmony_ci
764e66f31c5Sopenharmony_ci  ts.tv_sec = 0;
765e66f31c5Sopenharmony_ci  ts.tv_nsec = 1;
766e66f31c5Sopenharmony_ci
767e66f31c5Sopenharmony_ci  err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
768e66f31c5Sopenharmony_ci  if (err != 0 && err != ETIMEDOUT)
769e66f31c5Sopenharmony_ci    abort();
770e66f31c5Sopenharmony_ci
771e66f31c5Sopenharmony_ci  if (pthread_mutex_unlock(&mutex))
772e66f31c5Sopenharmony_ci    abort();
773e66f31c5Sopenharmony_ci
774e66f31c5Sopenharmony_ci  if (pthread_mutex_destroy(&mutex))
775e66f31c5Sopenharmony_ci    abort();
776e66f31c5Sopenharmony_ci#endif /* defined(__APPLE__) && defined(__MACH__) */
777e66f31c5Sopenharmony_ci
778e66f31c5Sopenharmony_ci  if (pthread_cond_destroy(cond))
779e66f31c5Sopenharmony_ci    abort();
780e66f31c5Sopenharmony_ci}
781e66f31c5Sopenharmony_ci
782e66f31c5Sopenharmony_civoid uv_cond_signal(uv_cond_t* cond) {
783e66f31c5Sopenharmony_ci  if (pthread_cond_signal(cond))
784e66f31c5Sopenharmony_ci    abort();
785e66f31c5Sopenharmony_ci}
786e66f31c5Sopenharmony_ci
787e66f31c5Sopenharmony_civoid uv_cond_broadcast(uv_cond_t* cond) {
788e66f31c5Sopenharmony_ci  if (pthread_cond_broadcast(cond))
789e66f31c5Sopenharmony_ci    abort();
790e66f31c5Sopenharmony_ci}
791e66f31c5Sopenharmony_ci
792e66f31c5Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
793e66f31c5Sopenharmony_ci
794e66f31c5Sopenharmony_civoid uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
795e66f31c5Sopenharmony_ci  int r;
796e66f31c5Sopenharmony_ci
797e66f31c5Sopenharmony_ci  errno = 0;
798e66f31c5Sopenharmony_ci  r = pthread_cond_wait(cond, mutex);
799e66f31c5Sopenharmony_ci
800e66f31c5Sopenharmony_ci  /* Workaround for a bug in OS X at least up to 13.6
801e66f31c5Sopenharmony_ci   * See https://github.com/libuv/libuv/issues/4165
802e66f31c5Sopenharmony_ci   */
803e66f31c5Sopenharmony_ci  if (r == EINVAL)
804e66f31c5Sopenharmony_ci    if (errno == EBUSY)
805e66f31c5Sopenharmony_ci      return;
806e66f31c5Sopenharmony_ci
807e66f31c5Sopenharmony_ci  if (r)
808e66f31c5Sopenharmony_ci    abort();
809e66f31c5Sopenharmony_ci}
810e66f31c5Sopenharmony_ci
811e66f31c5Sopenharmony_ci#else /* !(defined(__APPLE__) && defined(__MACH__)) */
812e66f31c5Sopenharmony_ci
813e66f31c5Sopenharmony_civoid uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
814e66f31c5Sopenharmony_ci  if (pthread_cond_wait(cond, mutex))
815e66f31c5Sopenharmony_ci    abort();
816e66f31c5Sopenharmony_ci}
817e66f31c5Sopenharmony_ci
818e66f31c5Sopenharmony_ci#endif
819e66f31c5Sopenharmony_ci
820e66f31c5Sopenharmony_ciint uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
821e66f31c5Sopenharmony_ci  int r;
822e66f31c5Sopenharmony_ci  struct timespec ts;
823e66f31c5Sopenharmony_ci#if defined(__MVS__)
824e66f31c5Sopenharmony_ci  struct timeval tv;
825e66f31c5Sopenharmony_ci#endif
826e66f31c5Sopenharmony_ci
827e66f31c5Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
828e66f31c5Sopenharmony_ci  ts.tv_sec = timeout / NANOSEC;
829e66f31c5Sopenharmony_ci  ts.tv_nsec = timeout % NANOSEC;
830e66f31c5Sopenharmony_ci  r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
831e66f31c5Sopenharmony_ci#else
832e66f31c5Sopenharmony_ci#if defined(__MVS__)
833e66f31c5Sopenharmony_ci  if (gettimeofday(&tv, NULL))
834e66f31c5Sopenharmony_ci    abort();
835e66f31c5Sopenharmony_ci  timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
836e66f31c5Sopenharmony_ci#else
837e66f31c5Sopenharmony_ci  timeout += uv__hrtime(UV_CLOCK_PRECISE);
838e66f31c5Sopenharmony_ci#endif
839e66f31c5Sopenharmony_ci  ts.tv_sec = timeout / NANOSEC;
840e66f31c5Sopenharmony_ci  ts.tv_nsec = timeout % NANOSEC;
841e66f31c5Sopenharmony_ci  r = pthread_cond_timedwait(cond, mutex, &ts);
842e66f31c5Sopenharmony_ci#endif
843e66f31c5Sopenharmony_ci
844e66f31c5Sopenharmony_ci
845e66f31c5Sopenharmony_ci  if (r == 0)
846e66f31c5Sopenharmony_ci    return 0;
847e66f31c5Sopenharmony_ci
848e66f31c5Sopenharmony_ci  if (r == ETIMEDOUT)
849e66f31c5Sopenharmony_ci    return UV_ETIMEDOUT;
850e66f31c5Sopenharmony_ci
851e66f31c5Sopenharmony_ci  abort();
852e66f31c5Sopenharmony_ci#ifndef __SUNPRO_C
853e66f31c5Sopenharmony_ci  return UV_EINVAL;  /* Satisfy the compiler. */
854e66f31c5Sopenharmony_ci#endif
855e66f31c5Sopenharmony_ci}
856e66f31c5Sopenharmony_ci
857e66f31c5Sopenharmony_ci
858e66f31c5Sopenharmony_ciint uv_key_create(uv_key_t* key) {
859e66f31c5Sopenharmony_ci  return UV__ERR(pthread_key_create(key, NULL));
860e66f31c5Sopenharmony_ci}
861e66f31c5Sopenharmony_ci
862e66f31c5Sopenharmony_ci
863e66f31c5Sopenharmony_civoid uv_key_delete(uv_key_t* key) {
864e66f31c5Sopenharmony_ci  if (pthread_key_delete(*key))
865e66f31c5Sopenharmony_ci    abort();
866e66f31c5Sopenharmony_ci}
867e66f31c5Sopenharmony_ci
868e66f31c5Sopenharmony_ci
869e66f31c5Sopenharmony_civoid* uv_key_get(uv_key_t* key) {
870e66f31c5Sopenharmony_ci  return pthread_getspecific(*key);
871e66f31c5Sopenharmony_ci}
872e66f31c5Sopenharmony_ci
873e66f31c5Sopenharmony_ci
874e66f31c5Sopenharmony_civoid uv_key_set(uv_key_t* key, void* value) {
875e66f31c5Sopenharmony_ci  if (pthread_setspecific(*key, value))
876e66f31c5Sopenharmony_ci    abort();
877e66f31c5Sopenharmony_ci}
878