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