about summary refs log tree commit diff
path: root/src/internal
Commit message (Collapse)AuthorAgeFilesLines
* simplify multi-threaded errno, eliminate useless function pointerRich Felker2011-08-061-2/+1
|
* use weak aliases rather than function pointers to simplify some codeRich Felker2011-08-061-2/+0
|
* overhaul rwlocks to address several issuesRich Felker2011-08-031-4/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | like mutexes and semaphores, rwlocks suffered from a race condition where the unlock operation could access the lock memory after another thread successfully obtained the lock (and possibly destroyed or unmapped the object). this has been fixed in the same way it was fixed for other lock types. in addition, the previous implementation favored writers over readers. in the absence of other considerations, that is the best behavior for rwlocks, and posix explicitly allows it. however posix also requires read locks to be recursive. if writers are favored, any attempt to obtain a read lock while a writer is waiting for the lock will fail, causing "recursive" read locks to deadlock. this can be avoided by keeping track of which threads already hold read locks, but doing so requires unbounded memory usage, and there must be a fallback case that favors readers in case memory allocation failed. and all of this must be synchronized. the cost, complexity, and risk of errors in getting it right is too great, so we simply favor readers. tracking of the owner of write locks has been removed, as it was not useful for anything. it could allow deadlock detection, but it's not clear to me that returning EDEADLK (which a buggy program is likely to ignore) is better than deadlocking; at least the latter behavior prevents further data corruption. a correct program cannot invoke this situation anyway. the reader count and write lock state, as well as the "last minute" waiter flag have all been combined into a single atomic lock. this means all state transitions for the lock are atomic compare-and-swap operations. this makes establishing correctness much easier and may improve performance. finally, some code duplication has been cleaned up. more is called for, especially the standard __timedwait idiom repeated in all locks.
* unify and overhaul timed futex waitsRich Felker2011-08-022-2/+4
| | | | | | | | | | | | | | new features: - FUTEX_WAIT_BITSET op will be used for timed waits if available. this saves a call to clock_gettime. - error checking for the timespec struct is now inside __timedwait so it doesn't need to be duplicated everywhere. cond_timedwait still needs to duplicate it to avoid unlocking the mutex, though. - pushing and popping the cancellation handler is delegated to __timedwait, and cancellable/non-cancellable waits are unified.
* add proper fuxed-based locking for stdioRich Felker2011-07-303-6/+8
| | | | | | | | | | | | | | | | | | | | | | 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.
* new attempt at making set*id() safe and robustRich Felker2011-07-292-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | changing credentials in a multi-threaded program is extremely difficult on linux because it requires synchronizing the change between all threads, which have their own thread-local credentials on the kernel side. this is further complicated by the fact that changing the real uid can fail due to exceeding RLIMIT_NPROC, making it possible that the syscall will succeed in some threads but fail in others. the old __rsyscall approach being replaced was robust in that it would report failure if any one thread failed, but in this case, the program would be left in an inconsistent state where individual threads might have different uid. (this was not as bad as glibc, which would sometimes even fail to report the failure entirely!) the new approach being committed refuses to change real user id when it cannot temporarily set the rlimit to infinity. this is completely POSIX conformant since POSIX does not require an implementation to allow real-user-id changes for non-privileged processes whatsoever. still, setting the real uid can fail due to memory allocation in the kernel, but this can only happen if there is not already a cached object for the target user. thus, we forcibly serialize the syscalls attempts, and fail the entire operation on the first failure. this *should* lead to an all-or-nothing success/failure result, but it's still fragile and highly dependent on kernel developers not breaking things worse than they're already broken. ideally linux will eventually add a CLONE_USERCRED flag that would give POSIX conformant credential changes without any hacks from userspace, and all of this code would become redundant and could be removed ~10 years down the line when everyone has abandoned the old broken kernels. i'm not holding my breath...
* comment non-obvious de bruijn sequence code in int parserRich Felker2011-07-251-0/+2
|
* fix various bugs in new integer parser frameworkRich Felker2011-07-141-4/+7
| | | | | | | | | | 1. my interpretation of subject sequence definition was wrong. adjust parser to conform to the standard. 2. some code for handling tail overflow case was missing (forgot to finish writing it). 3. typo (= instead of ==) caused ERANGE to wrongly behave like EINVAL
* new restartable integer parsing framework.Rich Felker2011-07-142-0/+116
| | | | | | | | | this fixes a number of bugs in integer parsing due to lazy haphazard wrapping, as well as some misinterpretations of the standard. the new parser is able to work character-at-a-time or on whole strings, making it easy to support the wide functions without unbounded space for conversion. it will also be possible to update scanf to use the new parser.
* restore use of .type in asm, but use modern @function (vs %function)Rich Felker2011-06-142-0/+2
| | | | | | | | this seems to be necessary to make the linker accept the functions in a shared library (perhaps to generate PLT entries?) strictly speaking libc-internal asm should not need it. i might clean that up later.
* fix race condition in pthread_killRich Felker2011-06-141-0/+1
| | | | | | | | | | | | | | if thread id was reused by the kernel between the time pthread_kill read it from the userspace pthread_t object and the time of the tgkill syscall, a signal could be sent to the wrong thread. the tgkill syscall was supposed to prevent this race (versus the old tkill syscall) but it can't; it can only help in the case where the tid is reused in a different process, but not when the tid is reused in the same process. the only solution i can see is an extra lock to prevent threads from exiting while another thread is trying to pthread_kill them. it should be very very cheap in the non-contended case.
* fix sigset macro for 64-bit systems (<< was overflowing due to wrong type)Rich Felker2011-06-131-1/+1
|
* remove all .size and .type directives for functions from the asmRich Felker2011-06-132-4/+0
| | | | | these are useless and have caused problems for users trying to build with non-gnu tools like tcc's assembler.
* implement uselocale function (minimal)Rich Felker2011-05-301-0/+2
|
* optimize compound-literal sigset_t's not to contain useless hurd bitsRich Felker2011-05-071-2/+4
|
* overhaul implementation-internal signal protectionsRich Felker2011-05-071-3/+6
| | | | | | | | | | | | | | | | | | | 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.
* completely new barrier implementation, addressing major correctness issuesRich Felker2011-05-061-4/+4
| | | | | | | | | | | | | | | | | | | | the previous implementation had at least 2 problems: 1. the case where additional threads reached the barrier before the first wave was finished leaving the barrier was untested and seemed not to be working. 2. threads leaving the barrier continued to access memory within the barrier object after other threads had successfully returned from pthread_barrier_wait. this could lead to memory corruption or crashes if the barrier object had automatic storage in one of the waiting threads and went out of scope before all threads finished returning, or if one thread unmapped the memory in which the barrier object lived. the new implementation avoids both problems by making the barrier state essentially local to the first thread which enters the barrier wait, and forces that thread to be the last to return.
* workaround for preprocessor bug in pccRich Felker2011-05-011-7/+7
| | | | | | | with this patch, musl compiles and mostly works with pcc 1.0.0. a few tests are still failing and i'm uncertain whether they are due to portability problems in musl, or bugs in pcc, but i suspect the latter.
* fix minor bugs due to incorrect threaded-predicate semanticsRich Felker2011-04-201-0/+1
| | | | | | | | | | | | some functions that should have been testing whether pthread_self() had been called and initialized the thread pointer were instead testing whether pthread_create() had been called and actually made the program "threaded". while it's unlikely any mismatch would occur in real-world problems, this could have introduced subtle bugs. now, we store the address of the main thread's thread descriptor in the libc structure and use its presence as a flag that the thread register is initialized. note that after fork, the calling thread (not necessarily the original main thread) is the new main thread.
* clean up handling of thread/nothread mode, lockingRich Felker2011-04-172-5/+4
|
* optimize cancellation enable/disable codeRich Felker2011-04-171-0/+1
| | | | | | | | | | | | | | | | | | the goal is to be able to use pthread_setcancelstate internally in the implementation, whenever a function might want to use functions which are cancellation points but avoid becoming a cancellation point itself. i could have just used a separate internal function for temporarily inhibiting cancellation, but the solution in this commit is better because (1) it's one less implementation-specific detail in functions that need to use it, and (2) application code can also get the same benefit. previously, pthread_setcancelstate dependend on pthread_self, which would pull in unwanted thread setup overhead for non-threaded programs. now, it temporarily stores the state in the global libc struct if threads have not been initialized, and later moves it if needed. this way we can instead use __pthread_self, which has no dependencies and assumes that the thread register is already valid.
* overhaul pthread cancellationRich Felker2011-04-173-8/+18
| | | | | | | | | | | | | | | | | | | | | | this patch improves the correctness, simplicity, and size of cancellation-related code. modulo any small errors, it should now be completely conformant, safe, and resource-leak free. the notion of entering and exiting cancellation-point context has been completely eliminated and replaced with alternative syscall assembly code for cancellable syscalls. the assembly is responsible for setting up execution context information (stack pointer and address of the syscall instruction) which the cancellation signal handler can use to determine whether the interrupted code was in a cancellable state. these changes eliminate race conditions in the previous generation of cancellation handling code (whereby a cancellation request received just prior to the syscall would not be processed, leaving the syscall to block, potentially indefinitely), and remedy an issue where non-cancellable syscalls made from signal handlers became cancellable if the signal handler interrupted a cancellation point. x86_64 asm is untested and may need a second try to get it right.
* use a separate signal from SIGCANCEL for SIGEV_THREAD timersRich Felker2011-04-141-0/+1
| | | | | | otherwise we cannot support an application's desire to use asynchronous cancellation within the callback function. this change also slightly debloats pthread_create.c.
* greatly improve SIGEV_THREAD timersRich Felker2011-04-091-0/+1
| | | | | calling pthread_exit from, or pthread_cancel on, the timer callback thread will no longer destroy the timer.
* move rsyscall out of pthread_create moduleRich Felker2011-04-062-1/+5
| | | | | | | | | | | | | | this is something of a tradeoff, as now set*id() functions, rather than pthread_create, are what pull in the code overhead for dealing with linux's refusal to implement proper POSIX thread-vs-process semantics. my motivations are: 1. it's cleaner this way, especially cleaner to optimize out the rsyscall locking overhead from pthread_create when it's not needed. 2. it's expected that only a tiny number of core system programs will ever use set*id() functions, whereas many programs may want to use threads, and making thread overhead tiny is an incentive for "light" programs to try threads.
* new framework to inhibit thread cancellation when neededRich Felker2011-04-051-0/+2
| | | | | | | with these small changes, libc functions which need to call functions which are cancellation points, but which themselves must not be cancellation points, can use the CANCELPT_INHIBIT and CANCELPT_RESUME macros to temporarily inhibit all cancellation.
* simplify calling of timer signal handlerRich Felker2011-04-031-2/+1
|
* simplify pthread tsd key handlingRich Felker2011-04-031-2/+1
|
* reorganize the __libc structure for threaded performance issuesRich Felker2011-04-011-6/+6
| | | | | | | we want to keep atomically updated fields (locks and thread count) and really anything writable far away from frequently-needed function pointers. stuff some rarely-needed function pointers in between to pad, hopefully up to a cache line boundary.
* optimize timer creation and possibly protect against some minor racesRich Felker2011-03-301-2/+0
| | | | | | | | | the major idea of this patch is not to depend on having the timer pointer delivered to the signal handler, and instead use the thread pointer to get the callback function address and argument. this way, the parent thread can make the timer_create syscall while the child thread is starting, and it should never have to block waiting for the barrier.
* major improvements to cancellation handlingRich Felker2011-03-292-2/+6
| | | | | | | | | | | | | - there is no longer any risk of spoofing cancellation requests, since the cancel flag is set in pthread_cancel rather than in the signal handler. - cancellation signal is no longer unblocked when running the cancellation handlers. instead, pthread_create will cause any new threads created from a cancellation handler to unblock their own cancellation signal. - various tweaks in preparation for POSIX timer support.
* some preliminaries for adding POSIX timersRich Felker2011-03-291-0/+4
|
* remove useless field in pthread struct (wasted a good bit of space)Rich Felker2011-03-281-1/+0
|
* major stdio overhaul, using readv/writev, plus other changesRich Felker2011-03-281-12/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | the biggest change in this commit is that stdio now uses readv to fill the caller's buffer and the FILE buffer with a single syscall, and likewise writev to flush the FILE buffer and write out the caller's buffer in a single syscall. making this change required fundamental architectural changes to stdio, so i also made a number of other improvements in the process: - the implementation no longer assumes that further io will fail following errors, and no longer blocks io when the error flag is set (though the latter could easily be changed back if desired) - unbuffered mode is no longer implemented as a one-byte buffer. as a consequence, scanf unreading has to use ungetc, to the unget buffer has been enlarged to hold at least 2 wide characters. - the FILE structure has been rearranged to maintain the locations of the fields that might be used in glibc getc/putc type macros, while shrinking the structure to save some space. - error cases for fflush, fseek, etc. should be more correct. - library-internal macros are used for getc_unlocked and putc_unlocked now, eliminating some ugly code duplication. __uflow and __overflow are no longer used anywhere but these macros. switch to read or write mode is also separated so the code can be better shared, e.g. with ungetc. - lots of other small things.
* simplify and optimize FILE lock handlingRich Felker2011-03-241-3/+2
|
* overhaul cancellation to fix resource leaks and dangerous behavior with signalsRich Felker2011-03-241-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | this commit addresses two issues: 1. a race condition, whereby a cancellation request occurring after a syscall returned from kernelspace but before the subsequent CANCELPT_END would cause cancellable resource-allocating syscalls (like open) to leak resources. 2. signal handlers invoked while the thread was blocked at a cancellation point behaved as if asynchronous cancellation mode wer in effect, resulting in potentially dangerous state corruption if a cancellation request occurs. the glibc/nptl implementation of threads shares both of these issues. with this commit, both are fixed. however, cancellation points encountered in a signal handler will not be acted upon if the signal was received while the thread was already at a cancellation point. they will of course be acted upon after the signal handler returns, so in real-world usage where signal handlers quickly return, it should not be a problem. it's possible to solve this problem too by having sigaction() wrap all signal handlers with a function that uses a pthread_cleanup handler to catch cancellation, patch up the saved context, and return into the cancellable function that will catch and act upon the cancellation. however that would be a lot of complexity for minimal if any benefit...
* global cleanup to use the new syscall interfaceRich Felker2011-03-201-22/+0
|
* syscall overhaul part two - unify public and internal syscall interfaceRich Felker2011-03-191-0/+32
| | | | | | | | | | | | | | | | with this patch, the syscallN() functions are no longer needed; a variadic syscall() macro allows syscalls with anywhere from 0 to 6 arguments to be made with a single macro name. also, manually casting each non-integer argument with (long) is no longer necessary; the casts are hidden in the macros. some source files which depended on being able to define the old macro SYSCALL_RETURNS_ERRNO have been modified to directly use __syscall() instead of syscall(). references to SYSCALL_SIGSET_SIZE and SYSCALL_LL have also been changed. x86_64 has not been tested, and may need a follow-up commit to fix any minor bugs/oversights.
* remove comment cruft that got left behind in x86_64 syscall.sRich Felker2011-03-191-1/+0
|
* overhaul syscall interfaceRich Felker2011-03-194-11/+46
| | | | | | | | | | | | | | | this commit shuffles around the location of syscall definitions so that we can make a syscall() library function with both SYS_* and __NR_* style syscall names available to user applications, provides the syscall() library function, and optimizes the code that performs the actual inline syscalls in the library itself. previously on i386 when built as PIC (shared library), syscalls were incurring bus lock (lock prefix) overhead at entry and exit, due to the way the ebx register was being loaded (xchg instruction with a memory operand). now the xchg takes place between two registers. further cleanup to arch/$(ARCH)/syscall.h is planned.
* implement [v]swprintfRich Felker2011-03-181-1/+1
|
* implement robust mutexesRich Felker2011-03-171-0/+5
| | | | | | some of this code should be cleaned up, e.g. using macros for some of the bit flags, masks, etc. nonetheless, the code is believed to be working and correct at this point.
* reorder mutex struct fields to make room for pointers (upcoming robust mutexes)Rich Felker2011-03-171-1/+3
| | | | | | the layout has been chosen so that pointer slots 3 and 4 fit between the integer slots on 32-bit archs, and come after the integer slots on 64-bit archs.
* unify lock and owner fields of mutex structureRich Felker2011-03-171-1/+0
| | | | | | this change is necessary to free up one slot in the mutex structure so that we can use doubly-linked lists in the implementation of robust mutexes.
* implement flockfile api, rework stdio lockingRich Felker2011-03-122-12/+11
|
* optimize pthread termination in the non-detached caseRich Felker2011-03-101-0/+1
| | | | | | | we can avoid blocking signals by simply using a flag to mark that the thread has exited and prevent it from getting counted in the rsyscall signal-pingpong. this restores the original pthread create/join throughput from before the sigprocmask call was added.
* fix and optimize non-default-type mutex behaviorRich Felker2011-03-081-0/+1
| | | | | | | | | problem 1: mutex type from the attribute was being ignored by pthread_mutex_init, so recursive/errorchecking mutexes were never being used at all. problem 2: ownership of recursive mutexes was not being enforced at unlock time.
* use the selected clock from the condattr for pthread_cond_timedwaitRich Felker2011-03-071-0/+1
|
* various changes in preparation for dynamic linking supportRich Felker2011-02-242-5/+13
| | | | | | | | | | | | | | | | | prefer using visibility=hidden for __libc internal data, rather than an accessor function, if the compiler has visibility. optimize with -O3 for PIC targets (shared library). without heavy inlining, reloading the GOT register in small functions kills performance. 20-30% size increase for a single libc.so is not a big deal, compared to comparaible size increase in every static binaries. use -Bsymbolic-functions, not -Bsymbolic. global variables are subject to COPY relocations, and thus binding their addresses in the library at link time will cause library functions to read the wrong (original) copies instead of the copies made in the main program's bss section. add entry point, _start, for dynamic linker.
* use an accessor function for __libc data pointer when compiled as PICRich Felker2011-02-202-4/+19
| | | | | | | | | | | | | | prior to this change, a large portion of libc was unusable prior to relocation by the dynamic linker, due to dependence on the global data in the __libc structure and the need to obtain its address through the GOT. with this patch, the accessor function __libc_loc is now able to obtain the address of __libc via PC-relative addressing without using the GOT. this means the majority of libc functionality is now accessible right away. naturally, the above statements all depend on having an architecture where PC-relative addressing and jumps/calls are feasible, and a compiler that generates the appropriate code.