pthread_create.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #define _GNU_SOURCE
  2. #include "pthread_impl.h"
  3. #include "stdio_impl.h"
  4. #include "libc.h"
  5. #include <sys/mman.h>
  6. #include <string.h>
  7. #include <stddef.h>
  8. void *__mmap(void *, size_t, int, int, int, off_t);
  9. int __munmap(void *, size_t);
  10. int __mprotect(void *, size_t, int);
  11. static void dummy_0()
  12. {
  13. }
  14. weak_alias(dummy_0, __acquire_ptc);
  15. weak_alias(dummy_0, __release_ptc);
  16. weak_alias(dummy_0, __pthread_tsd_run_dtors);
  17. weak_alias(dummy_0, __do_orphaned_stdio_locks);
  18. weak_alias(dummy_0, __dl_thread_cleanup);
  19. static void *dummy_1(void *p)
  20. {
  21. return 0;
  22. }
  23. weak_alias(dummy_1, __start_sched);
  24. _Noreturn void __pthread_exit(void *result)
  25. {
  26. pthread_t self = __pthread_self();
  27. sigset_t set;
  28. self->canceldisable = 1;
  29. self->cancelasync = 0;
  30. self->result = result;
  31. while (self->cancelbuf) {
  32. void (*f)(void *) = self->cancelbuf->__f;
  33. void *x = self->cancelbuf->__x;
  34. self->cancelbuf = self->cancelbuf->__next;
  35. f(x);
  36. }
  37. __pthread_tsd_run_dtors();
  38. /* Access to target the exiting thread with syscalls that use
  39. * its kernel tid is controlled by killlock. For detached threads,
  40. * any use past this point would have undefined behavior, but for
  41. * joinable threads it's a valid usage that must be handled. */
  42. LOCK(self->killlock);
  43. /* Block all signals before decrementing the live thread count.
  44. * This is important to ensure that dynamically allocated TLS
  45. * is not under-allocated/over-committed, and possibly for other
  46. * reasons as well. */
  47. __block_all_sigs(&set);
  48. /* It's impossible to determine whether this is "the last thread"
  49. * until performing the atomic decrement, since multiple threads
  50. * could exit at the same time. For the last thread, revert the
  51. * decrement, restore the tid, and unblock signals to give the
  52. * atexit handlers and stdio cleanup code a consistent state. */
  53. if (a_fetch_add(&libc.threads_minus_1, -1)==0) {
  54. libc.threads_minus_1 = 0;
  55. UNLOCK(self->killlock);
  56. __restore_sigs(&set);
  57. exit(0);
  58. }
  59. /* Process robust list in userspace to handle non-pshared mutexes
  60. * and the detached thread case where the robust list head will
  61. * be invalid when the kernel would process it. */
  62. __vm_lock();
  63. volatile void *volatile *rp;
  64. while ((rp=self->robust_list.head) && rp != &self->robust_list.head) {
  65. pthread_mutex_t *m = (void *)((char *)rp
  66. - offsetof(pthread_mutex_t, _m_next));
  67. int waiters = m->_m_waiters;
  68. int priv = (m->_m_type & 128) ^ 128;
  69. self->robust_list.pending = rp;
  70. self->robust_list.head = *rp;
  71. int cont = a_swap(&m->_m_lock, 0x40000000);
  72. self->robust_list.pending = 0;
  73. if (cont < 0 || waiters)
  74. __wake(&m->_m_lock, 1, priv);
  75. }
  76. __vm_unlock();
  77. __do_orphaned_stdio_locks();
  78. __dl_thread_cleanup();
  79. /* This atomic potentially competes with a concurrent pthread_detach
  80. * call; the loser is responsible for freeing thread resources. */
  81. int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING);
  82. if (state>=DT_DETACHED && self->map_base) {
  83. /* Detached threads must avoid the kernel clear_child_tid
  84. * feature, since the virtual address will have been
  85. * unmapped and possibly already reused by a new mapping
  86. * at the time the kernel would perform the write. In
  87. * the case of threads that started out detached, the
  88. * initial clone flags are correct, but if the thread was
  89. * detached later, we need to clear it here. */
  90. if (state == DT_DYNAMIC) __syscall(SYS_set_tid_address, 0);
  91. /* Robust list will no longer be valid, and was already
  92. * processed above, so unregister it with the kernel. */
  93. if (self->robust_list.off)
  94. __syscall(SYS_set_robust_list, 0, 3*sizeof(long));
  95. /* Since __unmapself bypasses the normal munmap code path,
  96. * explicitly wait for vmlock holders first. */
  97. __vm_wait();
  98. /* The following call unmaps the thread's stack mapping
  99. * and then exits without touching the stack. */
  100. __unmapself(self->map_base, self->map_size);
  101. }
  102. /* After the kernel thread exits, its tid may be reused. Clear it
  103. * to prevent inadvertent use and inform functions that would use
  104. * it that it's no longer available. */
  105. self->tid = 0;
  106. UNLOCK(self->killlock);
  107. for (;;) __syscall(SYS_exit, 0);
  108. }
  109. void __do_cleanup_push(struct __ptcb *cb)
  110. {
  111. struct pthread *self = __pthread_self();
  112. cb->__next = self->cancelbuf;
  113. self->cancelbuf = cb;
  114. }
  115. void __do_cleanup_pop(struct __ptcb *cb)
  116. {
  117. __pthread_self()->cancelbuf = cb->__next;
  118. }
  119. static int start(void *p)
  120. {
  121. pthread_t self = p;
  122. if (self->unblock_cancel)
  123. __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
  124. SIGPT_SET, 0, _NSIG/8);
  125. __pthread_exit(self->start(self->start_arg));
  126. return 0;
  127. }
  128. static int start_c11(void *p)
  129. {
  130. pthread_t self = p;
  131. int (*start)(void*) = (int(*)(void*)) self->start;
  132. __pthread_exit((void *)(uintptr_t)start(self->start_arg));
  133. return 0;
  134. }
  135. #define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
  136. /* pthread_key_create.c overrides this */
  137. static volatile size_t dummy = 0;
  138. weak_alias(dummy, __pthread_tsd_size);
  139. static void *dummy_tsd[1] = { 0 };
  140. weak_alias(dummy_tsd, __pthread_tsd_main);
  141. volatile int __block_new_threads = 0;
  142. extern size_t __default_stacksize;
  143. extern size_t __default_guardsize;
  144. static FILE *volatile dummy_file = 0;
  145. weak_alias(dummy_file, __stdin_used);
  146. weak_alias(dummy_file, __stdout_used);
  147. weak_alias(dummy_file, __stderr_used);
  148. static void init_file_lock(FILE *f)
  149. {
  150. if (f && f->lock<0) f->lock = 0;
  151. }
  152. void *__copy_tls(unsigned char *);
  153. int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
  154. {
  155. int ret, c11 = (attrp == __ATTRP_C11_THREAD);
  156. size_t size, guard;
  157. struct pthread *self, *new;
  158. unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit;
  159. unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
  160. | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS
  161. | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED;
  162. int do_sched = 0;
  163. pthread_attr_t attr = { 0 };
  164. struct start_sched_args ssa;
  165. if (!libc.can_do_threads) return ENOSYS;
  166. self = __pthread_self();
  167. if (!libc.threaded) {
  168. for (FILE *f=*__ofl_lock(); f; f=f->next)
  169. init_file_lock(f);
  170. __ofl_unlock();
  171. init_file_lock(__stdin_used);
  172. init_file_lock(__stdout_used);
  173. init_file_lock(__stderr_used);
  174. __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8);
  175. self->tsd = (void **)__pthread_tsd_main;
  176. libc.threaded = 1;
  177. }
  178. if (attrp && !c11) attr = *attrp;
  179. __acquire_ptc();
  180. if (!attrp || c11) {
  181. attr._a_stacksize = __default_stacksize;
  182. attr._a_guardsize = __default_guardsize;
  183. }
  184. if (__block_new_threads) __wait(&__block_new_threads, 0, 1, 1);
  185. if (attr._a_stackaddr) {
  186. size_t need = libc.tls_size + __pthread_tsd_size;
  187. size = attr._a_stacksize;
  188. stack = (void *)(attr._a_stackaddr & -16);
  189. stack_limit = (void *)(attr._a_stackaddr - size);
  190. /* Use application-provided stack for TLS only when
  191. * it does not take more than ~12% or 2k of the
  192. * application's stack space. */
  193. if (need < size/8 && need < 2048) {
  194. tsd = stack - __pthread_tsd_size;
  195. stack = tsd - libc.tls_size;
  196. memset(stack, 0, need);
  197. } else {
  198. size = ROUND(need);
  199. }
  200. guard = 0;
  201. } else {
  202. guard = ROUND(attr._a_guardsize);
  203. size = guard + ROUND(attr._a_stacksize
  204. + libc.tls_size + __pthread_tsd_size);
  205. }
  206. if (!tsd) {
  207. if (guard) {
  208. map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
  209. if (map == MAP_FAILED) goto fail;
  210. if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)
  211. && errno != ENOSYS) {
  212. __munmap(map, size);
  213. goto fail;
  214. }
  215. } else {
  216. map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
  217. if (map == MAP_FAILED) goto fail;
  218. }
  219. tsd = map + size - __pthread_tsd_size;
  220. if (!stack) {
  221. stack = tsd - libc.tls_size;
  222. stack_limit = map + guard;
  223. }
  224. }
  225. new = __copy_tls(tsd - libc.tls_size);
  226. new->map_base = map;
  227. new->map_size = size;
  228. new->stack = stack;
  229. new->stack_size = stack - stack_limit;
  230. new->guard_size = guard;
  231. new->start = entry;
  232. new->start_arg = arg;
  233. new->self = new;
  234. new->tsd = (void *)tsd;
  235. new->locale = &libc.global_locale;
  236. if (attr._a_detach) {
  237. new->detach_state = DT_DETACHED;
  238. flags -= CLONE_CHILD_CLEARTID;
  239. } else {
  240. new->detach_state = DT_JOINABLE;
  241. }
  242. if (attr._a_sched) {
  243. do_sched = 1;
  244. ssa.futex = -1;
  245. ssa.start_fn = new->start;
  246. ssa.start_arg = new->start_arg;
  247. ssa.attr = &attr;
  248. new->start = __start_sched;
  249. new->start_arg = &ssa;
  250. __block_app_sigs(&ssa.mask);
  251. }
  252. new->robust_list.head = &new->robust_list.head;
  253. new->unblock_cancel = self->cancel;
  254. new->CANARY = self->CANARY;
  255. a_inc(&libc.threads_minus_1);
  256. ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->detach_state);
  257. __release_ptc();
  258. if (do_sched) {
  259. __restore_sigs(&ssa.mask);
  260. }
  261. if (ret < 0) {
  262. a_dec(&libc.threads_minus_1);
  263. if (map) __munmap(map, size);
  264. return EAGAIN;
  265. }
  266. if (do_sched) {
  267. __futexwait(&ssa.futex, -1, 1);
  268. ret = ssa.futex;
  269. if (ret) return ret;
  270. }
  271. *res = new;
  272. return 0;
  273. fail:
  274. __release_ptc();
  275. return EAGAIN;
  276. }
  277. weak_alias(__pthread_exit, pthread_exit);
  278. weak_alias(__pthread_create, pthread_create);