pthread_create.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "pthread_impl.h"
  2. #include "stdio_impl.h"
  3. static void dummy_0()
  4. {
  5. }
  6. weak_alias(dummy_0, __synccall_lock);
  7. weak_alias(dummy_0, __synccall_unlock);
  8. weak_alias(dummy_0, __pthread_tsd_run_dtors);
  9. void pthread_exit(void *result)
  10. {
  11. pthread_t self = pthread_self();
  12. int n;
  13. self->result = result;
  14. while (self->cancelbuf) {
  15. void (*f)(void *) = self->cancelbuf->__f;
  16. void *x = self->cancelbuf->__x;
  17. self->cancelbuf = self->cancelbuf->__next;
  18. f(x);
  19. }
  20. __pthread_tsd_run_dtors();
  21. __lock(&self->exitlock);
  22. /* Mark this thread dead before decrementing count */
  23. __lock(&self->killlock);
  24. self->dead = 1;
  25. a_store(&self->killlock, 0);
  26. do n = libc.threads_minus_1;
  27. while (n && a_cas(&libc.threads_minus_1, n, n-1)!=n);
  28. if (!n) exit(0);
  29. if (self->detached && self->map_base) {
  30. __syscall(SYS_rt_sigprocmask, SIG_BLOCK, (uint64_t[]){-1},0,8);
  31. __unmapself(self->map_base, self->map_size);
  32. }
  33. __syscall(SYS_exit, 0);
  34. }
  35. void __do_cleanup_push(struct __ptcb *cb, void (*f)(void *), void *x)
  36. {
  37. struct pthread *self = pthread_self();
  38. cb->__next = self->cancelbuf;
  39. self->cancelbuf = cb;
  40. }
  41. void __do_cleanup_pop(struct __ptcb *cb, int run)
  42. {
  43. __pthread_self()->cancelbuf = cb->__next;
  44. }
  45. static int start(void *p)
  46. {
  47. pthread_t self = p;
  48. if (self->unblock_cancel)
  49. __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, 8);
  50. pthread_exit(self->start(self->start_arg));
  51. return 0;
  52. }
  53. #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
  54. /* pthread_key_create.c overrides this */
  55. static const size_t dummy = 0;
  56. weak_alias(dummy, __pthread_tsd_size);
  57. static FILE *const dummy_file = 0;
  58. weak_alias(dummy_file, __stdin_used);
  59. weak_alias(dummy_file, __stdout_used);
  60. weak_alias(dummy_file, __stderr_used);
  61. static void init_file_lock(FILE *f)
  62. {
  63. if (f && f->lock<0) f->lock = 0;
  64. }
  65. int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(void *), void *arg)
  66. {
  67. int ret;
  68. size_t size = DEFAULT_STACK_SIZE + DEFAULT_GUARD_SIZE;
  69. size_t guard = DEFAULT_GUARD_SIZE;
  70. struct pthread *self = pthread_self(), *new;
  71. unsigned char *map, *stack, *tsd;
  72. if (!self) return ENOSYS;
  73. if (!libc.threaded) {
  74. for (FILE *f=libc.ofl_head; f; f=f->next)
  75. init_file_lock(f);
  76. init_file_lock(__stdin_used);
  77. init_file_lock(__stdout_used);
  78. init_file_lock(__stderr_used);
  79. __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, 8);
  80. libc.threaded = 1;
  81. }
  82. if (attr) {
  83. guard = ROUND(attr->_a_guardsize + DEFAULT_GUARD_SIZE);
  84. size = guard + ROUND(attr->_a_stacksize + DEFAULT_STACK_SIZE);
  85. }
  86. size += __pthread_tsd_size;
  87. map = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
  88. if (map == MAP_FAILED) return EAGAIN;
  89. if (guard) mprotect(map, guard, PROT_NONE);
  90. tsd = map + size - __pthread_tsd_size;
  91. new = (void *)(tsd - sizeof *new - PAGE_SIZE%sizeof *new);
  92. new->map_base = map;
  93. new->map_size = size;
  94. new->pid = self->pid;
  95. new->errno_ptr = &new->errno_val;
  96. new->start = entry;
  97. new->start_arg = arg;
  98. new->self = new;
  99. new->tsd = (void *)tsd;
  100. if (attr) new->detached = attr->_a_detach;
  101. new->unblock_cancel = self->cancel;
  102. new->canary = self->canary ^ (uintptr_t)&new;
  103. stack = (void *)new;
  104. __synccall_lock();
  105. a_inc(&libc.threads_minus_1);
  106. ret = __clone(start, stack, 0x7d8f00, new, &new->tid, new, &new->tid);
  107. __synccall_unlock();
  108. if (ret < 0) {
  109. a_dec(&libc.threads_minus_1);
  110. munmap(map, size);
  111. return EAGAIN;
  112. }
  113. *res = new;
  114. return 0;
  115. }