about summary refs log tree commit diff
path: root/sysdeps/nptl/pthread.h
Commit message (Collapse)AuthorAgeFilesLines
* Update copyright dates with scripts/update-copyrights.Joseph Myers2017-01-011-1/+1
|
* New condvar implementation that provides stronger ordering guarantees.Torvald Riegel2016-12-311-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a new implementation for condition variables, required after http://austingroupbugs.net/view.php?id=609 to fix bug 13165. In essence, we need to be stricter in which waiters a signal or broadcast is required to wake up; this couldn't be solved using the old algorithm. ISO C++ made a similar clarification, so this also fixes a bug in current libstdc++, for example. We can't use the old algorithm anymore because futexes do not guarantee to wake in FIFO order. Thus, when we wake, we can't simply let any waiter grab a signal, but we need to ensure that one of the waiters happening before the signal is woken up. This is something the previous algorithm violated (see bug 13165). There's another issue specific to condvars: ABA issues on the underlying futexes. Unlike mutexes that have just three states, or semaphores that have no tokens or a limited number of them, the state of a condvar is the *order* of the waiters. A waiter on a semaphore can grab a token whenever one is available; a condvar waiter must only consume a signal if it is eligible to do so as determined by the relative order of the waiter and the signal. Therefore, this new algorithm maintains two groups of waiters: Those eligible to consume signals (G1), and those that have to wait until previous waiters have consumed signals (G2). Once G1 is empty, G2 becomes the new G1. 64b counters are used to avoid ABA issues. This condvar doesn't yet use a requeue optimization (ie, on a broadcast, waking just one thread and requeueing all others on the futex of the mutex supplied by the program). I don't think doing the requeue is necessarily the right approach (but I haven't done real measurements yet): * If a program expects to wake many threads at the same time and make that scalable, a condvar isn't great anyway because of how it requires waiters to operate mutually exclusive (due to the mutex usage). Thus, a thundering herd problem is a scalability problem with or without the optimization. Using something like a semaphore might be more appropriate in such a case. * The scalability problem is actually at the mutex side; the condvar could help (and it tries to with the requeue optimization), but it should be the mutex who decides how that is done, and whether it is done at all. * Forcing all but one waiter into the kernel-side wait queue of the mutex prevents/avoids the use of lock elision on the mutex. Thus, it prevents the only cure against the underlying scalability problem inherent to condvars. * If condvars use short critical sections (ie, hold the mutex just to check a binary flag or such), which they should do ideally, then forcing all those waiter to proceed serially with kernel-based hand-off (ie, futex ops in the mutex' contended state, via the futex wait queues) will be less efficient than just letting a scalable mutex implementation take care of it. Our current mutex impl doesn't employ spinning at all, but if critical sections are short, spinning can be much better. * Doing the requeue stuff requires all waiters to always drive the mutex into the contended state. This leads to each waiter having to call futex_wake after lock release, even if this wouldn't be necessary. [BZ #13165] * nptl/pthread_cond_broadcast.c (__pthread_cond_broadcast): Rewrite to use new algorithm. * nptl/pthread_cond_destroy.c (__pthread_cond_destroy): Likewise. * nptl/pthread_cond_init.c (__pthread_cond_init): Likewise. * nptl/pthread_cond_signal.c (__pthread_cond_signal): Likewise. * nptl/pthread_cond_wait.c (__pthread_cond_wait): Likewise. (__pthread_cond_timedwait): Move here from pthread_cond_timedwait.c. (__condvar_confirm_wakeup, __condvar_cancel_waiting, __condvar_cleanup_waiting, __condvar_dec_grefs, __pthread_cond_wait_common): New. (__condvar_cleanup): Remove. * npt/pthread_condattr_getclock.c (pthread_condattr_getclock): Adapt. * npt/pthread_condattr_setclock.c (pthread_condattr_setclock): Likewise. * npt/pthread_condattr_getpshared.c (pthread_condattr_getpshared): Likewise. * npt/pthread_condattr_init.c (pthread_condattr_init): Likewise. * nptl/tst-cond1.c: Add comment. * nptl/tst-cond20.c (do_test): Adapt. * nptl/tst-cond22.c (do_test): Likewise. * sysdeps/aarch64/nptl/bits/pthreadtypes.h (pthread_cond_t): Adapt structure. * sysdeps/arm/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/ia64/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/m68k/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/microblaze/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/mips/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/nios2/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/s390/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/sh/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/tile/nptl/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/x86/bits/pthreadtypes.h (pthread_cond_t): Likewise. * sysdeps/nptl/internaltypes.h (COND_NWAITERS_SHIFT): Remove. (COND_CLOCK_BITS): Adapt. * sysdeps/nptl/pthread.h (PTHREAD_COND_INITIALIZER): Adapt. * nptl/pthreadP.h (__PTHREAD_COND_CLOCK_MONOTONIC_MASK, __PTHREAD_COND_SHARED_MASK): New. * nptl/nptl-printers.py (CLOCK_IDS): Remove. (ConditionVariablePrinter, ConditionVariableAttributesPrinter): Adapt. * nptl/nptl_lock_constants.pysym: Adapt. * nptl/test-cond-printers.py: Adapt. * sysdeps/unix/sysv/linux/hppa/internaltypes.h (cond_compat_clear, cond_compat_check_and_clear): Adapt. * sysdeps/unix/sysv/linux/hppa/pthread_cond_timedwait.c: Remove file ... * sysdeps/unix/sysv/linux/hppa/pthread_cond_wait.c (__pthread_cond_timedwait): ... and move here. * nptl/DESIGN-condvar.txt: Remove file. * nptl/lowlevelcond.sym: Likewise. * nptl/pthread_cond_timedwait.c: Likewise. * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: Likewise. * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: Likewise. * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: Likewise. * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: Likewise. * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: Likewise. * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: Likewise. * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: Likewise. * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise.
* Installed-header hygiene (BZ#20366): time.h types.Zack Weinberg2016-09-231-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Many headers are expected to expose a subset of the type definitions in time.h. time.h has a whole bunch of messy logic for conditionally defining some its types and structs, but, as best I can tell, this has never worked 100%. In particular, __need_timespec is ineffective if _TIME_H has already been defined, which means that if you compile #include <time.h> #include <sched.h> with e.g. -fsyntax-only -std=c89 -Wall -Wsystem-headers, you will get In file included from test.c:2:0: /usr/include/sched.h:74:57: warning: "struct timespec" declared inside parameter list will not be visible outside of this definition or declaration extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW; ^~~~~~~~ And if you want to _use_ sched_rr_get_interval in a TU compiled that way, you're hosed. This patch replaces all of that with small bits/types/TYPE.h headers as introduced earlier. time.h and bits/time.h are now *much* simpler, and a lot of other headers are slightly simpler. * time/time.h, bits/time.h, sysdeps/unix/sysv/linux/bits/time.h: Remove all logic conditional on __need macros. Move all the conditionally defined types to their own headers... * time/bits/types/clock_t.h: Define clock_t here. * time/bits/types/clockid_t.h: Define clockid_t here. * time/bits/types/struct_itimerspec.h: Define struct itimerspec here. * time/bits/types/struct_timespec.h: Define struct timespec here. * time/bits/types/struct_timeval.h: Define struct timeval here. * time/bits/types/struct_tm.h: Define struct tm here. * time/bits/types/time_t.h: Define time_t here. * time/bits/types/timer_t.h: Define timer_t here. * time/Makefile: Install the new headers. * bits/resource.h, io/fcntl.h, io/sys/poll.h, io/sys/stat.h * io/utime.h, misc/sys/select.h, posix/sched.h, posix/sys/times.h * posix/sys/types.h, resolv/netdb.h, rt/aio.h, rt/mqueue.h * signal/signal.h, pthread/semaphore.h, sysdeps/nptl/pthread.h * sysdeps/unix/sysv/linux/alpha/bits/resource.h * sysdeps/unix/sysv/linux/alpha/sys/acct.h * sysdeps/unix/sysv/linux/bits/resource.h * sysdeps/unix/sysv/linux/bits/timex.h * sysdeps/unix/sysv/linux/mips/bits/resource.h * sysdeps/unix/sysv/linux/net/ppp_defs.h * sysdeps/unix/sysv/linux/sparc/bits/resource.h * sysdeps/unix/sysv/linux/sys/acct.h * sysdeps/unix/sysv/linux/sys/timerfd.h * sysvipc/sys/msg.h, sysvipc/sys/sem.h, sysvipc/sys/shm.h * time/sys/time.h, time/sys/timeb.h Use the new bits/types headers. * include/time.h: Remove __need logic. * include/bits/time.h * include/bits/types/clock_t.h, include/bits/types/clockid_t.h * include/bits/types/time_t.h, include/bits/types/timer_t.h * include/bits/types/struct_itimerspec.h * include/bits/types/struct_timespec.h * include/bits/types/struct_timeval.h * include/bits/types/struct_tm.h: New wrapper headers.
* Update copyright dates with scripts/update-copyrights.Joseph Myers2016-01-041-1/+1
|
* NPTL: Remove duplicate definition of PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NPMartin Galvan2015-03-281-2/+0
| | | | | The PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP macro was defined twice with the same values in pthread.h; this removes the second definition.
* Update copyright dates with scripts/update-copyrights.Joseph Myers2015-01-021-1/+1
|
* Add adaptive elision to rwlocksAndi Kleen2014-06-131-3/+3
| | | | | | | | | | | | | | | | | | | This patch relies on the C version of the rwlocks posted earlier. With C rwlocks it is very straight forward to do adaptive elision using TSX. It is based on the infrastructure added earlier for mutexes, but uses its own elision macros. The macros are fairly general purpose and could be used for other elision purposes too. This version is much cleaner than the earlier assembler based version, and in particular implements adaptation which makes it safer. I changed the behavior slightly to not require any changes in the test suite and fully conform to all expected behaviors (generally at the cost of not eliding in various situations). In particular this means the timedlock variants are not elided. Nested trylock aborts.
* Get rid of nptl/sysdeps/pthread/ subdirectoryRoland McGrath2014-06-121-0/+1163