1
0

thread.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  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. #include "uv.h"
  22. #include "internal.h"
  23. #include <pthread.h>
  24. #include <assert.h>
  25. #include <errno.h>
  26. #include <sys/time.h>
  27. #include <sys/resource.h> /* getrlimit() */
  28. #include <unistd.h> /* getpagesize() */
  29. #include <limits.h>
  30. #ifdef __MVS__
  31. #include <sys/ipc.h>
  32. #include <sys/sem.h>
  33. #endif
  34. #if defined(__GLIBC__) && !defined(__UCLIBC__)
  35. #include <gnu/libc-version.h> /* gnu_get_libc_version() */
  36. #endif
  37. #undef NANOSEC
  38. #define NANOSEC ((uint64_t) 1e9)
  39. #if defined(PTHREAD_BARRIER_SERIAL_THREAD)
  40. STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
  41. #endif
  42. /* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
  43. #if defined(_AIX) || \
  44. defined(__OpenBSD__) || \
  45. !defined(PTHREAD_BARRIER_SERIAL_THREAD)
  46. int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
  47. struct _uv_barrier* b;
  48. int rc;
  49. if (barrier == NULL || count == 0)
  50. return UV_EINVAL;
  51. b = uv__malloc(sizeof(*b));
  52. if (b == NULL)
  53. return UV_ENOMEM;
  54. b->in = 0;
  55. b->out = 0;
  56. b->threshold = count;
  57. rc = uv_mutex_init(&b->mutex);
  58. if (rc != 0)
  59. goto error2;
  60. rc = uv_cond_init(&b->cond);
  61. if (rc != 0)
  62. goto error;
  63. barrier->b = b;
  64. return 0;
  65. error:
  66. uv_mutex_destroy(&b->mutex);
  67. error2:
  68. uv__free(b);
  69. return rc;
  70. }
  71. int uv_barrier_wait(uv_barrier_t* barrier) {
  72. struct _uv_barrier* b;
  73. int last;
  74. if (barrier == NULL || barrier->b == NULL)
  75. return UV_EINVAL;
  76. b = barrier->b;
  77. uv_mutex_lock(&b->mutex);
  78. if (++b->in == b->threshold) {
  79. b->in = 0;
  80. b->out = b->threshold;
  81. uv_cond_signal(&b->cond);
  82. } else {
  83. do
  84. uv_cond_wait(&b->cond, &b->mutex);
  85. while (b->in != 0);
  86. }
  87. last = (--b->out == 0);
  88. if (!last)
  89. uv_cond_signal(&b->cond); /* Not needed for last thread. */
  90. uv_mutex_unlock(&b->mutex);
  91. return last;
  92. }
  93. void uv_barrier_destroy(uv_barrier_t* barrier) {
  94. struct _uv_barrier* b;
  95. b = barrier->b;
  96. uv_mutex_lock(&b->mutex);
  97. assert(b->in == 0);
  98. assert(b->out == 0);
  99. if (b->in != 0 || b->out != 0)
  100. abort();
  101. uv_mutex_unlock(&b->mutex);
  102. uv_mutex_destroy(&b->mutex);
  103. uv_cond_destroy(&b->cond);
  104. uv__free(barrier->b);
  105. barrier->b = NULL;
  106. }
  107. #else
  108. int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
  109. return UV__ERR(pthread_barrier_init(barrier, NULL, count));
  110. }
  111. int uv_barrier_wait(uv_barrier_t* barrier) {
  112. int rc;
  113. rc = pthread_barrier_wait(barrier);
  114. if (rc != 0)
  115. if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
  116. abort();
  117. return rc == PTHREAD_BARRIER_SERIAL_THREAD;
  118. }
  119. void uv_barrier_destroy(uv_barrier_t* barrier) {
  120. if (pthread_barrier_destroy(barrier))
  121. abort();
  122. }
  123. #endif
  124. /* On MacOS, threads other than the main thread are created with a reduced
  125. * stack size by default. Adjust to RLIMIT_STACK aligned to the page size.
  126. *
  127. * On Linux, threads created by musl have a much smaller stack than threads
  128. * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency.
  129. */
  130. static size_t thread_stack_size(void) {
  131. #if defined(__APPLE__) || defined(__linux__)
  132. struct rlimit lim;
  133. if (getrlimit(RLIMIT_STACK, &lim))
  134. abort();
  135. if (lim.rlim_cur != RLIM_INFINITY) {
  136. /* pthread_attr_setstacksize() expects page-aligned values. */
  137. lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
  138. /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
  139. * too small to safely receive signals on.
  140. *
  141. * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
  142. * the largest MINSIGSTKSZ of the architectures that musl supports) so
  143. * let's use that as a lower bound.
  144. *
  145. * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
  146. * is between 28 and 133 KB when compiling against glibc, depending
  147. * on the architecture.
  148. */
  149. if (lim.rlim_cur >= 8192)
  150. if (lim.rlim_cur >= PTHREAD_STACK_MIN)
  151. return lim.rlim_cur;
  152. }
  153. #endif
  154. #if !defined(__linux__)
  155. return 0;
  156. #elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
  157. return 4 << 20; /* glibc default. */
  158. #else
  159. return 2 << 20; /* glibc default. */
  160. #endif
  161. }
  162. int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
  163. uv_thread_options_t params;
  164. params.flags = UV_THREAD_NO_FLAGS;
  165. return uv_thread_create_ex(tid, &params, entry, arg);
  166. }
  167. int uv_thread_create_ex(uv_thread_t* tid,
  168. const uv_thread_options_t* params,
  169. void (*entry)(void *arg),
  170. void *arg) {
  171. int err;
  172. pthread_attr_t* attr;
  173. pthread_attr_t attr_storage;
  174. size_t pagesize;
  175. size_t stack_size;
  176. /* Used to squelch a -Wcast-function-type warning. */
  177. union {
  178. void (*in)(void*);
  179. void* (*out)(void*);
  180. } f;
  181. stack_size =
  182. params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
  183. attr = NULL;
  184. if (stack_size == 0) {
  185. stack_size = thread_stack_size();
  186. } else {
  187. pagesize = (size_t)getpagesize();
  188. /* Round up to the nearest page boundary. */
  189. stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
  190. #ifdef PTHREAD_STACK_MIN
  191. if (stack_size < PTHREAD_STACK_MIN)
  192. stack_size = PTHREAD_STACK_MIN;
  193. #endif
  194. }
  195. if (stack_size > 0) {
  196. attr = &attr_storage;
  197. if (pthread_attr_init(attr))
  198. abort();
  199. if (pthread_attr_setstacksize(attr, stack_size))
  200. abort();
  201. }
  202. f.in = entry;
  203. err = pthread_create(tid, attr, f.out, arg);
  204. if (attr != NULL)
  205. pthread_attr_destroy(attr);
  206. return UV__ERR(err);
  207. }
  208. uv_thread_t uv_thread_self(void) {
  209. return pthread_self();
  210. }
  211. int uv_thread_join(uv_thread_t *tid) {
  212. return UV__ERR(pthread_join(*tid, NULL));
  213. }
  214. int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
  215. return pthread_equal(*t1, *t2);
  216. }
  217. int uv_mutex_init(uv_mutex_t* mutex) {
  218. #if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
  219. return UV__ERR(pthread_mutex_init(mutex, NULL));
  220. #else
  221. pthread_mutexattr_t attr;
  222. int err;
  223. if (pthread_mutexattr_init(&attr))
  224. abort();
  225. if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
  226. abort();
  227. err = pthread_mutex_init(mutex, &attr);
  228. if (pthread_mutexattr_destroy(&attr))
  229. abort();
  230. return UV__ERR(err);
  231. #endif
  232. }
  233. int uv_mutex_init_recursive(uv_mutex_t* mutex) {
  234. pthread_mutexattr_t attr;
  235. int err;
  236. if (pthread_mutexattr_init(&attr))
  237. abort();
  238. if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
  239. abort();
  240. err = pthread_mutex_init(mutex, &attr);
  241. if (pthread_mutexattr_destroy(&attr))
  242. abort();
  243. return UV__ERR(err);
  244. }
  245. void uv_mutex_destroy(uv_mutex_t* mutex) {
  246. if (pthread_mutex_destroy(mutex))
  247. abort();
  248. }
  249. void uv_mutex_lock(uv_mutex_t* mutex) {
  250. if (pthread_mutex_lock(mutex))
  251. abort();
  252. }
  253. int uv_mutex_trylock(uv_mutex_t* mutex) {
  254. int err;
  255. err = pthread_mutex_trylock(mutex);
  256. if (err) {
  257. if (err != EBUSY && err != EAGAIN)
  258. abort();
  259. return UV_EBUSY;
  260. }
  261. return 0;
  262. }
  263. void uv_mutex_unlock(uv_mutex_t* mutex) {
  264. if (pthread_mutex_unlock(mutex))
  265. abort();
  266. }
  267. int uv_rwlock_init(uv_rwlock_t* rwlock) {
  268. return UV__ERR(pthread_rwlock_init(rwlock, NULL));
  269. }
  270. void uv_rwlock_destroy(uv_rwlock_t* rwlock) {
  271. if (pthread_rwlock_destroy(rwlock))
  272. abort();
  273. }
  274. void uv_rwlock_rdlock(uv_rwlock_t* rwlock) {
  275. if (pthread_rwlock_rdlock(rwlock))
  276. abort();
  277. }
  278. int uv_rwlock_tryrdlock(uv_rwlock_t* rwlock) {
  279. int err;
  280. err = pthread_rwlock_tryrdlock(rwlock);
  281. if (err) {
  282. if (err != EBUSY && err != EAGAIN)
  283. abort();
  284. return UV_EBUSY;
  285. }
  286. return 0;
  287. }
  288. void uv_rwlock_rdunlock(uv_rwlock_t* rwlock) {
  289. if (pthread_rwlock_unlock(rwlock))
  290. abort();
  291. }
  292. void uv_rwlock_wrlock(uv_rwlock_t* rwlock) {
  293. if (pthread_rwlock_wrlock(rwlock))
  294. abort();
  295. }
  296. int uv_rwlock_trywrlock(uv_rwlock_t* rwlock) {
  297. int err;
  298. err = pthread_rwlock_trywrlock(rwlock);
  299. if (err) {
  300. if (err != EBUSY && err != EAGAIN)
  301. abort();
  302. return UV_EBUSY;
  303. }
  304. return 0;
  305. }
  306. void uv_rwlock_wrunlock(uv_rwlock_t* rwlock) {
  307. if (pthread_rwlock_unlock(rwlock))
  308. abort();
  309. }
  310. void uv_once(uv_once_t* guard, void (*callback)(void)) {
  311. if (pthread_once(guard, callback))
  312. abort();
  313. }
  314. #if defined(__APPLE__) && defined(__MACH__)
  315. int uv_sem_init(uv_sem_t* sem, unsigned int value) {
  316. kern_return_t err;
  317. err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
  318. if (err == KERN_SUCCESS)
  319. return 0;
  320. if (err == KERN_INVALID_ARGUMENT)
  321. return UV_EINVAL;
  322. if (err == KERN_RESOURCE_SHORTAGE)
  323. return UV_ENOMEM;
  324. abort();
  325. return UV_EINVAL; /* Satisfy the compiler. */
  326. }
  327. void uv_sem_destroy(uv_sem_t* sem) {
  328. if (semaphore_destroy(mach_task_self(), *sem))
  329. abort();
  330. }
  331. void uv_sem_post(uv_sem_t* sem) {
  332. if (semaphore_signal(*sem))
  333. abort();
  334. }
  335. void uv_sem_wait(uv_sem_t* sem) {
  336. int r;
  337. do
  338. r = semaphore_wait(*sem);
  339. while (r == KERN_ABORTED);
  340. if (r != KERN_SUCCESS)
  341. abort();
  342. }
  343. int uv_sem_trywait(uv_sem_t* sem) {
  344. mach_timespec_t interval;
  345. kern_return_t err;
  346. interval.tv_sec = 0;
  347. interval.tv_nsec = 0;
  348. err = semaphore_timedwait(*sem, interval);
  349. if (err == KERN_SUCCESS)
  350. return 0;
  351. if (err == KERN_OPERATION_TIMED_OUT)
  352. return UV_EAGAIN;
  353. abort();
  354. return UV_EINVAL; /* Satisfy the compiler. */
  355. }
  356. #else /* !(defined(__APPLE__) && defined(__MACH__)) */
  357. #if defined(__GLIBC__) && !defined(__UCLIBC__)
  358. /* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
  359. * by providing a custom implementation for glibc < 2.21 in terms of other
  360. * concurrency primitives.
  361. * Refs: https://github.com/nodejs/node/issues/19903 */
  362. /* To preserve ABI compatibility, we treat the uv_sem_t as storage for
  363. * a pointer to the actual struct we're using underneath. */
  364. static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
  365. static int platform_needs_custom_semaphore = 0;
  366. static void glibc_version_check(void) {
  367. const char* version = gnu_get_libc_version();
  368. platform_needs_custom_semaphore =
  369. version[0] == '2' && version[1] == '.' &&
  370. atoi(version + 2) < 21;
  371. }
  372. #elif defined(__MVS__)
  373. #define platform_needs_custom_semaphore 1
  374. #else /* !defined(__GLIBC__) && !defined(__MVS__) */
  375. #define platform_needs_custom_semaphore 0
  376. #endif
  377. typedef struct uv_semaphore_s {
  378. uv_mutex_t mutex;
  379. uv_cond_t cond;
  380. unsigned int value;
  381. } uv_semaphore_t;
  382. #if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
  383. platform_needs_custom_semaphore
  384. STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
  385. #endif
  386. static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
  387. int err;
  388. uv_semaphore_t* sem;
  389. sem = uv__malloc(sizeof(*sem));
  390. if (sem == NULL)
  391. return UV_ENOMEM;
  392. if ((err = uv_mutex_init(&sem->mutex)) != 0) {
  393. uv__free(sem);
  394. return err;
  395. }
  396. if ((err = uv_cond_init(&sem->cond)) != 0) {
  397. uv_mutex_destroy(&sem->mutex);
  398. uv__free(sem);
  399. return err;
  400. }
  401. sem->value = value;
  402. *(uv_semaphore_t**)sem_ = sem;
  403. return 0;
  404. }
  405. static void uv__custom_sem_destroy(uv_sem_t* sem_) {
  406. uv_semaphore_t* sem;
  407. sem = *(uv_semaphore_t**)sem_;
  408. uv_cond_destroy(&sem->cond);
  409. uv_mutex_destroy(&sem->mutex);
  410. uv__free(sem);
  411. }
  412. static void uv__custom_sem_post(uv_sem_t* sem_) {
  413. uv_semaphore_t* sem;
  414. sem = *(uv_semaphore_t**)sem_;
  415. uv_mutex_lock(&sem->mutex);
  416. sem->value++;
  417. if (sem->value == 1)
  418. uv_cond_signal(&sem->cond);
  419. uv_mutex_unlock(&sem->mutex);
  420. }
  421. static void uv__custom_sem_wait(uv_sem_t* sem_) {
  422. uv_semaphore_t* sem;
  423. sem = *(uv_semaphore_t**)sem_;
  424. uv_mutex_lock(&sem->mutex);
  425. while (sem->value == 0)
  426. uv_cond_wait(&sem->cond, &sem->mutex);
  427. sem->value--;
  428. uv_mutex_unlock(&sem->mutex);
  429. }
  430. static int uv__custom_sem_trywait(uv_sem_t* sem_) {
  431. uv_semaphore_t* sem;
  432. sem = *(uv_semaphore_t**)sem_;
  433. if (uv_mutex_trylock(&sem->mutex) != 0)
  434. return UV_EAGAIN;
  435. if (sem->value == 0) {
  436. uv_mutex_unlock(&sem->mutex);
  437. return UV_EAGAIN;
  438. }
  439. sem->value--;
  440. uv_mutex_unlock(&sem->mutex);
  441. return 0;
  442. }
  443. static int uv__sem_init(uv_sem_t* sem, unsigned int value) {
  444. if (sem_init(sem, 0, value))
  445. return UV__ERR(errno);
  446. return 0;
  447. }
  448. static void uv__sem_destroy(uv_sem_t* sem) {
  449. if (sem_destroy(sem))
  450. abort();
  451. }
  452. static void uv__sem_post(uv_sem_t* sem) {
  453. if (sem_post(sem))
  454. abort();
  455. }
  456. static void uv__sem_wait(uv_sem_t* sem) {
  457. int r;
  458. do
  459. r = sem_wait(sem);
  460. while (r == -1 && errno == EINTR);
  461. if (r)
  462. abort();
  463. }
  464. static int uv__sem_trywait(uv_sem_t* sem) {
  465. int r;
  466. do
  467. r = sem_trywait(sem);
  468. while (r == -1 && errno == EINTR);
  469. if (r) {
  470. if (errno == EAGAIN)
  471. return UV_EAGAIN;
  472. abort();
  473. }
  474. return 0;
  475. }
  476. int uv_sem_init(uv_sem_t* sem, unsigned int value) {
  477. #if defined(__GLIBC__) && !defined(__UCLIBC__)
  478. uv_once(&glibc_version_check_once, glibc_version_check);
  479. #endif
  480. if (platform_needs_custom_semaphore)
  481. return uv__custom_sem_init(sem, value);
  482. else
  483. return uv__sem_init(sem, value);
  484. }
  485. void uv_sem_destroy(uv_sem_t* sem) {
  486. if (platform_needs_custom_semaphore)
  487. uv__custom_sem_destroy(sem);
  488. else
  489. uv__sem_destroy(sem);
  490. }
  491. void uv_sem_post(uv_sem_t* sem) {
  492. if (platform_needs_custom_semaphore)
  493. uv__custom_sem_post(sem);
  494. else
  495. uv__sem_post(sem);
  496. }
  497. void uv_sem_wait(uv_sem_t* sem) {
  498. if (platform_needs_custom_semaphore)
  499. uv__custom_sem_wait(sem);
  500. else
  501. uv__sem_wait(sem);
  502. }
  503. int uv_sem_trywait(uv_sem_t* sem) {
  504. if (platform_needs_custom_semaphore)
  505. return uv__custom_sem_trywait(sem);
  506. else
  507. return uv__sem_trywait(sem);
  508. }
  509. #endif /* defined(__APPLE__) && defined(__MACH__) */
  510. #if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
  511. int uv_cond_init(uv_cond_t* cond) {
  512. return UV__ERR(pthread_cond_init(cond, NULL));
  513. }
  514. #else /* !(defined(__APPLE__) && defined(__MACH__)) */
  515. int uv_cond_init(uv_cond_t* cond) {
  516. pthread_condattr_t attr;
  517. int err;
  518. err = pthread_condattr_init(&attr);
  519. if (err)
  520. return UV__ERR(err);
  521. #if !(defined(__ANDROID_API__) && __ANDROID_API__ < 21)
  522. err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
  523. if (err)
  524. goto error2;
  525. #endif
  526. err = pthread_cond_init(cond, &attr);
  527. if (err)
  528. goto error2;
  529. err = pthread_condattr_destroy(&attr);
  530. if (err)
  531. goto error;
  532. return 0;
  533. error:
  534. pthread_cond_destroy(cond);
  535. error2:
  536. pthread_condattr_destroy(&attr);
  537. return UV__ERR(err);
  538. }
  539. #endif /* defined(__APPLE__) && defined(__MACH__) */
  540. void uv_cond_destroy(uv_cond_t* cond) {
  541. #if defined(__APPLE__) && defined(__MACH__)
  542. /* It has been reported that destroying condition variables that have been
  543. * signalled but not waited on can sometimes result in application crashes.
  544. * See https://codereview.chromium.org/1323293005.
  545. */
  546. pthread_mutex_t mutex;
  547. struct timespec ts;
  548. int err;
  549. if (pthread_mutex_init(&mutex, NULL))
  550. abort();
  551. if (pthread_mutex_lock(&mutex))
  552. abort();
  553. ts.tv_sec = 0;
  554. ts.tv_nsec = 1;
  555. err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
  556. if (err != 0 && err != ETIMEDOUT)
  557. abort();
  558. if (pthread_mutex_unlock(&mutex))
  559. abort();
  560. if (pthread_mutex_destroy(&mutex))
  561. abort();
  562. #endif /* defined(__APPLE__) && defined(__MACH__) */
  563. if (pthread_cond_destroy(cond))
  564. abort();
  565. }
  566. void uv_cond_signal(uv_cond_t* cond) {
  567. if (pthread_cond_signal(cond))
  568. abort();
  569. }
  570. void uv_cond_broadcast(uv_cond_t* cond) {
  571. if (pthread_cond_broadcast(cond))
  572. abort();
  573. }
  574. void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) {
  575. if (pthread_cond_wait(cond, mutex))
  576. abort();
  577. }
  578. int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) {
  579. int r;
  580. struct timespec ts;
  581. #if defined(__MVS__)
  582. struct timeval tv;
  583. #endif
  584. #if defined(__APPLE__) && defined(__MACH__)
  585. ts.tv_sec = timeout / NANOSEC;
  586. ts.tv_nsec = timeout % NANOSEC;
  587. r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
  588. #else
  589. #if defined(__MVS__)
  590. if (gettimeofday(&tv, NULL))
  591. abort();
  592. timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
  593. #else
  594. timeout += uv__hrtime(UV_CLOCK_PRECISE);
  595. #endif
  596. ts.tv_sec = timeout / NANOSEC;
  597. ts.tv_nsec = timeout % NANOSEC;
  598. #if defined(__ANDROID_API__) && __ANDROID_API__ < 21
  599. /*
  600. * The bionic pthread implementation doesn't support CLOCK_MONOTONIC,
  601. * but has this alternative function instead.
  602. */
  603. r = pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
  604. #else
  605. r = pthread_cond_timedwait(cond, mutex, &ts);
  606. #endif /* __ANDROID_API__ */
  607. #endif
  608. if (r == 0)
  609. return 0;
  610. if (r == ETIMEDOUT)
  611. return UV_ETIMEDOUT;
  612. abort();
  613. #ifndef __SUNPRO_C
  614. return UV_EINVAL; /* Satisfy the compiler. */
  615. #endif
  616. }
  617. int uv_key_create(uv_key_t* key) {
  618. return UV__ERR(pthread_key_create(key, NULL));
  619. }
  620. void uv_key_delete(uv_key_t* key) {
  621. if (pthread_key_delete(*key))
  622. abort();
  623. }
  624. void* uv_key_get(uv_key_t* key) {
  625. return pthread_getspecific(*key);
  626. }
  627. void uv_key_set(uv_key_t* key, void* value) {
  628. if (pthread_setspecific(*key, value))
  629. abort();
  630. }