+ if (__block_new_threads) __wait(&__block_new_threads, 0, 1, 1);
+
+ if (attr._a_stackaddr) {
+ size_t need = libc.tls_size + __pthread_tsd_size;
+ size = attr._a_stacksize;
+ stack = (void *)(attr._a_stackaddr & -16);
+ stack_limit = (void *)(attr._a_stackaddr - size);
+ /* Use application-provided stack for TLS only when
+ * it does not take more than ~12% or 2k of the
+ * application's stack space. */
+ if (need < size/8 && need < 2048) {
+ tsd = stack - __pthread_tsd_size;
+ stack = tsd - libc.tls_size;
+ memset(stack, 0, need);
+ } else {
+ size = ROUND(need);
+ }
+ guard = 0;
+ } else {
+ guard = ROUND(attr._a_guardsize);
+ size = guard + ROUND(attr._a_stacksize
+ + libc.tls_size + __pthread_tsd_size);
+ }
+
+ if (!tsd) {
+ if (guard) {
+ map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (map == MAP_FAILED) goto fail;
+ if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)
+ && errno != ENOSYS) {
+ __munmap(map, size);
+ goto fail;
+ }
+ } else {
+ map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (map == MAP_FAILED) goto fail;
+ }
+ tsd = map + size - __pthread_tsd_size;
+ if (!stack) {
+ stack = tsd - libc.tls_size;
+ stack_limit = map + guard;
+ }