2013-09-16 10:54:31 -04:00
|
|
|
#define _GNU_SOURCE
|
2011-02-12 00:22:29 -05:00
|
|
|
#include "pthread_impl.h"
|
2011-07-30 08:02:14 -04:00
|
|
|
#include "stdio_impl.h"
|
2013-09-15 02:00:32 +00:00
|
|
|
#include "libc.h"
|
2012-11-08 17:04:20 -05:00
|
|
|
#include <sys/mman.h>
|
2014-08-22 14:05:10 -04:00
|
|
|
#include <string.h>
|
2015-04-10 00:26:34 -04:00
|
|
|
#include <stddef.h>
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2014-09-01 00:46:23 +02:00
|
|
|
void *__mmap(void *, size_t, int, int, int, off_t);
|
|
|
|
int __munmap(void *, size_t);
|
|
|
|
int __mprotect(void *, size_t, int);
|
2015-04-10 00:26:34 -04:00
|
|
|
void __vm_lock_impl(int);
|
|
|
|
void __vm_unlock_impl(void);
|
2014-09-01 00:46:23 +02:00
|
|
|
|
2011-04-06 20:27:07 -04:00
|
|
|
static void dummy_0()
|
|
|
|
{
|
|
|
|
}
|
2012-10-05 11:51:50 -04:00
|
|
|
weak_alias(dummy_0, __acquire_ptc);
|
|
|
|
weak_alias(dummy_0, __release_ptc);
|
2011-04-19 23:09:14 -04:00
|
|
|
weak_alias(dummy_0, __pthread_tsd_run_dtors);
|
2014-08-23 23:35:10 -04:00
|
|
|
weak_alias(dummy_0, __do_orphaned_stdio_locks);
|
2011-04-03 02:33:50 -04:00
|
|
|
|
2014-09-01 00:46:23 +02:00
|
|
|
_Noreturn void __pthread_exit(void *result)
|
2011-02-13 19:58:30 -05:00
|
|
|
{
|
2014-06-10 04:02:40 -04:00
|
|
|
pthread_t self = __pthread_self();
|
2013-04-26 16:16:04 -04:00
|
|
|
sigset_t set;
|
2011-02-13 19:58:30 -05:00
|
|
|
|
2015-02-16 22:25:50 -05:00
|
|
|
self->canceldisable = 1;
|
|
|
|
self->cancelasync = 0;
|
2012-02-09 02:33:08 -05:00
|
|
|
self->result = result;
|
|
|
|
|
|
|
|
while (self->cancelbuf) {
|
|
|
|
void (*f)(void *) = self->cancelbuf->__f;
|
|
|
|
void *x = self->cancelbuf->__x;
|
|
|
|
self->cancelbuf = self->cancelbuf->__next;
|
|
|
|
f(x);
|
2011-04-17 17:06:05 -04:00
|
|
|
}
|
2011-02-13 19:58:30 -05:00
|
|
|
|
2011-04-19 23:09:14 -04:00
|
|
|
__pthread_tsd_run_dtors();
|
2011-02-13 19:58:30 -05:00
|
|
|
|
2012-07-12 11:23:43 -04:00
|
|
|
__lock(self->exitlock);
|
2011-06-14 01:25:17 -04:00
|
|
|
|
2011-03-10 18:31:37 -05:00
|
|
|
/* Mark this thread dead before decrementing count */
|
2012-07-12 11:23:43 -04:00
|
|
|
__lock(self->killlock);
|
2011-03-10 18:31:37 -05:00
|
|
|
self->dead = 1;
|
2011-02-19 11:04:36 -05:00
|
|
|
|
2013-04-26 16:04:30 -04:00
|
|
|
/* Block all signals before decrementing the live thread count.
|
|
|
|
* This is important to ensure that dynamically allocated TLS
|
|
|
|
* is not under-allocated/over-committed, and possibly for other
|
|
|
|
* reasons as well. */
|
2013-04-26 19:48:01 -04:00
|
|
|
__block_all_sigs(&set);
|
2013-04-26 15:47:44 -04:00
|
|
|
|
2013-04-26 17:51:22 -04:00
|
|
|
/* Wait to unlock the kill lock, which governs functions like
|
|
|
|
* pthread_kill which target a thread id, until signals have
|
|
|
|
* been blocked. This precludes observation of the thread id
|
|
|
|
* as a live thread (with application code running in it) after
|
|
|
|
* the thread was reported dead by ESRCH being returned. */
|
|
|
|
__unlock(self->killlock);
|
|
|
|
|
2013-04-26 16:16:04 -04:00
|
|
|
/* It's impossible to determine whether this is "the last thread"
|
|
|
|
* until performing the atomic decrement, since multiple threads
|
|
|
|
* could exit at the same time. For the last thread, revert the
|
|
|
|
* decrement and unblock signals to give the atexit handlers and
|
|
|
|
* stdio cleanup code a consistent state. */
|
|
|
|
if (a_fetch_add(&libc.threads_minus_1, -1)==0) {
|
|
|
|
libc.threads_minus_1 = 0;
|
2013-04-26 19:48:01 -04:00
|
|
|
__restore_sigs(&set);
|
2013-04-26 16:16:04 -04:00
|
|
|
exit(0);
|
|
|
|
}
|
2011-02-19 10:38:57 -05:00
|
|
|
|
add locale framework
this commit adds non-stub implementations of setlocale, duplocale,
newlocale, and uselocale, along with the data structures and minimal
code needed for representing the active locale on a per-thread basis
and optimizing the common case where thread-local locale settings are
not in use.
at this point, the data structures only contain what is necessary to
represent LC_CTYPE (a single flag) and LC_MESSAGES (a name for use in
finding message translation files). representation for the other
categories will be added later; the expectation is that a single
pointer will suffice for each.
for LC_CTYPE, the strings "C" and "POSIX" are treated as special; any
other string is accepted and treated as "C.UTF-8". for other
categories, any string is accepted after being truncated to a maximum
supported length (currently 15 bytes). for LC_MESSAGES, the name is
kept regardless of whether libc itself can use such a message
translation locale, since applications using catgets or gettext should
be able to use message locales libc is not aware of. for other
categories, names which are not successfully loaded as locales (which,
at present, means all names) are treated as aliases for "C". setlocale
never fails.
locale settings are not yet used anywhere, so this commit should have
no visible effects except for the contents of the string returned by
setlocale.
2014-07-02 19:33:19 -04:00
|
|
|
if (self->locale != &libc.global_locale) {
|
|
|
|
a_dec(&libc.uselocale_cnt);
|
|
|
|
if (self->locale->ctype_utf8)
|
|
|
|
a_dec(&libc.bytelocale_cnt_minus_1);
|
|
|
|
}
|
|
|
|
|
2015-04-10 00:26:34 -04:00
|
|
|
/* Process robust list in userspace to handle non-pshared mutexes
|
|
|
|
* and the detached thread case where the robust list head will
|
|
|
|
* be invalid when the kernel would process it. */
|
|
|
|
__vm_lock_impl(+1);
|
|
|
|
volatile void *volatile *rp;
|
|
|
|
while ((rp=self->robust_list.head) && rp != &self->robust_list.head) {
|
|
|
|
pthread_mutex_t *m = (void *)((char *)rp
|
|
|
|
- offsetof(pthread_mutex_t, _m_next));
|
|
|
|
int waiters = m->_m_waiters;
|
|
|
|
int priv = (m->_m_type & 128) ^ 128;
|
|
|
|
self->robust_list.pending = rp;
|
|
|
|
self->robust_list.head = *rp;
|
|
|
|
int cont = a_swap(&m->_m_lock, self->tid|0x40000000);
|
|
|
|
self->robust_list.pending = 0;
|
|
|
|
if (cont < 0 || waiters)
|
|
|
|
__wake(&m->_m_lock, 1, priv);
|
|
|
|
}
|
|
|
|
__vm_unlock_impl();
|
|
|
|
|
2014-08-23 23:35:10 -04:00
|
|
|
__do_orphaned_stdio_locks();
|
2014-08-16 02:28:34 -04:00
|
|
|
|
2011-03-10 18:31:37 -05:00
|
|
|
if (self->detached && self->map_base) {
|
2013-04-26 16:04:30 -04:00
|
|
|
/* Detached threads must avoid the kernel clear_child_tid
|
|
|
|
* feature, since the virtual address will have been
|
|
|
|
* unmapped and possibly already reused by a new mapping
|
|
|
|
* at the time the kernel would perform the write. In
|
|
|
|
* the case of threads that started out detached, the
|
|
|
|
* initial clone flags are correct, but if the thread was
|
|
|
|
* detached later (== 2), we need to clear it here. */
|
|
|
|
if (self->detached == 2) __syscall(SYS_set_tid_address, 0);
|
|
|
|
|
2015-04-10 00:26:34 -04:00
|
|
|
/* Robust list will no longer be valid, and was already
|
|
|
|
* processed above, so unregister it with the kernel. */
|
|
|
|
if (self->robust_list.off)
|
|
|
|
__syscall(SYS_set_robust_list, 0, 3*sizeof(long));
|
|
|
|
|
2013-04-26 16:04:30 -04:00
|
|
|
/* The following call unmaps the thread's stack mapping
|
|
|
|
* and then exits without touching the stack. */
|
2011-02-13 19:58:30 -05:00
|
|
|
__unmapself(self->map_base, self->map_size);
|
2011-03-10 18:31:37 -05:00
|
|
|
}
|
2011-02-13 19:58:30 -05:00
|
|
|
|
further use of _Noreturn, for non-plain-C functions
note that POSIX does not specify these functions as _Noreturn, because
POSIX is aligned with C99, not the new C11 standard. when POSIX is
eventually updated to C11, it will almost surely give these functions
the _Noreturn attribute. for now, the actual _Noreturn keyword is not
used anyway when compiling with a c99 compiler, which is what POSIX
requires; the GCC __attribute__ is used instead if it's available,
however.
in a few places, I've added infinite for loops at the end of _Noreturn
functions to silence compiler warnings. presumably
__buildin_unreachable could achieve the same thing, but it would only
work on newer GCCs and would not be portable. the loops should have
near-zero code size cost anyway.
like the previous _Noreturn commit, this one is based on patches
contributed by philomath.
2012-09-06 23:34:10 -04:00
|
|
|
for (;;) __syscall(SYS_exit, 0);
|
2011-02-13 19:58:30 -05:00
|
|
|
}
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-05-23 14:13:54 -04:00
|
|
|
void __do_cleanup_push(struct __ptcb *cb)
|
2011-08-03 19:57:46 -04:00
|
|
|
{
|
always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.
previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.
in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.
some notes on specific changes:
- the confusing use of libc.main_thread as an indicator that the
thread pointer is initialized is eliminated in favor of an explicit
has_thread_pointer predicate.
- sigaction no longer needs to ensure that the thread pointer is
initialized before installing a signal handler (this was needed to
prevent a situation where the signal handler caused the thread
pointer to be initialized and the subsequent sigreturn cleared it
again) but it still needs to ensure that implementation-internal
thread-related signals are not blocked.
- pthread tsd initialization for the main thread is deferred in a new
manner to minimize bloat in the static-linked __init_tp code.
- pthread_setcancelstate no longer needs special handling for the
situation before the thread pointer is initialized. it simply fails
on systems that cannot support a thread pointer, which are
non-conforming anyway.
- pthread_cleanup_push/pop now check for missing thread pointer and
nop themselves out in this case, so stdio no longer needs to avoid
the cancellable path when the thread pointer is not available.
a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
|
|
|
if (!libc.has_thread_pointer) return;
|
2014-06-10 04:02:40 -04:00
|
|
|
struct pthread *self = __pthread_self();
|
2011-08-03 19:57:46 -04:00
|
|
|
cb->__next = self->cancelbuf;
|
|
|
|
self->cancelbuf = cb;
|
|
|
|
}
|
|
|
|
|
2012-05-23 14:13:54 -04:00
|
|
|
void __do_cleanup_pop(struct __ptcb *cb)
|
2011-08-03 19:57:46 -04:00
|
|
|
{
|
always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.
previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.
in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.
some notes on specific changes:
- the confusing use of libc.main_thread as an indicator that the
thread pointer is initialized is eliminated in favor of an explicit
has_thread_pointer predicate.
- sigaction no longer needs to ensure that the thread pointer is
initialized before installing a signal handler (this was needed to
prevent a situation where the signal handler caused the thread
pointer to be initialized and the subsequent sigreturn cleared it
again) but it still needs to ensure that implementation-internal
thread-related signals are not blocked.
- pthread tsd initialization for the main thread is deferred in a new
manner to minimize bloat in the static-linked __init_tp code.
- pthread_setcancelstate no longer needs special handling for the
situation before the thread pointer is initialized. it simply fails
on systems that cannot support a thread pointer, which are
non-conforming anyway.
- pthread_cleanup_push/pop now check for missing thread pointer and
nop themselves out in this case, so stdio no longer needs to avoid
the cancellable path when the thread pointer is not available.
a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
|
|
|
if (!libc.has_thread_pointer) return;
|
2012-02-09 02:33:08 -05:00
|
|
|
__pthread_self()->cancelbuf = cb->__next;
|
2011-08-03 19:57:46 -04:00
|
|
|
}
|
|
|
|
|
overhaul clone syscall wrapping
several things are changed. first, i have removed the old __uniclone
function signature and replaced it with the "standard" linux
__clone/clone signature. this was necessary to expose clone to
applications anyway, and it makes it easier to port __clone to new
archs, since it's now testable independently of pthread_create.
secondly, i have removed all references to the ugly ldt descriptor
structure (i386 only) from the c code and pthread structure. in places
where it is needed, it is now created on the stack just when it's
needed, in assembly code. thus, the i386 __clone function takes the
desired thread pointer as its argument, rather than an ldt descriptor
pointer, just like on all other sane archs. this should not affect
applications since there is really no way an application can use clone
with threads/tls in a way that doesn't horribly conflict with and
clobber the underlying implementation's use. applications are expected
to use clone only for creating actual processes, possibly with new
namespace features and whatnot.
2011-09-18 10:14:37 -04:00
|
|
|
static int start(void *p)
|
2011-02-12 00:22:29 -05:00
|
|
|
{
|
overhaul clone syscall wrapping
several things are changed. first, i have removed the old __uniclone
function signature and replaced it with the "standard" linux
__clone/clone signature. this was necessary to expose clone to
applications anyway, and it makes it easier to port __clone to new
archs, since it's now testable independently of pthread_create.
secondly, i have removed all references to the ugly ldt descriptor
structure (i386 only) from the c code and pthread structure. in places
where it is needed, it is now created on the stack just when it's
needed, in assembly code. thus, the i386 __clone function takes the
desired thread pointer as its argument, rather than an ldt descriptor
pointer, just like on all other sane archs. this should not affect
applications since there is really no way an application can use clone
with threads/tls in a way that doesn't horribly conflict with and
clobber the underlying implementation's use. applications are expected
to use clone only for creating actual processes, possibly with new
namespace features and whatnot.
2011-09-18 10:14:37 -04:00
|
|
|
pthread_t self = p;
|
2012-11-11 15:38:04 -05:00
|
|
|
if (self->startlock[0]) {
|
|
|
|
__wait(self->startlock, 0, 1, 1);
|
|
|
|
if (self->startlock[0]) {
|
|
|
|
self->detached = 2;
|
|
|
|
pthread_exit(0);
|
|
|
|
}
|
2013-04-26 19:48:01 -04:00
|
|
|
__restore_sigs(self->sigmask);
|
2012-11-11 15:38:04 -05:00
|
|
|
}
|
overhaul implementation-internal signal protections
the new approach relies on the fact that the only ways to create
sigset_t objects without invoking UB are to use the sig*set()
functions, or from the masks returned by sigprocmask, sigaction, etc.
or in the ucontext_t argument to a signal handler. thus, as long as
sigfillset and sigaddset avoid adding the "protected" signals, there
is no way the application will ever obtain a sigset_t including these
bits, and thus no need to add the overhead of checking/clearing them
when sigprocmask or sigaction is called.
note that the old code actually *failed* to remove the bits from
sa_mask when sigaction was called.
the new implementations are also significantly smaller, simpler, and
faster due to ignoring the useless "GNU HURD signals" 65-1024, which
are not used and, if there's any sanity in the world, never will be
used.
2011-05-07 23:23:58 -04:00
|
|
|
if (self->unblock_cancel)
|
2012-08-09 22:52:13 -04:00
|
|
|
__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
|
2013-03-26 23:07:31 -04:00
|
|
|
SIGPT_SET, 0, _NSIG/8);
|
2014-09-07 10:28:08 -04:00
|
|
|
__pthread_exit(self->start(self->start_arg));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int start_c11(void *p)
|
|
|
|
{
|
|
|
|
pthread_t self = p;
|
|
|
|
int (*start)(void*) = (int(*)(void*)) self->start;
|
|
|
|
__pthread_exit((void *)(uintptr_t)start(self->start_arg));
|
overhaul clone syscall wrapping
several things are changed. first, i have removed the old __uniclone
function signature and replaced it with the "standard" linux
__clone/clone signature. this was necessary to expose clone to
applications anyway, and it makes it easier to port __clone to new
archs, since it's now testable independently of pthread_create.
secondly, i have removed all references to the ugly ldt descriptor
structure (i386 only) from the c code and pthread structure. in places
where it is needed, it is now created on the stack just when it's
needed, in assembly code. thus, the i386 __clone function takes the
desired thread pointer as its argument, rather than an ldt descriptor
pointer, just like on all other sane archs. this should not affect
applications since there is really no way an application can use clone
with threads/tls in a way that doesn't horribly conflict with and
clobber the underlying implementation's use. applications are expected
to use clone only for creating actual processes, possibly with new
namespace features and whatnot.
2011-09-18 10:14:37 -04:00
|
|
|
return 0;
|
2011-02-12 00:22:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#define ROUND(x) (((x)+PAGE_SIZE-1)&-PAGE_SIZE)
|
|
|
|
|
|
|
|
/* pthread_key_create.c overrides this */
|
2014-07-16 21:32:06 -04:00
|
|
|
static volatile size_t dummy = 0;
|
2011-02-12 00:22:29 -05:00
|
|
|
weak_alias(dummy, __pthread_tsd_size);
|
2014-07-16 21:32:06 -04:00
|
|
|
static void *dummy_tsd[1] = { 0 };
|
always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.
previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.
in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.
some notes on specific changes:
- the confusing use of libc.main_thread as an indicator that the
thread pointer is initialized is eliminated in favor of an explicit
has_thread_pointer predicate.
- sigaction no longer needs to ensure that the thread pointer is
initialized before installing a signal handler (this was needed to
prevent a situation where the signal handler caused the thread
pointer to be initialized and the subsequent sigreturn cleared it
again) but it still needs to ensure that implementation-internal
thread-related signals are not blocked.
- pthread tsd initialization for the main thread is deferred in a new
manner to minimize bloat in the static-linked __init_tp code.
- pthread_setcancelstate no longer needs special handling for the
situation before the thread pointer is initialized. it simply fails
on systems that cannot support a thread pointer, which are
non-conforming anyway.
- pthread_cleanup_push/pop now check for missing thread pointer and
nop themselves out in this case, so stdio no longer needs to avoid
the cancellable path when the thread pointer is not available.
a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
|
|
|
weak_alias(dummy_tsd, __pthread_tsd_main);
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2015-01-15 23:17:38 -05:00
|
|
|
volatile int __block_new_threads = 0;
|
|
|
|
|
2014-07-16 21:32:06 -04:00
|
|
|
static FILE *volatile dummy_file = 0;
|
2011-07-30 08:02:14 -04:00
|
|
|
weak_alias(dummy_file, __stdin_used);
|
|
|
|
weak_alias(dummy_file, __stdout_used);
|
|
|
|
weak_alias(dummy_file, __stderr_used);
|
|
|
|
|
|
|
|
static void init_file_lock(FILE *f)
|
|
|
|
{
|
|
|
|
if (f && f->lock<0) f->lock = 0;
|
|
|
|
}
|
|
|
|
|
2012-10-05 11:51:50 -04:00
|
|
|
void *__copy_tls(unsigned char *);
|
2012-10-04 16:35:46 -04:00
|
|
|
|
2014-09-01 00:46:23 +02:00
|
|
|
int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
|
2011-02-12 00:22:29 -05:00
|
|
|
{
|
2014-09-07 10:28:08 -04:00
|
|
|
int ret, c11 = (attrp == __ATTRP_C11_THREAD);
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
size_t size, guard;
|
always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.
previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.
in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.
some notes on specific changes:
- the confusing use of libc.main_thread as an indicator that the
thread pointer is initialized is eliminated in favor of an explicit
has_thread_pointer predicate.
- sigaction no longer needs to ensure that the thread pointer is
initialized before installing a signal handler (this was needed to
prevent a situation where the signal handler caused the thread
pointer to be initialized and the subsequent sigreturn cleared it
again) but it still needs to ensure that implementation-internal
thread-related signals are not blocked.
- pthread tsd initialization for the main thread is deferred in a new
manner to minimize bloat in the static-linked __init_tp code.
- pthread_setcancelstate no longer needs special handling for the
situation before the thread pointer is initialized. it simply fails
on systems that cannot support a thread pointer, which are
non-conforming anyway.
- pthread_cleanup_push/pop now check for missing thread pointer and
nop themselves out in this case, so stdio no longer needs to avoid
the cancellable path when the thread pointer is not available.
a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
|
|
|
struct pthread *self, *new;
|
2013-03-31 23:25:55 -04:00
|
|
|
unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit;
|
2013-09-16 10:54:31 -04:00
|
|
|
unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
|
2013-09-16 10:56:01 -04:00
|
|
|
| CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS
|
2013-09-16 10:54:31 -04:00
|
|
|
| CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED;
|
2012-11-11 15:38:04 -05:00
|
|
|
int do_sched = 0;
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
pthread_attr_t attr = {0};
|
2011-02-12 00:22:29 -05:00
|
|
|
|
always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.
previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.
in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.
some notes on specific changes:
- the confusing use of libc.main_thread as an indicator that the
thread pointer is initialized is eliminated in favor of an explicit
has_thread_pointer predicate.
- sigaction no longer needs to ensure that the thread pointer is
initialized before installing a signal handler (this was needed to
prevent a situation where the signal handler caused the thread
pointer to be initialized and the subsequent sigreturn cleared it
again) but it still needs to ensure that implementation-internal
thread-related signals are not blocked.
- pthread tsd initialization for the main thread is deferred in a new
manner to minimize bloat in the static-linked __init_tp code.
- pthread_setcancelstate no longer needs special handling for the
situation before the thread pointer is initialized. it simply fails
on systems that cannot support a thread pointer, which are
non-conforming anyway.
- pthread_cleanup_push/pop now check for missing thread pointer and
nop themselves out in this case, so stdio no longer needs to avoid
the cancellable path when the thread pointer is not available.
a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
|
|
|
if (!libc.can_do_threads) return ENOSYS;
|
|
|
|
self = __pthread_self();
|
2011-04-17 16:53:54 -04:00
|
|
|
if (!libc.threaded) {
|
2011-07-30 08:02:14 -04:00
|
|
|
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);
|
always initialize thread pointer at program start
this is the first step in an overhaul aimed at greatly simplifying and
optimizing everything dealing with thread-local state.
previously, the thread pointer was initialized lazily on first access,
or at program startup if stack protector was in use, or at certain
random places where inconsistent state could be reached if it were not
initialized early. while believed to be fully correct, the logic was
fragile and non-obvious.
in the first phase of the thread pointer overhaul, support is retained
(and in some cases improved) for systems/situation where loading the
thread pointer fails, e.g. old kernels.
some notes on specific changes:
- the confusing use of libc.main_thread as an indicator that the
thread pointer is initialized is eliminated in favor of an explicit
has_thread_pointer predicate.
- sigaction no longer needs to ensure that the thread pointer is
initialized before installing a signal handler (this was needed to
prevent a situation where the signal handler caused the thread
pointer to be initialized and the subsequent sigreturn cleared it
again) but it still needs to ensure that implementation-internal
thread-related signals are not blocked.
- pthread tsd initialization for the main thread is deferred in a new
manner to minimize bloat in the static-linked __init_tp code.
- pthread_setcancelstate no longer needs special handling for the
situation before the thread pointer is initialized. it simply fails
on systems that cannot support a thread pointer, which are
non-conforming anyway.
- pthread_cleanup_push/pop now check for missing thread pointer and
nop themselves out in this case, so stdio no longer needs to avoid
the cancellable path when the thread pointer is not available.
a number of cases remain where certain interfaces may crash if the
system does not support a thread pointer. at this point, these should
be limited to pthread interfaces, and the number of such cases should
be fewer than before.
2014-03-24 16:57:11 -04:00
|
|
|
__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8);
|
2014-03-24 17:39:08 -04:00
|
|
|
self->tsd = (void **)__pthread_tsd_main;
|
2011-04-17 16:53:54 -04:00
|
|
|
libc.threaded = 1;
|
|
|
|
}
|
2014-09-07 10:28:08 -04:00
|
|
|
if (attrp && !c11) attr = *attrp;
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-10-05 11:51:50 -04:00
|
|
|
__acquire_ptc();
|
2015-01-15 23:17:38 -05:00
|
|
|
if (__block_new_threads) __wait(&__block_new_threads, 0, 1, 1);
|
2012-10-05 11:51:50 -04:00
|
|
|
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
if (attr._a_stackaddr) {
|
|
|
|
size_t need = libc.tls_size + __pthread_tsd_size;
|
|
|
|
size = attr._a_stacksize + DEFAULT_STACK_SIZE;
|
|
|
|
stack = (void *)(attr._a_stackaddr & -16);
|
2013-04-06 01:15:08 -04:00
|
|
|
stack_limit = (void *)(attr._a_stackaddr - size);
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
/* 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;
|
2014-08-22 14:05:10 -04:00
|
|
|
memset(stack, 0, need);
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
} else {
|
|
|
|
size = ROUND(need);
|
|
|
|
guard = 0;
|
2012-06-09 19:53:29 -04:00
|
|
|
}
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
} else {
|
|
|
|
guard = ROUND(DEFAULT_GUARD_SIZE + attr._a_guardsize);
|
|
|
|
size = guard + ROUND(DEFAULT_STACK_SIZE + attr._a_stacksize
|
|
|
|
+ libc.tls_size + __pthread_tsd_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!tsd) {
|
2012-10-04 16:35:46 -04:00
|
|
|
if (guard) {
|
2014-09-01 00:46:23 +02:00
|
|
|
map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
2013-02-01 22:25:19 -05:00
|
|
|
if (map == MAP_FAILED) goto fail;
|
2014-09-01 00:46:23 +02:00
|
|
|
if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)) {
|
|
|
|
__munmap(map, size);
|
2013-02-01 22:25:19 -05:00
|
|
|
goto fail;
|
2012-10-04 16:35:46 -04:00
|
|
|
}
|
|
|
|
} else {
|
2014-09-01 00:46:23 +02:00
|
|
|
map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
|
2013-02-01 22:25:19 -05:00
|
|
|
if (map == MAP_FAILED) goto fail;
|
2012-10-04 16:35:46 -04:00
|
|
|
}
|
2012-06-09 19:53:29 -04:00
|
|
|
tsd = map + size - __pthread_tsd_size;
|
2013-03-31 23:25:55 -04:00
|
|
|
if (!stack) {
|
|
|
|
stack = tsd - libc.tls_size;
|
|
|
|
stack_limit = map + guard;
|
|
|
|
}
|
2011-05-07 23:39:48 -04:00
|
|
|
}
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
|
|
|
|
new = __copy_tls(tsd - libc.tls_size);
|
2011-02-12 00:22:29 -05:00
|
|
|
new->map_base = map;
|
|
|
|
new->map_size = size;
|
2013-03-31 23:25:55 -04:00
|
|
|
new->stack = stack;
|
|
|
|
new->stack_size = stack - stack_limit;
|
2011-02-12 00:22:29 -05:00
|
|
|
new->start = entry;
|
|
|
|
new->start_arg = arg;
|
|
|
|
new->self = new;
|
|
|
|
new->tsd = (void *)tsd;
|
add locale framework
this commit adds non-stub implementations of setlocale, duplocale,
newlocale, and uselocale, along with the data structures and minimal
code needed for representing the active locale on a per-thread basis
and optimizing the common case where thread-local locale settings are
not in use.
at this point, the data structures only contain what is necessary to
represent LC_CTYPE (a single flag) and LC_MESSAGES (a name for use in
finding message translation files). representation for the other
categories will be added later; the expectation is that a single
pointer will suffice for each.
for LC_CTYPE, the strings "C" and "POSIX" are treated as special; any
other string is accepted and treated as "C.UTF-8". for other
categories, any string is accepted after being truncated to a maximum
supported length (currently 15 bytes). for LC_MESSAGES, the name is
kept regardless of whether libc itself can use such a message
translation locale, since applications using catgets or gettext should
be able to use message locales libc is not aware of. for other
categories, names which are not successfully loaded as locales (which,
at present, means all names) are treated as aliases for "C". setlocale
never fails.
locale settings are not yet used anywhere, so this commit should have
no visible effects except for the contents of the string returned by
setlocale.
2014-07-02 19:33:19 -04:00
|
|
|
new->locale = &libc.global_locale;
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
if (attr._a_detach) {
|
2012-07-11 23:36:46 -04:00
|
|
|
new->detached = 1;
|
2013-09-16 10:54:31 -04:00
|
|
|
flags -= CLONE_CHILD_CLEARTID;
|
2012-07-11 23:36:46 -04:00
|
|
|
}
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
if (attr._a_sched) {
|
2012-11-11 15:38:04 -05:00
|
|
|
do_sched = new->startlock[0] = 1;
|
2013-04-26 19:48:01 -04:00
|
|
|
__block_app_sigs(new->sigmask);
|
2012-11-11 15:38:04 -05:00
|
|
|
}
|
2011-03-29 12:58:22 -04:00
|
|
|
new->unblock_cancel = self->cancel;
|
2012-10-07 21:43:46 -04:00
|
|
|
new->canary = self->canary;
|
2011-02-12 00:22:29 -05:00
|
|
|
|
|
|
|
a_inc(&libc.threads_minus_1);
|
2014-09-07 10:28:08 -04:00
|
|
|
ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-10-05 11:51:50 -04:00
|
|
|
__release_ptc();
|
2011-02-12 00:22:29 -05:00
|
|
|
|
2012-11-11 15:38:04 -05:00
|
|
|
if (do_sched) {
|
2013-04-26 19:48:01 -04:00
|
|
|
__restore_sigs(new->sigmask);
|
2012-11-11 15:38:04 -05:00
|
|
|
}
|
|
|
|
|
2011-02-12 00:22:29 -05:00
|
|
|
if (ret < 0) {
|
|
|
|
a_dec(&libc.threads_minus_1);
|
2014-09-01 00:46:23 +02:00
|
|
|
if (map) __munmap(map, size);
|
2011-02-15 02:20:21 -05:00
|
|
|
return EAGAIN;
|
2011-02-12 00:22:29 -05:00
|
|
|
}
|
2012-11-11 15:38:04 -05:00
|
|
|
|
|
|
|
if (do_sched) {
|
|
|
|
ret = __syscall(SYS_sched_setscheduler, new->tid,
|
pthread stack treatment overhaul for application-provided stacks, etc.
the main goal of these changes is to address the case where an
application provides a stack of size N, but TLS has size M that's a
significant portion of the size N (or even larger than N), thus giving
the application less stack space than it expected or no stack at all!
the new strategy pthread_create now uses is to only put TLS on the
application-provided stack if TLS is smaller than 1/8 of the stack
size or 2k, whichever is smaller. this ensures that the application
always has "close enough" to what it requested, and the threshold is
chosen heuristically to make sure "sane" amounts of TLS still end up
in the application-provided stack.
if TLS does not fit the above criteria, pthread_create uses mmap to
obtain space for TLS, but still uses the application-provided stack
for actual call frame stack. this is to avoid wasting memory, and for
the sake of supporting ugly hacks like garbage collection based on
assumptions that the implementation will use the provided stack range.
in order for the above heuristics to ever succeed, the amount of TLS
space wasted on POSIX TSD (pthread_key_create based) needed to be
reduced. otherwise, these changes would preclude any use of
pthread_create without mmap, which would have serious memory usage and
performance costs for applications trying to create huge numbers of
threads using pre-allocated stack space. the new value of
PTHREAD_KEYS_MAX is the minimum allowed by POSIX, 128. this should
still be plenty more than real-world applications need, especially now
that C11/gcc-style TLS is now supported in musl, and most apps and
libraries choose to use that instead of POSIX TSD when available.
at the same time, PTHREAD_STACK_MIN has been decreased. it was
originally set to PAGE_SIZE back when there was no support for TLS or
application-provided stacks, and requests smaller than a whole page
did not make sense. now, there are two good reasons to support
requests smaller than a page: (1) applications could provide
pre-allocated stacks smaller than a page, and (2) with smaller stack
sizes, stack+TLS+TSD can all fit in one page, making it possible for
applications which need huge numbers of threads with minimal stack
needs to allocate exactly one page per thread. the new value of
PTHREAD_STACK_MIN, 2k, is aligned with the minimum size for
sigaltstack.
2013-02-01 22:10:40 -05:00
|
|
|
attr._a_policy, &attr._a_prio);
|
2012-11-11 15:38:04 -05:00
|
|
|
a_store(new->startlock, ret<0 ? 2 : 0);
|
|
|
|
__wake(new->startlock, 1, 1);
|
|
|
|
if (ret < 0) return -ret;
|
|
|
|
}
|
|
|
|
|
2011-02-12 00:22:29 -05:00
|
|
|
*res = new;
|
|
|
|
return 0;
|
2013-02-01 22:25:19 -05:00
|
|
|
fail:
|
|
|
|
__release_ptc();
|
|
|
|
return EAGAIN;
|
2011-02-12 00:22:29 -05:00
|
|
|
}
|
2014-09-01 00:46:23 +02:00
|
|
|
|
|
|
|
weak_alias(__pthread_exit, pthread_exit);
|
|
|
|
weak_alias(__pthread_create, pthread_create);
|