summaryrefslogtreecommitdiff
path: root/src/thread/pthread_key_create.c
AgeCommit message (Collapse)AuthorLines
2019-03-21fix data race choosing next key slot in pthread_key_createRich Felker-1/+1
commit 84d061d5a31c9c773e29e1e2b1ffe8cb9557bc58 wrongly moved the access to the global next_key outside of the scope of the lock. the error manifested as spurious failure to find an available key slot under concurrent calls to pthread_key_create, since the stopping condition could be met after only a small number of slots were examined.
2019-02-17fix data race between new pthread_key_delete and dtor executionRich Felker-2/+4
access to clear the entry in each thread's tsd array for the key being deleted was not synchronized with __pthread_tsd_run_dtors. I probably made this mistake from a mistaken belief that the thread list lock was held during the latter, which of course is not possible since it executes application code in a still-live-thread context. while we're at it, expand the interval during which signals are blocked to cover taking the write lock on key_lock, so that a signal at an inopportune time doesn't block forward progress of readers.
2019-02-16introduce namespace-safe rwlock aliases; use in pthread_key_createRich Felker-9/+9
commit 84d061d5a31c9c773e29e1e2b1ffe8cb9557bc58 inadvertently introduced namespace violations by using the pthread-namespace rwlock functions in pthread_key_create, which is in turn used for C11 tss. fix that and possible future uses of rwlocks elsewhere.
2019-02-16rewrite pthread_key_delete to use global thread listRich Felker-61/+19
with the availability of the thread list, there is no need to mark tsd key slots dirty and clean them up only when a free slot can't be found. instead, directly iterate threads and clear any value associated with the key being deleted. no synchronization is necessary for the clearing, since there is no way the slot can be accessed without having synchronized with the creation of a new key occupying the same slot, which is already sequenced after and synchronized with the deletion of the old key.
2019-01-16fix unintended linking dependency of pthread_key_create on __synccallRich Felker-0/+6
commit 84d061d5a31c9c773e29e1e2b1ffe8cb9557bc58 attempted to do this already, but omitted from pthread_key_create.c the weak definition of __pthread_key_delete_synccall, so that the definition provided by pthread_key_delete.c was always pulled in. based on patch by Markus Wichmann, but with a weak alias rather than weak reference for consistency/policy about dependence on tooling features.
2018-09-18fix deletion of pthread tsd keys that still have non-null values storedRich Felker-18/+87
per POSIX, deletion of a key for which some threads still have values stored is permitted, and newly created keys must initially hold the null value in all threads. these properties were not met by our implementation; if a key was deleted with values left and a new key was created in the same slot, the old values were still visible. moreover, due to lack of any synchronization in pthread_key_delete, there was a TOCTOU race whereby a concurrent pthread_exit could attempt to call a null destructor pointer for the newly orphaned value. this commit introduces a solution based on __synccall, stopping the world to zero out the values for deleted keys, but only does so lazily when all key slots have been exhausted. pthread_key_delete is split off into a separate translation unit so that static-linked programs which only create keys but never delete them will not pull in the __synccall machinery. a global rwlock is added to synchronize creation and deletion of keys with dtor execution. since the dtor execution loop now has to release and retake the lock around its call to each dtor, checks are made not to call the nodtor dummy function for keys which lack a dtor.
2015-04-13remove remnants of support for running in no-thread-pointer modeRich Felker-6/+4
since 1.1.0, musl has nominally required a thread pointer to be setup. most of the remaining code that was checking for its availability was doing so for the sake of being usable by the dynamic linker. as of commit 71f099cb7db821c51d8f39dfac622c61e54d794c, this is no longer necessary; the thread pointer is now valid before any libc code (outside of dynamic linker bootstrap functions) runs. this commit essentially concludes "phase 3" of the "transition path for removing lazy init of thread pointer" project that began during the 1.1.0 release cycle.
2015-03-03make all objects used with atomic operations volatileRich Felker-1/+1
the memory model we use internally for atomics permits plain loads of values which may be subject to concurrent modification without requiring that a special load function be used. since a compiler is free to make transformations that alter the number of loads or the way in which loads are performed, the compiler is theoretically free to break this usage. the most obvious concern is with atomic cas constructs: something of the form tmp=*p;a_cas(p,tmp,f(tmp)); could be transformed to a_cas(p,*p,f(*p)); where the latter is intended to show multiple loads of *p whose resulting values might fail to be equal; this would break the atomicity of the whole operation. but even more fundamental breakage is possible. with the changes being made now, objects that may be modified by atomics are modeled as volatile, and the atomic operations performed on them by other threads are modeled as asynchronous stores by hardware which happens to be acting on the request of another thread. such modeling of course does not itself address memory synchronization between cores/cpus, but that aspect was already handled. this all seems less than ideal, but it's the best we can do without mandating a C11 compiler and using the C11 model for atomics. in the case of pthread_once_t, the ABI type of the underlying object is not volatile-qualified. so we are assuming that accessing the object through a volatile-qualified lvalue via casts yields volatile access semantics. the language of the C standard is somewhat unclear on this matter, but this is an assumption the linux kernel also makes, and seems to be the correct interpretation of the standard.
2014-09-06use weak symbols for the POSIX functions that will be used by C threadsJens Gustedt-2/+5
The intent of this is to avoid name space pollution of the C threads implementation. This has two sides to it. First we have to provide symbols that wouldn't pollute the name space for the C threads implementation. Second we have to clean up some internal uses of POSIX functions such that they don't implicitly drag in such symbols.
2014-07-16work around constant folding bug 61144 in gcc 4.9.0 and 4.9.1Rich Felker-1/+1
previously we detected this bug in configure and issued advice for a workaround, but this turned out not to work. since then gcc 4.9.0 has appeared in several distributions, and now 4.9.1 has been released without a fix despite this being a wrong code generation bug which is supposed to be a release-blocker, per gcc policy. since the scope of the bug seems to affect only data objects (rather than functions) whose definitions are overridable, and there are only a very small number of these in musl, I am just changing them from const to volatile for the time being. simply removing the const would be sufficient to make gcc 4.9.1 work (the non-const case was inadvertently fixed as part of another change in gcc), and this would also be sufficient with 4.9.0 if we forced -O0 on the affected files or on the whole build. however it's cleaner to just remove all the broken compiler detection and use volatile, which will ensure that they are never constant-folded. the quality of a non-broken compiler's output should not be affected except for the fact that these objects are no longer const and thus possibly add a few bytes to data/bss. this change can be reconsidered and possibly reverted at some point in the future when the broken gcc versions are no longer relevant.
2014-03-24always initialize thread pointer at program startRich Felker-1/+7
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.
2013-10-04fix invalid implicit pointer conversion in pthread_key_createRich Felker-1/+1
2011-07-30add proper fuxed-based locking for stdioRich Felker-1/+1
previously, stdio used spinlocks, which would be unacceptable if we ever add support for thread priorities, and which yielded pathologically bad performance if an application attempted to use flockfile on a key file as a major/primary locking mechanism. i had held off on making this change for fear that it would hurt performance in the non-threaded case, but actually support for recursive locking had already inflicted that cost. by having the internal locking functions store a flag indicating whether they need to perform unlocking, rather than using the actual recursive lock counter, i was able to combine the conditionals at unlock time, eliminating any additional cost, and also avoid a nasty corner case where a huge number of calls to ftrylockfile could cause deadlock later at the point of internal locking. this commit also fixes some issues with usage of pthread_self conflicting with __attribute__((const)) which resulted in crashes with some compiler versions/optimizations, mainly in flockfile prior to pthread_create.
2011-04-19move some more code out of pthread_create.cRich Felker-1/+2
this also de-uglifies the dummy function aliasing a bit.
2011-04-03simplify pthread tsd key handlingRich Felker-1/+6
2011-04-03omit pthread tsd dtor code if tsd is not usedRich Felker-1/+18
2011-04-01use bss instead of mmap for main thread's pthread thread-specific dataRich Felker-0/+1
this simplifies code and removes a failure case
2011-03-31greatly simplify pthread_key_create (~20% size reduction)Rich Felker-10/+9
2011-03-03optimize POSIX TSD for fast pthread_getspecificRich Felker-0/+1
2011-02-12initial check-in, version 0.5.0v0.5.0Rich Felker-0/+25