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