- Update some comments and fix minor bugs. Minor cosmetic changes.
- Replace some spinlocks with mutexes and rwlocks.
- Change the process private semaphores to use mutexes and condition
variables instead of doing the synchronization directly. Spinlocks
are no longer used by the semaphore code.
Instead, make the deferred wakeup list a per-thread array and pass down
the lwpid_t's that way.
- In pthread_cond_wait(), take the mutex before dealing with early wakeup.
In this way there should never be contention on the CV's spinlock if
the app follows POSIX rules (there should only be contention on the
user-provided mutex).
- Add a port of the kernel's rwlocks. The rwlock's spinlock is only taken if
there is contention. This is enabled where atomic ops are available. Right
now that is only i386 and amd64 because I don't have other hardware to
test with. It's trivial to add stubs for other architectures as long as
they have compare-and-swap. When we have proper atomic ops the old rwlock
code can be removed.
- Add a new mutex implementation that's similar to the kernel's mutexes, but
uses compare-and-swap to maintain the waiters list, so no spinlocks are
involved. Same caveats apply as for the rwlocks.
yielding. This is a nasty band-aid but with many threads, looping over
sched_yield() wastes a huge amount of CPU time. It would be nice to have a
way to temporarily disable preemption, but it turns out that's yet another
no-brain concept that has been patented and the patent holder seems to be
suing people lately. Another alternative is probably to have kernel-assisted
spinlocks.
Chops another ~10% off create/join in a loop on i386.
- Disable low level debugging as this is stable. Improves benchmarks
across the board by a small percentage. Uncontested mutex acquire
and release in a loop becomes about 8% quicker.
- Minor cleanup.
hint pointer, but do so in a way that remains compatible with older
pthread libraries. This can be used to wake another thread before the
calling thread goes asleep, saving at least one syscall + involuntary
context switch. This turns out to be a fairly large win on the condvar
benchmarks that I have tried.
detach/join.
- Make mutex acquire spin for a short time, as done with spinlocks.
- Make the number of spins controllable with the env var PTHREAD_NSPINS.
- Reduce the amount of time that libpthread internal spinlocks are held.
- Rely more on the barrier effects of park/unpark to avoid taking spinlocks.
- Simplify the locking around pthreads and the global queues.
- Align per-thread sync data on a 128 byte boundary.
- Offset thread stacks by a small amount to try and reduce cache thrash.
After resuming execution, the thread must check to see if it
has been restarted as a result of pthread_cond_signal(). If it
has, but cannot take the wakeup (because of eg a pending Unix
signal or timeout) then try to ensure that another thread sees
it. This is necessary because there may be multiple waiters,
and at least one should take the wakeup if possible.
so avoid making them.
- When parking an LWP on a condition variable, point the hint argument at
the mutex's waiters queue. Chances are we will be awoken from that later.
the mutex that the waiters are using to synchronise, then transfer them
to the mutex's waiters list so that the wakeup is deferred until release
of the mutex. Improves the timings for CV sleep/wakeup by between 30-100%
in tests conducted locally on a UP system. There can be a penalty for MP
systems when only one thread is being awoken, but in practice I think it
won't be be an issue.
- pthread_signal: search for a thread that does not have a pending wakeup.
Threads can have a pending wakeup and still be on the waiters list if we
clash with an earlier pthread_cond_broadcast().
be used only as as a hint. Clear the pointer when releasing the mutex.
- When releasing a mutex, wake all waiters. Makes it possible to tranfer
waiters from another object to a mutex.
mutex thread, thus leaving a thread sleeping on an unlocked mutex.
Reviewed by myself and Christos.
Problem reported by Arne H. Juul, arnej at pvv dot ntnu dot no,
in PR 26208. This fix represents option 1 presented in the PR.
forget to clear it out of pt_siglist, otherwise we will keep getting
it over and over again. fixes a problem introduced in rev 1.43.
problem observed with mysqld where sending it a SIGHUP after it has
set an alarm (e.g. due to some package like rt3 using it) caused the
signal handler thread to go into a tight loop (collecting a SIGALRM
[via sigwait() in mysqld.cc] that would not go away due to the above
issue). mysqld appears to get a SIGHUP when /etc/rc exits, so it
can go into this tight loop after a reboot (but not if you restart
it by hand). the bad sequence is:
/etc/rc runs:
- starts mysqld
- starts web server with rt3 fastcgi starts
- fastcgi/rt3 talks to mysqld (causing it to set an alarm)
- /etc/rc exits, SIGHUP goes to mysqld
- mysqld catches SIGHUP, signal handler thread gets
stuck in loop (database continues to operate, slowly).
you can also trigger the problem by sending mysqld a SIGHUP by hand after
you've caused it to set an alarm by connecting to it.
the process' signal mask -- this ends up in a no-op.
Use the system call directly instead.
(This might be done in pthread_sig.c, but for now I wanted a simple
patch which is easily tested and pulled up.)
so that the main thread is not different from others.
as a side effect, fix memory leak in pthread_create on error.
- make pthread__stackid_setup return a error rather than calling err(2).
locations:
- Don't declare pthread__switch_away global
- Do the PIC dance for pthread__switch_return_point and
pthread__locked_switch. Ideally these (and other) symbols would
be hidden.
Thanks to uwe@, dyoung@ and elad@ for help.
XXX sh3 is still to be done.
XXX vax does strange things.