- if (!init && ++init) init_threads();
-
- if (!attr) attr = &default_attr;
- guard = ROUND(attr->_a_guardsize + DEFAULT_GUARD_SIZE);
- size = guard + ROUND(attr->_a_stacksize + DEFAULT_STACK_SIZE);
- size += __pthread_tsd_size;
- map = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
- if (!map) return EAGAIN;
- if (guard) mprotect(map, guard, PROT_NONE);
-
- tsd = map + size - __pthread_tsd_size;
- new = (void *)(tsd - sizeof *new - PAGE_SIZE%sizeof *new);
+ if (!libc.threaded) {
+ for (FILE *f=libc.ofl_head; f; f=f->next)
+ init_file_lock(f);
+ init_file_lock(__stdin_used);
+ init_file_lock(__stdout_used);
+ init_file_lock(__stderr_used);
+ libc.threaded = 1;
+ }
+
+ __acquire_ptc();
+
+ if (attr && attr->_a_stackaddr) {
+ map = 0;
+ tsd = (void *)(attr->_a_stackaddr-__pthread_tsd_size & -16);
+ } else {
+ if (attr) {
+ guard = ROUND(attr->_a_guardsize + DEFAULT_GUARD_SIZE);
+ size = guard + ROUND(attr->_a_stacksize
+ + DEFAULT_STACK_SIZE + libc.tls_size);
+ }
+ size += __pthread_tsd_size;
+ if (guard) {
+ map = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (map == MAP_FAILED) return EAGAIN;
+ if (mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)) {
+ munmap(map, size);
+ return EAGAIN;
+ }
+ } else {
+ map = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (map == MAP_FAILED) return EAGAIN;
+ }
+ tsd = map + size - __pthread_tsd_size;
+ }
+ new = __copy_tls(stack = tsd - libc.tls_size);