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, ¶ms, 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