Rizin
unix-like reverse engineering framework and cli tools
thread.c
Go to the documentation of this file.
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 #include <assert.h>
27 #include <errno.h>
28 
29 #include <sys/time.h>
30 #include <sys/resource.h> /* getrlimit() */
31 #include <unistd.h> /* getpagesize() */
32 
33 #include <limits.h>
34 
35 #ifdef __MVS__
36 #include <sys/ipc.h>
37 #include <sys/sem.h>
38 #endif
39 
40 #if defined(__GLIBC__) && !defined(__UCLIBC__)
41 #include <gnu/libc-version.h> /* gnu_get_libc_version() */
42 #endif
43 
44 #undef NANOSEC
45 #define NANOSEC ((uint64_t) 1e9)
46 
47 #if defined(PTHREAD_BARRIER_SERIAL_THREAD)
48 STATIC_ASSERT(sizeof(uv_barrier_t) == sizeof(pthread_barrier_t));
49 #endif
50 
51 /* Note: guard clauses should match uv_barrier_t's in include/uv/unix.h. */
52 #if defined(_AIX) || \
53  defined(__OpenBSD__) || \
54  !defined(PTHREAD_BARRIER_SERIAL_THREAD)
55 int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
56  struct _uv_barrier* b;
57  int rc;
58 
59  if (barrier == NULL || count == 0)
60  return UV_EINVAL;
61 
62  b = uv__malloc(sizeof(*b));
63  if (b == NULL)
64  return UV_ENOMEM;
65 
66  b->in = 0;
67  b->out = 0;
68  b->threshold = count;
69 
70  rc = uv_mutex_init(&b->mutex);
71  if (rc != 0)
72  goto error2;
73 
74  rc = uv_cond_init(&b->cond);
75  if (rc != 0)
76  goto error;
77 
78  barrier->b = b;
79  return 0;
80 
81 error:
82  uv_mutex_destroy(&b->mutex);
83 error2:
84  uv__free(b);
85  return rc;
86 }
87 
88 
90  struct _uv_barrier* b;
91  int last;
92 
93  if (barrier == NULL || barrier->b == NULL)
94  return UV_EINVAL;
95 
96  b = barrier->b;
97  uv_mutex_lock(&b->mutex);
98 
99  if (++b->in == b->threshold) {
100  b->in = 0;
101  b->out = b->threshold;
102  uv_cond_signal(&b->cond);
103  } else {
104  do
105  uv_cond_wait(&b->cond, &b->mutex);
106  while (b->in != 0);
107  }
108 
109  last = (--b->out == 0);
110  if (!last)
111  uv_cond_signal(&b->cond); /* Not needed for last thread. */
112 
113  uv_mutex_unlock(&b->mutex);
114  return last;
115 }
116 
117 
119  struct _uv_barrier* b;
120 
121  b = barrier->b;
122  uv_mutex_lock(&b->mutex);
123 
124  assert(b->in == 0);
125  assert(b->out == 0);
126 
127  if (b->in != 0 || b->out != 0)
128  abort();
129 
130  uv_mutex_unlock(&b->mutex);
131  uv_mutex_destroy(&b->mutex);
132  uv_cond_destroy(&b->cond);
133 
134  uv__free(barrier->b);
135  barrier->b = NULL;
136 }
137 
138 #else
139 
140 int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) {
141  return UV__ERR(pthread_barrier_init(barrier, NULL, count));
142 }
143 
144 
145 int uv_barrier_wait(uv_barrier_t* barrier) {
146  int rc;
147 
148  rc = pthread_barrier_wait(barrier);
149  if (rc != 0)
150  if (rc != PTHREAD_BARRIER_SERIAL_THREAD)
151  abort();
152 
153  return rc == PTHREAD_BARRIER_SERIAL_THREAD;
154 }
155 
156 
157 void uv_barrier_destroy(uv_barrier_t* barrier) {
158  if (pthread_barrier_destroy(barrier))
159  abort();
160 }
161 
162 #endif
163 
164 
165 /* On MacOS, threads other than the main thread are created with a reduced
166  * stack size by default. Adjust to RLIMIT_STACK aligned to the page size.
167  *
168  * On Linux, threads created by musl have a much smaller stack than threads
169  * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency.
170  */
171 static size_t thread_stack_size(void) {
172 #if defined(__APPLE__) || defined(__linux__)
173  struct rlimit lim;
174 
175  /* getrlimit() can fail on some aarch64 systems due to a glibc bug where
176  * the system call wrapper invokes the wrong system call. Don't treat
177  * that as fatal, just use the default stack size instead.
178  */
179  if (0 == getrlimit(RLIMIT_STACK, &lim) && lim.rlim_cur != RLIM_INFINITY) {
180  /* pthread_attr_setstacksize() expects page-aligned values. */
181  lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize();
182 
183  /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is
184  * too small to safely receive signals on.
185  *
186  * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has
187  * the largest MINSIGSTKSZ of the architectures that musl supports) so
188  * let's use that as a lower bound.
189  *
190  * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ
191  * is between 28 and 133 KB when compiling against glibc, depending
192  * on the architecture.
193  */
194  if (lim.rlim_cur >= 8192)
195  if (lim.rlim_cur >= PTHREAD_STACK_MIN)
196  return lim.rlim_cur;
197  }
198 #endif
199 
200 #if !defined(__linux__)
201  return 0;
202 #elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__)
203  return 4 << 20; /* glibc default. */
204 #else
205  return 2 << 20; /* glibc default. */
206 #endif
207 }
208 
209 
210 int uv_thread_create(uv_thread_t *tid, void (*entry)(void *arg), void *arg) {
211  uv_thread_options_t params;
212  params.flags = UV_THREAD_NO_FLAGS;
213  return uv_thread_create_ex(tid, &params, entry, arg);
214 }
215 
217  const uv_thread_options_t* params,
218  void (*entry)(void *arg),
219  void *arg) {
220  int err;
221  pthread_attr_t* attr;
222  pthread_attr_t attr_storage;
223  size_t pagesize;
224  size_t stack_size;
225 
226  /* Used to squelch a -Wcast-function-type warning. */
227  union {
228  void (*in)(void*);
229  void* (*out)(void*);
230  } f;
231 
232  stack_size =
233  params->flags & UV_THREAD_HAS_STACK_SIZE ? params->stack_size : 0;
234 
235  attr = NULL;
236  if (stack_size == 0) {
237  stack_size = thread_stack_size();
238  } else {
239  pagesize = (size_t)getpagesize();
240  /* Round up to the nearest page boundary. */
241  stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1);
242 #ifdef PTHREAD_STACK_MIN
243  if (stack_size < PTHREAD_STACK_MIN)
244  stack_size = PTHREAD_STACK_MIN;
245 #endif
246  }
247 
248  if (stack_size > 0) {
249  attr = &attr_storage;
250 
251  if (pthread_attr_init(attr))
252  abort();
253 
254  if (pthread_attr_setstacksize(attr, stack_size))
255  abort();
256  }
257 
258  f.in = entry;
259  err = pthread_create(tid, attr, f.out, arg);
260 
261  if (attr != NULL)
262  pthread_attr_destroy(attr);
263 
264  return UV__ERR(err);
265 }
266 
267 
269  return pthread_self();
270 }
271 
273  return UV__ERR(pthread_join(*tid, NULL));
274 }
275 
276 
277 int uv_thread_equal(const uv_thread_t* t1, const uv_thread_t* t2) {
278  return pthread_equal(*t1, *t2);
279 }
280 
281 
283 #if defined(NDEBUG) || !defined(PTHREAD_MUTEX_ERRORCHECK)
284  return UV__ERR(pthread_mutex_init(mutex, NULL));
285 #else
286  pthread_mutexattr_t attr;
287  int err;
288 
289  if (pthread_mutexattr_init(&attr))
290  abort();
291 
292  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK))
293  abort();
294 
295  err = pthread_mutex_init(mutex, &attr);
296 
297  if (pthread_mutexattr_destroy(&attr))
298  abort();
299 
300  return UV__ERR(err);
301 #endif
302 }
303 
304 
306  pthread_mutexattr_t attr;
307  int err;
308 
309  if (pthread_mutexattr_init(&attr))
310  abort();
311 
312  if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE))
313  abort();
314 
315  err = pthread_mutex_init(mutex, &attr);
316 
317  if (pthread_mutexattr_destroy(&attr))
318  abort();
319 
320  return UV__ERR(err);
321 }
322 
323 
325  if (pthread_mutex_destroy(mutex))
326  abort();
327 }
328 
329 
331  if (pthread_mutex_lock(mutex))
332  abort();
333 }
334 
335 
337  int err;
338 
339  err = pthread_mutex_trylock(mutex);
340  if (err) {
341  if (err != EBUSY && err != EAGAIN)
342  abort();
343  return UV_EBUSY;
344  }
345 
346  return 0;
347 }
348 
349 
351  if (pthread_mutex_unlock(mutex))
352  abort();
353 }
354 
355 
357  return UV__ERR(pthread_rwlock_init(rwlock, NULL));
358 }
359 
360 
362  if (pthread_rwlock_destroy(rwlock))
363  abort();
364 }
365 
366 
368  if (pthread_rwlock_rdlock(rwlock))
369  abort();
370 }
371 
372 
374  int err;
375 
376  err = pthread_rwlock_tryrdlock(rwlock);
377  if (err) {
378  if (err != EBUSY && err != EAGAIN)
379  abort();
380  return UV_EBUSY;
381  }
382 
383  return 0;
384 }
385 
386 
388  if (pthread_rwlock_unlock(rwlock))
389  abort();
390 }
391 
392 
394  if (pthread_rwlock_wrlock(rwlock))
395  abort();
396 }
397 
398 
400  int err;
401 
402  err = pthread_rwlock_trywrlock(rwlock);
403  if (err) {
404  if (err != EBUSY && err != EAGAIN)
405  abort();
406  return UV_EBUSY;
407  }
408 
409  return 0;
410 }
411 
412 
414  if (pthread_rwlock_unlock(rwlock))
415  abort();
416 }
417 
418 
419 void uv_once(uv_once_t* guard, void (*callback)(void)) {
420  if (pthread_once(guard, callback))
421  abort();
422 }
423 
424 #if defined(__APPLE__) && defined(__MACH__)
425 
426 int uv_sem_init(uv_sem_t* sem, unsigned int value) {
427  kern_return_t err;
428 
429  err = semaphore_create(mach_task_self(), sem, SYNC_POLICY_FIFO, value);
430  if (err == KERN_SUCCESS)
431  return 0;
432  if (err == KERN_INVALID_ARGUMENT)
433  return UV_EINVAL;
434  if (err == KERN_RESOURCE_SHORTAGE)
435  return UV_ENOMEM;
436 
437  abort();
438  return UV_EINVAL; /* Satisfy the compiler. */
439 }
440 
441 
442 void uv_sem_destroy(uv_sem_t* sem) {
443  if (semaphore_destroy(mach_task_self(), *sem))
444  abort();
445 }
446 
447 
448 void uv_sem_post(uv_sem_t* sem) {
449  if (semaphore_signal(*sem))
450  abort();
451 }
452 
453 
454 void uv_sem_wait(uv_sem_t* sem) {
455  int r;
456 
457  do
458  r = semaphore_wait(*sem);
459  while (r == KERN_ABORTED);
460 
461  if (r != KERN_SUCCESS)
462  abort();
463 }
464 
465 
466 int uv_sem_trywait(uv_sem_t* sem) {
467  mach_timespec_t interval;
468  kern_return_t err;
469 
470  interval.tv_sec = 0;
471  interval.tv_nsec = 0;
472 
473  err = semaphore_timedwait(*sem, interval);
474  if (err == KERN_SUCCESS)
475  return 0;
476  if (err == KERN_OPERATION_TIMED_OUT)
477  return UV_EAGAIN;
478 
479  abort();
480  return UV_EINVAL; /* Satisfy the compiler. */
481 }
482 
483 #else /* !(defined(__APPLE__) && defined(__MACH__)) */
484 
485 #if defined(__GLIBC__) && !defined(__UCLIBC__)
486 
487 /* Hack around https://sourceware.org/bugzilla/show_bug.cgi?id=12674
488  * by providing a custom implementation for glibc < 2.21 in terms of other
489  * concurrency primitives.
490  * Refs: https://github.com/nodejs/node/issues/19903 */
491 
492 /* To preserve ABI compatibility, we treat the uv_sem_t as storage for
493  * a pointer to the actual struct we're using underneath. */
494 
495 static uv_once_t glibc_version_check_once = UV_ONCE_INIT;
496 static int platform_needs_custom_semaphore = 0;
497 
498 static void glibc_version_check(void) {
499  const char* version = gnu_get_libc_version();
501  version[0] == '2' && version[1] == '.' &&
502  atoi(version + 2) < 21;
503 }
504 
505 #elif defined(__MVS__)
506 
507 #define platform_needs_custom_semaphore 1
508 
509 #else /* !defined(__GLIBC__) && !defined(__MVS__) */
510 
511 #define platform_needs_custom_semaphore 0
512 
513 #endif
514 
515 typedef struct uv_semaphore_s {
518  unsigned int value;
520 
521 #if (defined(__GLIBC__) && !defined(__UCLIBC__)) || \
522  platform_needs_custom_semaphore
523 STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*));
524 #endif
525 
526 static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) {
527  int err;
528  uv_semaphore_t* sem;
529 
530  sem = uv__malloc(sizeof(*sem));
531  if (sem == NULL)
532  return UV_ENOMEM;
533 
534  if ((err = uv_mutex_init(&sem->mutex)) != 0) {
535  uv__free(sem);
536  return err;
537  }
538 
539  if ((err = uv_cond_init(&sem->cond)) != 0) {
540  uv_mutex_destroy(&sem->mutex);
541  uv__free(sem);
542  return err;
543  }
544 
545  sem->value = value;
546  *(uv_semaphore_t**)sem_ = sem;
547  return 0;
548 }
549 
550 
551 static void uv__custom_sem_destroy(uv_sem_t* sem_) {
552  uv_semaphore_t* sem;
553 
554  sem = *(uv_semaphore_t**)sem_;
555  uv_cond_destroy(&sem->cond);
556  uv_mutex_destroy(&sem->mutex);
557  uv__free(sem);
558 }
559 
560 
561 static void uv__custom_sem_post(uv_sem_t* sem_) {
562  uv_semaphore_t* sem;
563 
564  sem = *(uv_semaphore_t**)sem_;
565  uv_mutex_lock(&sem->mutex);
566  sem->value++;
567  if (sem->value == 1)
568  uv_cond_signal(&sem->cond);
569  uv_mutex_unlock(&sem->mutex);
570 }
571 
572 
573 static void uv__custom_sem_wait(uv_sem_t* sem_) {
574  uv_semaphore_t* sem;
575 
576  sem = *(uv_semaphore_t**)sem_;
577  uv_mutex_lock(&sem->mutex);
578  while (sem->value == 0)
579  uv_cond_wait(&sem->cond, &sem->mutex);
580  sem->value--;
581  uv_mutex_unlock(&sem->mutex);
582 }
583 
584 
585 static int uv__custom_sem_trywait(uv_sem_t* sem_) {
586  uv_semaphore_t* sem;
587 
588  sem = *(uv_semaphore_t**)sem_;
589  if (uv_mutex_trylock(&sem->mutex) != 0)
590  return UV_EAGAIN;
591 
592  if (sem->value == 0) {
593  uv_mutex_unlock(&sem->mutex);
594  return UV_EAGAIN;
595  }
596 
597  sem->value--;
598  uv_mutex_unlock(&sem->mutex);
599 
600  return 0;
601 }
602 
603 static int uv__sem_init(uv_sem_t* sem, unsigned int value) {
604  if (sem_init(sem, 0, value))
605  return UV__ERR(errno);
606  return 0;
607 }
608 
609 
610 static void uv__sem_destroy(uv_sem_t* sem) {
611  if (sem_destroy(sem))
612  abort();
613 }
614 
615 
616 static void uv__sem_post(uv_sem_t* sem) {
617  if (sem_post(sem))
618  abort();
619 }
620 
621 
622 static void uv__sem_wait(uv_sem_t* sem) {
623  int r;
624 
625  do
626  r = sem_wait(sem);
627  while (r == -1 && errno == EINTR);
628 
629  if (r)
630  abort();
631 }
632 
633 
634 static int uv__sem_trywait(uv_sem_t* sem) {
635  int r;
636 
637  do
638  r = sem_trywait(sem);
639  while (r == -1 && errno == EINTR);
640 
641  if (r) {
642  if (errno == EAGAIN)
643  return UV_EAGAIN;
644  abort();
645  }
646 
647  return 0;
648 }
649 
650 int uv_sem_init(uv_sem_t* sem, unsigned int value) {
651 #if defined(__GLIBC__) && !defined(__UCLIBC__)
652  uv_once(&glibc_version_check_once, glibc_version_check);
653 #endif
654 
656  return uv__custom_sem_init(sem, value);
657  else
658  return uv__sem_init(sem, value);
659 }
660 
661 
665  else
666  uv__sem_destroy(sem);
667 }
668 
669 
670 void uv_sem_post(uv_sem_t* sem) {
672  uv__custom_sem_post(sem);
673  else
674  uv__sem_post(sem);
675 }
676 
677 
678 void uv_sem_wait(uv_sem_t* sem) {
680  uv__custom_sem_wait(sem);
681  else
682  uv__sem_wait(sem);
683 }
684 
685 
688  return uv__custom_sem_trywait(sem);
689  else
690  return uv__sem_trywait(sem);
691 }
692 
693 #endif /* defined(__APPLE__) && defined(__MACH__) */
694 
695 
696 #if defined(__APPLE__) && defined(__MACH__) || defined(__MVS__)
697 
699  return UV__ERR(pthread_cond_init(cond, NULL));
700 }
701 
702 #else /* !(defined(__APPLE__) && defined(__MACH__)) */
703 
705  pthread_condattr_t attr;
706  int err;
707 
708  err = pthread_condattr_init(&attr);
709  if (err)
710  return UV__ERR(err);
711 
712  err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
713  if (err)
714  goto error2;
715 
716  err = pthread_cond_init(cond, &attr);
717  if (err)
718  goto error2;
719 
720  err = pthread_condattr_destroy(&attr);
721  if (err)
722  goto error;
723 
724  return 0;
725 
726 error:
727  pthread_cond_destroy(cond);
728 error2:
729  pthread_condattr_destroy(&attr);
730  return UV__ERR(err);
731 }
732 
733 #endif /* defined(__APPLE__) && defined(__MACH__) */
734 
736 #if defined(__APPLE__) && defined(__MACH__)
737  /* It has been reported that destroying condition variables that have been
738  * signalled but not waited on can sometimes result in application crashes.
739  * See https://codereview.chromium.org/1323293005.
740  */
741  pthread_mutex_t mutex;
742  struct timespec ts;
743  int err;
744 
745  if (pthread_mutex_init(&mutex, NULL))
746  abort();
747 
748  if (pthread_mutex_lock(&mutex))
749  abort();
750 
751  ts.tv_sec = 0;
752  ts.tv_nsec = 1;
753 
754  err = pthread_cond_timedwait_relative_np(cond, &mutex, &ts);
755  if (err != 0 && err != ETIMEDOUT)
756  abort();
757 
758  if (pthread_mutex_unlock(&mutex))
759  abort();
760 
761  if (pthread_mutex_destroy(&mutex))
762  abort();
763 #endif /* defined(__APPLE__) && defined(__MACH__) */
764 
765  if (pthread_cond_destroy(cond))
766  abort();
767 }
768 
770  if (pthread_cond_signal(cond))
771  abort();
772 }
773 
775  if (pthread_cond_broadcast(cond))
776  abort();
777 }
778 
780  if (pthread_cond_wait(cond, mutex))
781  abort();
782 }
783 
784 
786  int r;
787  struct timespec ts;
788 #if defined(__MVS__)
789  struct timeval tv;
790 #endif
791 
792 #if defined(__APPLE__) && defined(__MACH__)
793  ts.tv_sec = timeout / NANOSEC;
794  ts.tv_nsec = timeout % NANOSEC;
795  r = pthread_cond_timedwait_relative_np(cond, mutex, &ts);
796 #else
797 #if defined(__MVS__)
798  if (gettimeofday(&tv, NULL))
799  abort();
800  timeout += tv.tv_sec * NANOSEC + tv.tv_usec * 1e3;
801 #else
803 #endif
804  ts.tv_sec = timeout / NANOSEC;
805  ts.tv_nsec = timeout % NANOSEC;
806  r = pthread_cond_timedwait(cond, mutex, &ts);
807 #endif
808 
809 
810  if (r == 0)
811  return 0;
812 
813  if (r == ETIMEDOUT)
814  return UV_ETIMEDOUT;
815 
816  abort();
817 #ifndef __SUNPRO_C
818  return UV_EINVAL; /* Satisfy the compiler. */
819 #endif
820 }
821 
822 
824  return UV__ERR(pthread_key_create(key, NULL));
825 }
826 
827 
829  if (pthread_key_delete(*key))
830  abort();
831 }
832 
833 
835  return pthread_getspecific(*key);
836 }
837 
838 
839 void uv_key_set(uv_key_t* key, void* value) {
840  if (pthread_setspecific(*key, value))
841  abort();
842 }
uint64_t uv__hrtime(uv_clocktype_t type)
Definition: aix-common.c:43
static bool err
Definition: armass.c:435
const lzma_allocator const uint8_t * in
Definition: block.h:527
static int value
Definition: cmd_api.c:93
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval tv
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog gettimeofday
Definition: sflib.h:79
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
#define UV__ERR(x)
Definition: errno.h:29
assert(limit<=UINT32_MAX/2)
int sem_wait(UV_PLATFORM_SEM_T *semid)
int sem_destroy(UV_PLATFORM_SEM_T *semid)
int sem_trywait(UV_PLATFORM_SEM_T *semid)
int sem_post(UV_PLATFORM_SEM_T *semid)
int sem_init(UV_PLATFORM_SEM_T *semid, int pshared, unsigned int value)
int size_t
Definition: sftypes.h:40
#define EINTR
Definition: sftypes.h:114
#define ETIMEDOUT
Definition: sftypes.h:170
#define EBUSY
Definition: sftypes.h:126
unsigned long uint64_t
Definition: sftypes.h:28
#define EAGAIN
Definition: sftypes.h:121
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define cond(bop, top, mask, flags)
Definition: zipcmp.c:77
long tv_nsec
Definition: sftypes.h:90
time_t tv_sec
Definition: sftypes.h:89
struct _uv_barrier * b
Definition: unix.h:157
Definition: win.h:284
unsigned int value
Definition: thread.c:518
uv_cond_t cond
Definition: thread.c:517
uv_mutex_t mutex
Definition: thread.c:516
unsigned int flags
Definition: uv.h:1753
size_t stack_size
Definition: uv.h:1754
uv_timer_t timeout
Definition: main.c:9
@ UV_CLOCK_PRECISE
Definition: internal.h:147
static void uv__custom_sem_destroy(uv_sem_t *sem_)
Definition: thread.c:551
int uv_barrier_wait(uv_barrier_t *barrier)
Definition: thread.c:89
int uv_rwlock_trywrlock(uv_rwlock_t *rwlock)
Definition: thread.c:399
int uv_thread_create_ex(uv_thread_t *tid, const uv_thread_options_t *params, void(*entry)(void *arg), void *arg)
Definition: thread.c:216
int uv_cond_init(uv_cond_t *cond)
Definition: thread.c:704
void uv_key_set(uv_key_t *key, void *value)
Definition: thread.c:839
void uv_cond_signal(uv_cond_t *cond)
Definition: thread.c:769
int uv_rwlock_init(uv_rwlock_t *rwlock)
Definition: thread.c:356
void uv_sem_wait(uv_sem_t *sem)
Definition: thread.c:678
static int uv__custom_sem_trywait(uv_sem_t *sem_)
Definition: thread.c:585
void uv_rwlock_rdlock(uv_rwlock_t *rwlock)
Definition: thread.c:367
#define NANOSEC
Definition: thread.c:45
int uv_mutex_trylock(uv_mutex_t *mutex)
Definition: thread.c:336
static void uv__custom_sem_post(uv_sem_t *sem_)
Definition: thread.c:561
void uv_mutex_unlock(uv_mutex_t *mutex)
Definition: thread.c:350
void uv_rwlock_wrlock(uv_rwlock_t *rwlock)
Definition: thread.c:393
static void uv__sem_post(uv_sem_t *sem)
Definition: thread.c:616
void * uv_key_get(uv_key_t *key)
Definition: thread.c:834
int uv_sem_trywait(uv_sem_t *sem)
Definition: thread.c:686
int uv_mutex_init_recursive(uv_mutex_t *mutex)
Definition: thread.c:305
int uv_thread_join(uv_thread_t *tid)
Definition: thread.c:272
int uv_thread_create(uv_thread_t *tid, void(*entry)(void *arg), void *arg)
Definition: thread.c:210
void uv_sem_post(uv_sem_t *sem)
Definition: thread.c:670
void uv_mutex_destroy(uv_mutex_t *mutex)
Definition: thread.c:324
int uv_thread_equal(const uv_thread_t *t1, const uv_thread_t *t2)
Definition: thread.c:277
uv_thread_t uv_thread_self(void)
Definition: thread.c:268
void uv_once(uv_once_t *guard, void(*callback)(void))
Definition: thread.c:419
void uv_rwlock_rdunlock(uv_rwlock_t *rwlock)
Definition: thread.c:387
int uv_key_create(uv_key_t *key)
Definition: thread.c:823
void uv_cond_destroy(uv_cond_t *cond)
Definition: thread.c:735
int uv_rwlock_tryrdlock(uv_rwlock_t *rwlock)
Definition: thread.c:373
void uv_barrier_destroy(uv_barrier_t *barrier)
Definition: thread.c:118
static int uv__custom_sem_init(uv_sem_t *sem_, unsigned int value)
Definition: thread.c:526
int uv_cond_timedwait(uv_cond_t *cond, uv_mutex_t *mutex, uint64_t timeout)
Definition: thread.c:785
static int uv__sem_init(uv_sem_t *sem, unsigned int value)
Definition: thread.c:603
int uv_sem_init(uv_sem_t *sem, unsigned int value)
Definition: thread.c:650
void uv_cond_broadcast(uv_cond_t *cond)
Definition: thread.c:774
void uv_rwlock_destroy(uv_rwlock_t *rwlock)
Definition: thread.c:361
static void uv__sem_destroy(uv_sem_t *sem)
Definition: thread.c:610
int uv_mutex_init(uv_mutex_t *mutex)
Definition: thread.c:282
static size_t thread_stack_size(void)
Definition: thread.c:171
void uv_mutex_lock(uv_mutex_t *mutex)
Definition: thread.c:330
void uv_cond_wait(uv_cond_t *cond, uv_mutex_t *mutex)
Definition: thread.c:779
struct uv_semaphore_s uv_semaphore_t
int uv_barrier_init(uv_barrier_t *barrier, unsigned int count)
Definition: thread.c:55
void uv_sem_destroy(uv_sem_t *sem)
Definition: thread.c:662
#define platform_needs_custom_semaphore
Definition: thread.c:511
void uv_key_delete(uv_key_t *key)
Definition: thread.c:828
static void uv__custom_sem_wait(uv_sem_t *sem_)
Definition: thread.c:573
void uv_rwlock_wrunlock(uv_rwlock_t *rwlock)
Definition: thread.c:413
static void uv__sem_wait(uv_sem_t *sem)
Definition: thread.c:622
static int uv__sem_trywait(uv_sem_t *sem)
Definition: thread.c:634
STATIC_ASSERT(sizeof(uv_thread_t)<=sizeof(void *))
static uv_mutex_t mutex
Definition: threadpool.c:34
Definition: win.h:249
UV_PLATFORM_SEM_T uv_sem_t
Definition: unix.h:139
pthread_mutex_t uv_mutex_t
Definition: unix.h:137
pthread_t uv_thread_t
Definition: unix.h:136
pthread_once_t uv_once_t
Definition: unix.h:135
#define UV_ONCE_INIT
Definition: unix.h:133
void error(const char *msg)
Definition: untgz.c:593
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__free(void *ptr)
Definition: uv-common.c:81
@ UV_THREAD_HAS_STACK_SIZE
Definition: uv.h:1749
@ UV_THREAD_NO_FLAGS
Definition: uv.h:1748