11cb0ef41Sopenharmony_ci/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
41cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to
51cb0ef41Sopenharmony_ci * deal in the Software without restriction, including without limitation the
61cb0ef41Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
71cb0ef41Sopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is
81cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
91cb0ef41Sopenharmony_ci *
101cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
111cb0ef41Sopenharmony_ci * all copies or substantial portions of the Software.
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
141cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
151cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
161cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
171cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
181cb0ef41Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
191cb0ef41Sopenharmony_ci * IN THE SOFTWARE.
201cb0ef41Sopenharmony_ci */
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#include "uv.h"
231cb0ef41Sopenharmony_ci#include "internal.h"
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci#include <pthread.h>
261cb0ef41Sopenharmony_ci#include <assert.h>
271cb0ef41Sopenharmony_ci#include <errno.h>
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include <sys/time.h>
301cb0ef41Sopenharmony_ci#include <sys/resource.h>  /* getrlimit() */
311cb0ef41Sopenharmony_ci#include <unistd.h>  /* getpagesize() */
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci#include <limits.h>
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci#ifdef __MVS__
361cb0ef41Sopenharmony_ci#include <sys/ipc.h>
371cb0ef41Sopenharmony_ci#include <sys/sem.h>
381cb0ef41Sopenharmony_ci#endif
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#if defined(__GLIBC__) && !defined(__UCLIBC__)
411cb0ef41Sopenharmony_ci#include <gnu/libc-version.h>  /* gnu_get_libc_version() */
421cb0ef41Sopenharmony_ci#endif
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci#undef NANOSEC
451cb0ef41Sopenharmony_ci#define NANOSEC ((uint64_t) 1e9)
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci#if defined(PTHREAD_BARRIER_SERIAL_THREAD)
481cb0ef41Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
491cb0ef41Sopenharmony_ci#endif
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci/* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
521cb0ef41Sopenharmony_ci#if defined(_AIX) || \
531cb0ef41Sopenharmony_ci    defined(__OpenBSD__) || \
541cb0ef41Sopenharmony_ci    !defined(PTHREAD_BARRIER_SERIAL_THREAD)
551cb0ef41Sopenharmony_ciint uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
561cb0ef41Sopenharmony_ci  struct _uv_barrier* b;
571cb0ef41Sopenharmony_ci  int rc;
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  if (barrier == NULL || count == 0)
601cb0ef41Sopenharmony_ci    return UV_EINVAL;
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  b = uv__malloc(sizeof(*b));
631cb0ef41Sopenharmony_ci  if (b == NULL)
641cb0ef41Sopenharmony_ci    return UV_ENOMEM;
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  b->in = 0;
671cb0ef41Sopenharmony_ci  b->out = 0;
681cb0ef41Sopenharmony_ci  b->threshold = count;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  rc = uv_mutex_init(&b->mutex);
711cb0ef41Sopenharmony_ci  if (rc != 0)
721cb0ef41Sopenharmony_ci    goto error2;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  rc = uv_cond_init(&b->cond);
751cb0ef41Sopenharmony_ci  if (rc != 0)
761cb0ef41Sopenharmony_ci    goto error;
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  barrier->b = b;
791cb0ef41Sopenharmony_ci  return 0;
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_cierror:
821cb0ef41Sopenharmony_ci  uv_mutex_destroy(&b->mutex);
831cb0ef41Sopenharmony_cierror2:
841cb0ef41Sopenharmony_ci  uv__free(b);
851cb0ef41Sopenharmony_ci  return rc;
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ciint uv_barrier_wait(uv_barrier_t* barrier) {
901cb0ef41Sopenharmony_ci  struct _uv_barrier* b;
911cb0ef41Sopenharmony_ci  int last;
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  if (barrier == NULL || barrier->b == NULL)
941cb0ef41Sopenharmony_ci    return UV_EINVAL;
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  b = barrier->b;
971cb0ef41Sopenharmony_ci  uv_mutex_lock(&b->mutex);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  if (++b->in == b->threshold) {
1001cb0ef41Sopenharmony_ci    b->in = 0;
1011cb0ef41Sopenharmony_ci    b->out = b->threshold;
1021cb0ef41Sopenharmony_ci    uv_cond_signal(&b->cond);
1031cb0ef41Sopenharmony_ci  } else {
1041cb0ef41Sopenharmony_ci    do
1051cb0ef41Sopenharmony_ci      uv_cond_wait(&b->cond, &b->mutex);
1061cb0ef41Sopenharmony_ci    while (b->in != 0);
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  last = (--b->out == 0);
1101cb0ef41Sopenharmony_ci  uv_cond_signal(&b->cond);
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  uv_mutex_unlock(&b->mutex);
1131cb0ef41Sopenharmony_ci  return last;
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_civoid uv_barrier_destroy(uv_barrier_t* barrier) {
1181cb0ef41Sopenharmony_ci  struct _uv_barrier* b;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  b = barrier->b;
1211cb0ef41Sopenharmony_ci  uv_mutex_lock(&b->mutex);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  assert(b->in == 0);
1241cb0ef41Sopenharmony_ci  while (b->out != 0)
1251cb0ef41Sopenharmony_ci    uv_cond_wait(&b->cond, &b->mutex);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  if (b->in != 0)
1281cb0ef41Sopenharmony_ci    abort();
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  uv_mutex_unlock(&b->mutex);
1311cb0ef41Sopenharmony_ci  uv_mutex_destroy(&b->mutex);
1321cb0ef41Sopenharmony_ci  uv_cond_destroy(&b->cond);
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  uv__free(barrier->b);
1351cb0ef41Sopenharmony_ci  barrier->b = NULL;
1361cb0ef41Sopenharmony_ci}
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci#else
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ciint uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
1411cb0ef41Sopenharmony_ci  return UV__ERR(pthread_barrier_init(barrier, NULL, count));
1421cb0ef41Sopenharmony_ci}
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ciint uv_barrier_wait(uv_barrier_t* barrier) {
1461cb0ef41Sopenharmony_ci  int rc;
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  rc = pthread_barrier_wait(barrier);
1491cb0ef41Sopenharmony_ci  if (rc != 0)
1501cb0ef41Sopenharmony_ci    if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
1511cb0ef41Sopenharmony_ci      abort();
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  return rc == PTHREAD_BARRIER_SERIAL_THREAD;
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_civoid uv_barrier_destroy(uv_barrier_t* barrier) {
1581cb0ef41Sopenharmony_ci  if (pthread_barrier_destroy(barrier))
1591cb0ef41Sopenharmony_ci    abort();
1601cb0ef41Sopenharmony_ci}
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci#endif
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci/* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
1661cb0ef41Sopenharmony_ci * too small to safely receive signals on.
1671cb0ef41Sopenharmony_ci *
1681cb0ef41Sopenharmony_ci * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
1691cb0ef41Sopenharmony_ci * the largest MINSIGSTKSZ of the architectures that musl supports) so
1701cb0ef41Sopenharmony_ci * let's use that as a lower bound.
1711cb0ef41Sopenharmony_ci *
1721cb0ef41Sopenharmony_ci * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
1731cb0ef41Sopenharmony_ci * is between 28 and 133 KB when compiling against glibc, depending
1741cb0ef41Sopenharmony_ci * on the architecture.
1751cb0ef41Sopenharmony_ci */
1761cb0ef41Sopenharmony_cistatic size_t uv__min_stack_size(void) {
1771cb0ef41Sopenharmony_ci  static const size_t min = 8192;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci#ifdef PTHREAD_STACK_MIN  /* Not defined on NetBSD. */
1801cb0ef41Sopenharmony_ci  if (min < (size_t) PTHREAD_STACK_MIN)
1811cb0ef41Sopenharmony_ci    return PTHREAD_STACK_MIN;
1821cb0ef41Sopenharmony_ci#endif  /* PTHREAD_STACK_MIN */
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  return min;
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci/* On Linux, threads created by musl have a much smaller stack than threads
1891cb0ef41Sopenharmony_ci * created by glibc (80 vs. 2048 or 4096 kB.)  Follow glibc for consistency.
1901cb0ef41Sopenharmony_ci */
1911cb0ef41Sopenharmony_cistatic size_t uv__default_stack_size(void) {
1921cb0ef41Sopenharmony_ci#if !defined(__linux__)
1931cb0ef41Sopenharmony_ci  return 0;
1941cb0ef41Sopenharmony_ci#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
1951cb0ef41Sopenharmony_ci  return 4 << 20;  /* glibc default. */
1961cb0ef41Sopenharmony_ci#else
1971cb0ef41Sopenharmony_ci  return 2 << 20;  /* glibc default. */
1981cb0ef41Sopenharmony_ci#endif
1991cb0ef41Sopenharmony_ci}
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci/* On MacOS, threads other than the main thread are created with a reduced
2031cb0ef41Sopenharmony_ci * stack size by default.  Adjust to RLIMIT_STACK aligned to the page size.
2041cb0ef41Sopenharmony_ci */
2051cb0ef41Sopenharmony_cisize_t uv__thread_stack_size(void) {
2061cb0ef41Sopenharmony_ci#if defined(__APPLE__) || defined(__linux__)
2071cb0ef41Sopenharmony_ci  struct rlimit lim;
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  /* getrlimit() can fail on some aarch64 systems due to a glibc bug where
2101cb0ef41Sopenharmony_ci   * the system call wrapper invokes the wrong system call. Don't treat
2111cb0ef41Sopenharmony_ci   * that as fatal, just use the default stack size instead.
2121cb0ef41Sopenharmony_ci   */
2131cb0ef41Sopenharmony_ci  if (getrlimit(RLIMIT_STACK, &lim))
2141cb0ef41Sopenharmony_ci    return uv__default_stack_size();
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  if (lim.rlim_cur == RLIM_INFINITY)
2171cb0ef41Sopenharmony_ci    return uv__default_stack_size();
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  /* pthread_attr_setstacksize() expects page-aligned values. */
2201cb0ef41Sopenharmony_ci  lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  if (lim.rlim_cur >= (rlim_t) uv__min_stack_size())
2231cb0ef41Sopenharmony_ci    return lim.rlim_cur;
2241cb0ef41Sopenharmony_ci#endif
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  return uv__default_stack_size();
2271cb0ef41Sopenharmony_ci}
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ciint uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
2311cb0ef41Sopenharmony_ci  uv_thread_options_t params;
2321cb0ef41Sopenharmony_ci  params.flags = UV_THREAD_NO_FLAGS;
2331cb0ef41Sopenharmony_ci  return uv_thread_create_ex(tid, &params, entry, arg);
2341cb0ef41Sopenharmony_ci}
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ciint uv_thread_create_ex(uv_thread_t* tid,
2371cb0ef41Sopenharmony_ci                        const uv_thread_options_t* params,
2381cb0ef41Sopenharmony_ci                        void (*entry)(void *arg),
2391cb0ef41Sopenharmony_ci                        void *arg) {
2401cb0ef41Sopenharmony_ci  int err;
2411cb0ef41Sopenharmony_ci  pthread_attr_t* attr;
2421cb0ef41Sopenharmony_ci  pthread_attr_t attr_storage;
2431cb0ef41Sopenharmony_ci  size_t pagesize;
2441cb0ef41Sopenharmony_ci  size_t stack_size;
2451cb0ef41Sopenharmony_ci  size_t min_stack_size;
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  /* Used to squelch a -Wcast-function-type warning. */
2481cb0ef41Sopenharmony_ci  union {
2491cb0ef41Sopenharmony_ci    void (*in)(void*);
2501cb0ef41Sopenharmony_ci    void* (*out)(void*);
2511cb0ef41Sopenharmony_ci  } f;
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  stack_size =
2541cb0ef41Sopenharmony_ci      params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  attr = NULL;
2571cb0ef41Sopenharmony_ci  if (stack_size == 0) {
2581cb0ef41Sopenharmony_ci    stack_size = uv__thread_stack_size();
2591cb0ef41Sopenharmony_ci  } else {
2601cb0ef41Sopenharmony_ci    pagesize = (size_t)getpagesize();
2611cb0ef41Sopenharmony_ci    /* Round up to the nearest page boundary. */
2621cb0ef41Sopenharmony_ci    stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
2631cb0ef41Sopenharmony_ci    min_stack_size = uv__min_stack_size();
2641cb0ef41Sopenharmony_ci    if (stack_size < min_stack_size)
2651cb0ef41Sopenharmony_ci      stack_size = min_stack_size;
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  if (stack_size > 0) {
2691cb0ef41Sopenharmony_ci    attr = &attr_storage;
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci    if (pthread_attr_init(attr))
2721cb0ef41Sopenharmony_ci      abort();
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci    if (pthread_attr_setstacksize(attr, stack_size))
2751cb0ef41Sopenharmony_ci      abort();
2761cb0ef41Sopenharmony_ci  }
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci  f.in = entry;
2791cb0ef41Sopenharmony_ci  err = pthread_create(tid, attr, f.out, arg);
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  if (attr != NULL)
2821cb0ef41Sopenharmony_ci    pthread_attr_destroy(attr);
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  return UV__ERR(err);
2851cb0ef41Sopenharmony_ci}
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ciuv_thread_t uv_thread_self(void) {
2891cb0ef41Sopenharmony_ci  return pthread_self();
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ciint uv_thread_join(uv_thread_t *tid) {
2931cb0ef41Sopenharmony_ci  return UV__ERR(pthread_join(*tid, NULL));
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ciint uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
2981cb0ef41Sopenharmony_ci  return pthread_equal(*t1, *t2);
2991cb0ef41Sopenharmony_ci}
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ciint uv_mutex_init(uv_mutex_t* mutex) {
3031cb0ef41Sopenharmony_ci#if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
3041cb0ef41Sopenharmony_ci  return UV__ERR(pthread_mutex_init(mutex, NULL));
3051cb0ef41Sopenharmony_ci#else
3061cb0ef41Sopenharmony_ci  pthread_mutexattr_t attr;
3071cb0ef41Sopenharmony_ci  int err;
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  if (pthread_mutexattr_init(&attr))
3101cb0ef41Sopenharmony_ci    abort();
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
3131cb0ef41Sopenharmony_ci    abort();
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  err = pthread_mutex_init(mutex, &attr);
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci  if (pthread_mutexattr_destroy(&attr))
3181cb0ef41Sopenharmony_ci    abort();
3191cb0ef41Sopenharmony_ci
3201cb0ef41Sopenharmony_ci  return UV__ERR(err);
3211cb0ef41Sopenharmony_ci#endif
3221cb0ef41Sopenharmony_ci}
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ciint uv_mutex_init_recursive(uv_mutex_t* mutex) {
3261cb0ef41Sopenharmony_ci  pthread_mutexattr_t attr;
3271cb0ef41Sopenharmony_ci  int err;
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci  if (pthread_mutexattr_init(&attr))
3301cb0ef41Sopenharmony_ci    abort();
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
3331cb0ef41Sopenharmony_ci    abort();
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  err = pthread_mutex_init(mutex, &attr);
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  if (pthread_mutexattr_destroy(&attr))
3381cb0ef41Sopenharmony_ci    abort();
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  return UV__ERR(err);
3411cb0ef41Sopenharmony_ci}
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_civoid uv_mutex_destroy(uv_mutex_t* mutex) {
3451cb0ef41Sopenharmony_ci  if (pthread_mutex_destroy(mutex))
3461cb0ef41Sopenharmony_ci    abort();
3471cb0ef41Sopenharmony_ci}
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_civoid uv_mutex_lock(uv_mutex_t* mutex) {
3511cb0ef41Sopenharmony_ci  if (pthread_mutex_lock(mutex))
3521cb0ef41Sopenharmony_ci    abort();
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ciint uv_mutex_trylock(uv_mutex_t* mutex) {
3571cb0ef41Sopenharmony_ci  int err;
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci  err = pthread_mutex_trylock(mutex);
3601cb0ef41Sopenharmony_ci  if (err) {
3611cb0ef41Sopenharmony_ci    if (err != EBUSY && err != EAGAIN)
3621cb0ef41Sopenharmony_ci      abort();
3631cb0ef41Sopenharmony_ci    return UV_EBUSY;
3641cb0ef41Sopenharmony_ci  }
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  return 0;
3671cb0ef41Sopenharmony_ci}
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_civoid uv_mutex_unlock(uv_mutex_t* mutex) {
3711cb0ef41Sopenharmony_ci  if (pthread_mutex_unlock(mutex))
3721cb0ef41Sopenharmony_ci    abort();
3731cb0ef41Sopenharmony_ci}
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ciint uv_rwlock_init(uv_rwlock_t* rwlock) {
3771cb0ef41Sopenharmony_ci  return UV__ERR(pthread_rwlock_init(rwlock, NULL));
3781cb0ef41Sopenharmony_ci}
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_civoid uv_rwlock_destroy(uv_rwlock_t* rwlock) {
3821cb0ef41Sopenharmony_ci  if (pthread_rwlock_destroy(rwlock))
3831cb0ef41Sopenharmony_ci    abort();
3841cb0ef41Sopenharmony_ci}
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_civoid uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
3881cb0ef41Sopenharmony_ci  if (pthread_rwlock_rdlock(rwlock))
3891cb0ef41Sopenharmony_ci    abort();
3901cb0ef41Sopenharmony_ci}
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ciint uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
3941cb0ef41Sopenharmony_ci  int err;
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  err = pthread_rwlock_tryrdlock(rwlock);
3971cb0ef41Sopenharmony_ci  if (err) {
3981cb0ef41Sopenharmony_ci    if (err != EBUSY && err != EAGAIN)
3991cb0ef41Sopenharmony_ci      abort();
4001cb0ef41Sopenharmony_ci    return UV_EBUSY;
4011cb0ef41Sopenharmony_ci  }
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci  return 0;
4041cb0ef41Sopenharmony_ci}
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_civoid uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
4081cb0ef41Sopenharmony_ci  if (pthread_rwlock_unlock(rwlock))
4091cb0ef41Sopenharmony_ci    abort();
4101cb0ef41Sopenharmony_ci}
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_civoid uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
4141cb0ef41Sopenharmony_ci  if (pthread_rwlock_wrlock(rwlock))
4151cb0ef41Sopenharmony_ci    abort();
4161cb0ef41Sopenharmony_ci}
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ciint uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
4201cb0ef41Sopenharmony_ci  int err;
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci  err = pthread_rwlock_trywrlock(rwlock);
4231cb0ef41Sopenharmony_ci  if (err) {
4241cb0ef41Sopenharmony_ci    if (err != EBUSY && err != EAGAIN)
4251cb0ef41Sopenharmony_ci      abort();
4261cb0ef41Sopenharmony_ci    return UV_EBUSY;
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  return 0;
4301cb0ef41Sopenharmony_ci}
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_civoid uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
4341cb0ef41Sopenharmony_ci  if (pthread_rwlock_unlock(rwlock))
4351cb0ef41Sopenharmony_ci    abort();
4361cb0ef41Sopenharmony_ci}
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_civoid uv_once(uv_once_t* guard, void (*callback)(void)) {
4401cb0ef41Sopenharmony_ci  if (pthread_once(guard, callback))
4411cb0ef41Sopenharmony_ci    abort();
4421cb0ef41Sopenharmony_ci}
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ciint uv_sem_init(uv_sem_t* sem, unsigned int value) {
4471cb0ef41Sopenharmony_ci  kern_return_t err;
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci  err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
4501cb0ef41Sopenharmony_ci  if (err == KERN_SUCCESS)
4511cb0ef41Sopenharmony_ci    return 0;
4521cb0ef41Sopenharmony_ci  if (err == KERN_INVALID_ARGUMENT)
4531cb0ef41Sopenharmony_ci    return UV_EINVAL;
4541cb0ef41Sopenharmony_ci  if (err == KERN_RESOURCE_SHORTAGE)
4551cb0ef41Sopenharmony_ci    return UV_ENOMEM;
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci  abort();
4581cb0ef41Sopenharmony_ci  return UV_EINVAL;  /* Satisfy the compiler. */
4591cb0ef41Sopenharmony_ci}
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_civoid uv_sem_destroy(uv_sem_t* sem) {
4631cb0ef41Sopenharmony_ci  if (semaphore_destroy(mach_task_self(), *sem))
4641cb0ef41Sopenharmony_ci    abort();
4651cb0ef41Sopenharmony_ci}
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_civoid uv_sem_post(uv_sem_t* sem) {
4691cb0ef41Sopenharmony_ci  if (semaphore_signal(*sem))
4701cb0ef41Sopenharmony_ci    abort();
4711cb0ef41Sopenharmony_ci}
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_civoid uv_sem_wait(uv_sem_t* sem) {
4751cb0ef41Sopenharmony_ci  int r;
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  do
4781cb0ef41Sopenharmony_ci    r = semaphore_wait(*sem);
4791cb0ef41Sopenharmony_ci  while (r == KERN_ABORTED);
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci  if (r != KERN_SUCCESS)
4821cb0ef41Sopenharmony_ci    abort();
4831cb0ef41Sopenharmony_ci}
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ciint uv_sem_trywait(uv_sem_t* sem) {
4871cb0ef41Sopenharmony_ci  mach_timespec_t interval;
4881cb0ef41Sopenharmony_ci  kern_return_t err;
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci  interval.tv_sec = 0;
4911cb0ef41Sopenharmony_ci  interval.tv_nsec = 0;
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  err = semaphore_timedwait(*sem, interval);
4941cb0ef41Sopenharmony_ci  if (err == KERN_SUCCESS)
4951cb0ef41Sopenharmony_ci    return 0;
4961cb0ef41Sopenharmony_ci  if (err == KERN_OPERATION_TIMED_OUT)
4971cb0ef41Sopenharmony_ci    return UV_EAGAIN;
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci  abort();
5001cb0ef41Sopenharmony_ci  return UV_EINVAL;  /* Satisfy the compiler. */
5011cb0ef41Sopenharmony_ci}
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci#else /* !(defined(__APPLE__) && defined(__MACH__)) */
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci#if defined(__GLIBC__) && !defined(__UCLIBC__)
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci/* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
5081cb0ef41Sopenharmony_ci * by providing a custom implementation for glibc < 2.21 in terms of other
5091cb0ef41Sopenharmony_ci * concurrency primitives.
5101cb0ef41Sopenharmony_ci * Refs: https://github.com/nodejs/node/issues/19903 */
5111cb0ef41Sopenharmony_ci
5121cb0ef41Sopenharmony_ci/* To preserve ABI compatibility, we treat the uv_sem_t as storage for
5131cb0ef41Sopenharmony_ci * a pointer to the actual struct we're using underneath. */
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_cistatic uv_once_t glibc_version_check_once = UV_ONCE_INIT;
5161cb0ef41Sopenharmony_cistatic int platform_needs_custom_semaphore = 0;
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_cistatic void glibc_version_check(void) {
5191cb0ef41Sopenharmony_ci  const char* version = gnu_get_libc_version();
5201cb0ef41Sopenharmony_ci  platform_needs_custom_semaphore =
5211cb0ef41Sopenharmony_ci      version[0] == '2' && version[1] == '.' &&
5221cb0ef41Sopenharmony_ci      atoi(version + 2) < 21;
5231cb0ef41Sopenharmony_ci}
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci#elif defined(__MVS__)
5261cb0ef41Sopenharmony_ci
5271cb0ef41Sopenharmony_ci#define platform_needs_custom_semaphore 1
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_ci#else /* !defined(__GLIBC__) && !defined(__MVS__) */
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci#define platform_needs_custom_semaphore 0
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci#endif
5341cb0ef41Sopenharmony_ci
5351cb0ef41Sopenharmony_citypedef struct uv_semaphore_s {
5361cb0ef41Sopenharmony_ci  uv_mutex_t mutex;
5371cb0ef41Sopenharmony_ci  uv_cond_t cond;
5381cb0ef41Sopenharmony_ci  unsigned int value;
5391cb0ef41Sopenharmony_ci} uv_semaphore_t;
5401cb0ef41Sopenharmony_ci
5411cb0ef41Sopenharmony_ci#if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
5421cb0ef41Sopenharmony_ci    platform_needs_custom_semaphore
5431cb0ef41Sopenharmony_ciSTATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
5441cb0ef41Sopenharmony_ci#endif
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_cistatic int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
5471cb0ef41Sopenharmony_ci  int err;
5481cb0ef41Sopenharmony_ci  uv_semaphore_t* sem;
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci  sem = uv__malloc(sizeof(*sem));
5511cb0ef41Sopenharmony_ci  if (sem == NULL)
5521cb0ef41Sopenharmony_ci    return UV_ENOMEM;
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  if ((err = uv_mutex_init(&sem->mutex)) != 0) {
5551cb0ef41Sopenharmony_ci    uv__free(sem);
5561cb0ef41Sopenharmony_ci    return err;
5571cb0ef41Sopenharmony_ci  }
5581cb0ef41Sopenharmony_ci
5591cb0ef41Sopenharmony_ci  if ((err = uv_cond_init(&sem->cond)) != 0) {
5601cb0ef41Sopenharmony_ci    uv_mutex_destroy(&sem->mutex);
5611cb0ef41Sopenharmony_ci    uv__free(sem);
5621cb0ef41Sopenharmony_ci    return err;
5631cb0ef41Sopenharmony_ci  }
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  sem->value = value;
5661cb0ef41Sopenharmony_ci  *(uv_semaphore_t**)sem_ = sem;
5671cb0ef41Sopenharmony_ci  return 0;
5681cb0ef41Sopenharmony_ci}
5691cb0ef41Sopenharmony_ci
5701cb0ef41Sopenharmony_ci
5711cb0ef41Sopenharmony_cistatic void uv__custom_sem_destroy(uv_sem_t* sem_) {
5721cb0ef41Sopenharmony_ci  uv_semaphore_t* sem;
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
5751cb0ef41Sopenharmony_ci  uv_cond_destroy(&sem->cond);
5761cb0ef41Sopenharmony_ci  uv_mutex_destroy(&sem->mutex);
5771cb0ef41Sopenharmony_ci  uv__free(sem);
5781cb0ef41Sopenharmony_ci}
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci
5811cb0ef41Sopenharmony_cistatic void uv__custom_sem_post(uv_sem_t* sem_) {
5821cb0ef41Sopenharmony_ci  uv_semaphore_t* sem;
5831cb0ef41Sopenharmony_ci
5841cb0ef41Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
5851cb0ef41Sopenharmony_ci  uv_mutex_lock(&sem->mutex);
5861cb0ef41Sopenharmony_ci  sem->value++;
5871cb0ef41Sopenharmony_ci  if (sem->value == 1)
5881cb0ef41Sopenharmony_ci    uv_cond_signal(&sem->cond);
5891cb0ef41Sopenharmony_ci  uv_mutex_unlock(&sem->mutex);
5901cb0ef41Sopenharmony_ci}
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_cistatic void uv__custom_sem_wait(uv_sem_t* sem_) {
5941cb0ef41Sopenharmony_ci  uv_semaphore_t* sem;
5951cb0ef41Sopenharmony_ci
5961cb0ef41Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
5971cb0ef41Sopenharmony_ci  uv_mutex_lock(&sem->mutex);
5981cb0ef41Sopenharmony_ci  while (sem->value == 0)
5991cb0ef41Sopenharmony_ci    uv_cond_wait(&sem->cond, &sem->mutex);
6001cb0ef41Sopenharmony_ci  sem->value--;
6011cb0ef41Sopenharmony_ci  uv_mutex_unlock(&sem->mutex);
6021cb0ef41Sopenharmony_ci}
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_cistatic int uv__custom_sem_trywait(uv_sem_t* sem_) {
6061cb0ef41Sopenharmony_ci  uv_semaphore_t* sem;
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci  sem = *(uv_semaphore_t**)sem_;
6091cb0ef41Sopenharmony_ci  if (uv_mutex_trylock(&sem->mutex) != 0)
6101cb0ef41Sopenharmony_ci    return UV_EAGAIN;
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  if (sem->value == 0) {
6131cb0ef41Sopenharmony_ci    uv_mutex_unlock(&sem->mutex);
6141cb0ef41Sopenharmony_ci    return UV_EAGAIN;
6151cb0ef41Sopenharmony_ci  }
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci  sem->value--;
6181cb0ef41Sopenharmony_ci  uv_mutex_unlock(&sem->mutex);
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci  return 0;
6211cb0ef41Sopenharmony_ci}
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_cistatic int uv__sem_init(uv_sem_t* sem, unsigned int value) {
6241cb0ef41Sopenharmony_ci  if (sem_init(sem, 0, value))
6251cb0ef41Sopenharmony_ci    return UV__ERR(errno);
6261cb0ef41Sopenharmony_ci  return 0;
6271cb0ef41Sopenharmony_ci}
6281cb0ef41Sopenharmony_ci
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_cistatic void uv__sem_destroy(uv_sem_t* sem) {
6311cb0ef41Sopenharmony_ci  if (sem_destroy(sem))
6321cb0ef41Sopenharmony_ci    abort();
6331cb0ef41Sopenharmony_ci}
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_cistatic void uv__sem_post(uv_sem_t* sem) {
6371cb0ef41Sopenharmony_ci  if (sem_post(sem))
6381cb0ef41Sopenharmony_ci    abort();
6391cb0ef41Sopenharmony_ci}
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci
6421cb0ef41Sopenharmony_cistatic void uv__sem_wait(uv_sem_t* sem) {
6431cb0ef41Sopenharmony_ci  int r;
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci  do
6461cb0ef41Sopenharmony_ci    r = sem_wait(sem);
6471cb0ef41Sopenharmony_ci  while (r == -1 && errno == EINTR);
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci  if (r)
6501cb0ef41Sopenharmony_ci    abort();
6511cb0ef41Sopenharmony_ci}
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_cistatic int uv__sem_trywait(uv_sem_t* sem) {
6551cb0ef41Sopenharmony_ci  int r;
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ci  do
6581cb0ef41Sopenharmony_ci    r = sem_trywait(sem);
6591cb0ef41Sopenharmony_ci  while (r == -1 && errno == EINTR);
6601cb0ef41Sopenharmony_ci
6611cb0ef41Sopenharmony_ci  if (r) {
6621cb0ef41Sopenharmony_ci    if (errno == EAGAIN)
6631cb0ef41Sopenharmony_ci      return UV_EAGAIN;
6641cb0ef41Sopenharmony_ci    abort();
6651cb0ef41Sopenharmony_ci  }
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci  return 0;
6681cb0ef41Sopenharmony_ci}
6691cb0ef41Sopenharmony_ci
6701cb0ef41Sopenharmony_ciint uv_sem_init(uv_sem_t* sem, unsigned int value) {
6711cb0ef41Sopenharmony_ci#if defined(__GLIBC__) && !defined(__UCLIBC__)
6721cb0ef41Sopenharmony_ci  uv_once(&glibc_version_check_once, glibc_version_check);
6731cb0ef41Sopenharmony_ci#endif
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci  if (platform_needs_custom_semaphore)
6761cb0ef41Sopenharmony_ci    return uv__custom_sem_init(sem, value);
6771cb0ef41Sopenharmony_ci  else
6781cb0ef41Sopenharmony_ci    return uv__sem_init(sem, value);
6791cb0ef41Sopenharmony_ci}
6801cb0ef41Sopenharmony_ci
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_civoid uv_sem_destroy(uv_sem_t* sem) {
6831cb0ef41Sopenharmony_ci  if (platform_needs_custom_semaphore)
6841cb0ef41Sopenharmony_ci    uv__custom_sem_destroy(sem);
6851cb0ef41Sopenharmony_ci  else
6861cb0ef41Sopenharmony_ci    uv__sem_destroy(sem);
6871cb0ef41Sopenharmony_ci}
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ci
6901cb0ef41Sopenharmony_civoid uv_sem_post(uv_sem_t* sem) {
6911cb0ef41Sopenharmony_ci  if (platform_needs_custom_semaphore)
6921cb0ef41Sopenharmony_ci    uv__custom_sem_post(sem);
6931cb0ef41Sopenharmony_ci  else
6941cb0ef41Sopenharmony_ci    uv__sem_post(sem);
6951cb0ef41Sopenharmony_ci}
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_civoid uv_sem_wait(uv_sem_t* sem) {
6991cb0ef41Sopenharmony_ci  if (platform_needs_custom_semaphore)
7001cb0ef41Sopenharmony_ci    uv__custom_sem_wait(sem);
7011cb0ef41Sopenharmony_ci  else
7021cb0ef41Sopenharmony_ci    uv__sem_wait(sem);
7031cb0ef41Sopenharmony_ci}
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ciint uv_sem_trywait(uv_sem_t* sem) {
7071cb0ef41Sopenharmony_ci  if (platform_needs_custom_semaphore)
7081cb0ef41Sopenharmony_ci    return uv__custom_sem_trywait(sem);
7091cb0ef41Sopenharmony_ci  else
7101cb0ef41Sopenharmony_ci    return uv__sem_trywait(sem);
7111cb0ef41Sopenharmony_ci}
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci#endif /* defined(__APPLE__) && defined(__MACH__) */
7141cb0ef41Sopenharmony_ci
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ciint uv_cond_init(uv_cond_t* cond) {
7191cb0ef41Sopenharmony_ci  return UV__ERR(pthread_cond_init(cond, NULL));
7201cb0ef41Sopenharmony_ci}
7211cb0ef41Sopenharmony_ci
7221cb0ef41Sopenharmony_ci#else /* !(defined(__APPLE__) && defined(__MACH__)) */
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ciint uv_cond_init(uv_cond_t* cond) {
7251cb0ef41Sopenharmony_ci  pthread_condattr_t attr;
7261cb0ef41Sopenharmony_ci  int err;
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci  err = pthread_condattr_init(&attr);
7291cb0ef41Sopenharmony_ci  if (err)
7301cb0ef41Sopenharmony_ci    return UV__ERR(err);
7311cb0ef41Sopenharmony_ci
7321cb0ef41Sopenharmony_ci  err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
7331cb0ef41Sopenharmony_ci  if (err)
7341cb0ef41Sopenharmony_ci    goto error2;
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_ci  err = pthread_cond_init(cond, &attr);
7371cb0ef41Sopenharmony_ci  if (err)
7381cb0ef41Sopenharmony_ci    goto error2;
7391cb0ef41Sopenharmony_ci
7401cb0ef41Sopenharmony_ci  err = pthread_condattr_destroy(&attr);
7411cb0ef41Sopenharmony_ci  if (err)
7421cb0ef41Sopenharmony_ci    goto error;
7431cb0ef41Sopenharmony_ci
7441cb0ef41Sopenharmony_ci  return 0;
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_cierror:
7471cb0ef41Sopenharmony_ci  pthread_cond_destroy(cond);
7481cb0ef41Sopenharmony_cierror2:
7491cb0ef41Sopenharmony_ci  pthread_condattr_destroy(&attr);
7501cb0ef41Sopenharmony_ci  return UV__ERR(err);
7511cb0ef41Sopenharmony_ci}
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci#endif /* defined(__APPLE__) && defined(__MACH__) */
7541cb0ef41Sopenharmony_ci
7551cb0ef41Sopenharmony_civoid uv_cond_destroy(uv_cond_t* cond) {
7561cb0ef41Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
7571cb0ef41Sopenharmony_ci  /* It has been reported that destroying condition variables that have been
7581cb0ef41Sopenharmony_ci   * signalled but not waited on can sometimes result in application crashes.
7591cb0ef41Sopenharmony_ci   * See https://codereview.chromium.org/1323293005.
7601cb0ef41Sopenharmony_ci   */
7611cb0ef41Sopenharmony_ci  pthread_mutex_t mutex;
7621cb0ef41Sopenharmony_ci  struct timespec ts;
7631cb0ef41Sopenharmony_ci  int err;
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci  if (pthread_mutex_init(&mutex, NULL))
7661cb0ef41Sopenharmony_ci    abort();
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ci  if (pthread_mutex_lock(&mutex))
7691cb0ef41Sopenharmony_ci    abort();
7701cb0ef41Sopenharmony_ci
7711cb0ef41Sopenharmony_ci  ts.tv_sec = 0;
7721cb0ef41Sopenharmony_ci  ts.tv_nsec = 1;
7731cb0ef41Sopenharmony_ci
7741cb0ef41Sopenharmony_ci  err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
7751cb0ef41Sopenharmony_ci  if (err != 0 && err != ETIMEDOUT)
7761cb0ef41Sopenharmony_ci    abort();
7771cb0ef41Sopenharmony_ci
7781cb0ef41Sopenharmony_ci  if (pthread_mutex_unlock(&mutex))
7791cb0ef41Sopenharmony_ci    abort();
7801cb0ef41Sopenharmony_ci
7811cb0ef41Sopenharmony_ci  if (pthread_mutex_destroy(&mutex))
7821cb0ef41Sopenharmony_ci    abort();
7831cb0ef41Sopenharmony_ci#endif /* defined(__APPLE__) && defined(__MACH__) */
7841cb0ef41Sopenharmony_ci
7851cb0ef41Sopenharmony_ci  if (pthread_cond_destroy(cond))
7861cb0ef41Sopenharmony_ci    abort();
7871cb0ef41Sopenharmony_ci}
7881cb0ef41Sopenharmony_ci
7891cb0ef41Sopenharmony_civoid uv_cond_signal(uv_cond_t* cond) {
7901cb0ef41Sopenharmony_ci  if (pthread_cond_signal(cond))
7911cb0ef41Sopenharmony_ci    abort();
7921cb0ef41Sopenharmony_ci}
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_civoid uv_cond_broadcast(uv_cond_t* cond) {
7951cb0ef41Sopenharmony_ci  if (pthread_cond_broadcast(cond))
7961cb0ef41Sopenharmony_ci    abort();
7971cb0ef41Sopenharmony_ci}
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_civoid uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
8001cb0ef41Sopenharmony_ci  if (pthread_cond_wait(cond, mutex))
8011cb0ef41Sopenharmony_ci    abort();
8021cb0ef41Sopenharmony_ci}
8031cb0ef41Sopenharmony_ci
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ciint uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
8061cb0ef41Sopenharmony_ci  int r;
8071cb0ef41Sopenharmony_ci  struct timespec ts;
8081cb0ef41Sopenharmony_ci#if defined(__MVS__)
8091cb0ef41Sopenharmony_ci  struct timeval tv;
8101cb0ef41Sopenharmony_ci#endif
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ci#if defined(__APPLE__) && defined(__MACH__)
8131cb0ef41Sopenharmony_ci  ts.tv_sec = timeout / NANOSEC;
8141cb0ef41Sopenharmony_ci  ts.tv_nsec = timeout % NANOSEC;
8151cb0ef41Sopenharmony_ci  r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
8161cb0ef41Sopenharmony_ci#else
8171cb0ef41Sopenharmony_ci#if defined(__MVS__)
8181cb0ef41Sopenharmony_ci  if (gettimeofday(&tv, NULL))
8191cb0ef41Sopenharmony_ci    abort();
8201cb0ef41Sopenharmony_ci  timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
8211cb0ef41Sopenharmony_ci#else
8221cb0ef41Sopenharmony_ci  timeout += uv__hrtime(UV_CLOCK_PRECISE);
8231cb0ef41Sopenharmony_ci#endif
8241cb0ef41Sopenharmony_ci  ts.tv_sec = timeout / NANOSEC;
8251cb0ef41Sopenharmony_ci  ts.tv_nsec = timeout % NANOSEC;
8261cb0ef41Sopenharmony_ci  r = pthread_cond_timedwait(cond, mutex, &ts);
8271cb0ef41Sopenharmony_ci#endif
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci
8301cb0ef41Sopenharmony_ci  if (r == 0)
8311cb0ef41Sopenharmony_ci    return 0;
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ci  if (r == ETIMEDOUT)
8341cb0ef41Sopenharmony_ci    return UV_ETIMEDOUT;
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_ci  abort();
8371cb0ef41Sopenharmony_ci#ifndef __SUNPRO_C
8381cb0ef41Sopenharmony_ci  return UV_EINVAL;  /* Satisfy the compiler. */
8391cb0ef41Sopenharmony_ci#endif
8401cb0ef41Sopenharmony_ci}
8411cb0ef41Sopenharmony_ci
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ciint uv_key_create(uv_key_t* key) {
8441cb0ef41Sopenharmony_ci  return UV__ERR(pthread_key_create(key, NULL));
8451cb0ef41Sopenharmony_ci}
8461cb0ef41Sopenharmony_ci
8471cb0ef41Sopenharmony_ci
8481cb0ef41Sopenharmony_civoid uv_key_delete(uv_key_t* key) {
8491cb0ef41Sopenharmony_ci  if (pthread_key_delete(*key))
8501cb0ef41Sopenharmony_ci    abort();
8511cb0ef41Sopenharmony_ci}
8521cb0ef41Sopenharmony_ci
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_civoid* uv_key_get(uv_key_t* key) {
8551cb0ef41Sopenharmony_ci  return pthread_getspecific(*key);
8561cb0ef41Sopenharmony_ci}
8571cb0ef41Sopenharmony_ci
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_civoid uv_key_set(uv_key_t* key, void* value) {
8601cb0ef41Sopenharmony_ci  if (pthread_setspecific(*key, value))
8611cb0ef41Sopenharmony_ci    abort();
8621cb0ef41Sopenharmony_ci}
863