of an alternate signal stack for handling signals. Let the kernel
send signals on the stack of the current thread and teach the threads
signal handler how to deliver signals to the current thread if it
needs to. Also, always store a threads context as a jmp_buf. Eventually
this will change to be a ucontext_t or mcontext_t.
Other small nits. Use struct pthread * instead of pthread_t in internal
library routines. The threads code wants struct pthread *, and pthread_t
doesn't necessarily have to be the same.
Reviewed by: jasone
return address when modifying a jmp_buf to create a new thread context.
Also set t12 with the return address.
This should fix libc_r on alpha.
With much detective work by: Bernd Walter <ticso@cicely.de>
kernel #defines to figure out where the stack is located. This stops
libc_r from exploding when the kernel is compiled with a different
KVM size. IMHO this is all kinda bogus, it would be better to just
check %esp and work from that.
- uthread_signal.c; libc_r does not wrap signal() since 1998/04/29.
- uthread_attr_setprio.c; it was never connected to the build, and
pthread_attr_setprio() does not exist in POSIX.
- uthread_sigblock.c and uthread_sigsetmask.c; these were no-ops
bloating libc_r's space.
pthread_private.h:
- Removed prototypes of non-syscalls: send().
- Removed prototypes of unused syscalls: sigpending(), sigsuspend(),
and select().
- Fixed prototype of fork().
- MFS: Fixed prototypes of <sys/socket.h> syscalls.
Reviewed by: deischen
Approved by: deischen, jasone
be malloc()ed, but they are now allocated using mmap(), just as the
default-size stacks are. A separate cache of stacks is kept for
non-default-size stacks.
Collaboration with: deischen
atomically:
1) Search _thread_list for the thread to join.
2) Search _dead_list for the thread to join.
3) Set the running thread as the joiner.
While we're at it, fix a race in the case where multiple threads try to
join on the same thread. POSIX says that the behavior of multiple joiners
is undefined, but the fix is cheap as a result of the other fix.
keep track of a joiner. POSIX only supports a single joiner, so this
simplification is acceptable.
At the same time, make sure to mark a joined thread as detached so that
its resources can be freed.
Reviewed by: deischen
PR: 24345
application to provide locking for I/O operations. This doesn't
break any of my tests, but the old behavior can be restored by
compiling with _FDLOCKS_ENABLED. This will eventually be removed
when it is obvious it does not cause any problems.
Remove most of flockfile implementation, with the exception of
flockfile_debug.
Make error messages more informational (submitted by Mike Heffner
<spock@techfour.net>, who's now known as mikeh@FreeBSD.org).
Add another check for thread library initialization (jdp, we
really need a way to get _thread_init called at program start
before any constructors are run).
_foo - wrapped system call
foo - weak definition to _foo
and for cancellation points:
_foo - wrapped system call
__foo - enter cancellation point, call _foo(), leave
cancellation point
foo - weak definition to __foo
Change use of global _thread_run to call a function to get the
currently running thread.
Make all pthread_foo functions weak definitions to _pthread_foo,
where _pthread_foo is the implementation. This allows an application
to provide its own pthread functions.
Provide slightly different versions of pthread_mutex_lock and
pthread_mutex_init so that we can tell the difference between
a libc mutex and an application mutex. Threads holding mutexes
internal to libc should never be allowed to exit, call signal
handlers, or cancel.
Approved by: -arch
the kernel to (re)use the alternate signal stack. In this
case, we don't return normally from the signal handler,
so the kernel still thinks we are using the signal stack.
The fixes a nasty bug where the signal handler can start
fiddling with the stack of a thread while the handler is
actually running on the same stack.
MFC candidate
file descriptors needing to be polled (Doh!). Reported
by Dan Nelson <dnelson@emsphone.com>.
Don't install and start the scheduling timer until the
first thread is created. This prevents the overhead of
having a periodic scheduling signal in a single threaded
program. Reported by Dan Nelson <dnelson@emsphone.com>.
Allow builtin longjmps out of application installed
signal handlers without the need perform any post-handler
cleanup:
o Change signal handling to save the threads interrupted
context on the stack. The threads current context is
now always stored in the same place (in the pthread).
If and when a signal handler returns, the interrupted
context is copied back to the storage area in the pthread.
o Before calling invoking a signal handler for a thread,
back the thread out of any internal waiting queues
(mutex, CV, join, etc) to which it belongs.
Rework uthread_info.c a bit to make it easier to change
the format of a thread dump.
Use an alternal signal stack for the thread library's
signal handler. This allows us to fiddle with the main
threads stack without fear of it being in use.
Reviewed by: jasone
thread switches should be on par with that under scheduler
activations.
o Timing is achieved through the use of a fixed interval
timer (ITIMER_PROF) to count scheduling ticks instead
of retrieving the time-of-day upon every thread switch
and calculating elapsed real time.
o Polling for I/O readiness is performed once for each
scheduling tick instead of every thread switch.
o The non-signal saving/restoring versions of setjmp/longjmp
are used to save and restore thread contexts. This may
allow the removal of _THREAD_SAFE macros from setjmp()
and longjmp() - needs more investigation.
Change signal handling so that signals are handled in the
context of the thread that is receiving the signal. When
signals are dispatched to a thread, a special signal handling
frame is created on top of the target threads stack. The
frame contains the threads saved state information and a new
context in which the thread can run. The applications signal
handler is invoked through a wrapper routine that knows how
to restore the threads saved state and unwind to previous
frames.
Fix interruption of threads due to signals. Some states
were being improperly interrupted while other states were
not being interrupted. This should fix several PRs.
Signal handlers, which are invoked as a result of a process
signal (not by pthread_kill()), are now called with the
code (or siginfo_t if SA_SIGINFO was set in sa_flags) and
sigcontext_t as received from the process signal handler.
Modify the search for a thread to which a signal is delivered.
The search algorithm is now:
o First thread found in sigwait() with signal in wait mask.
o First thread found sigsuspend()'d on the signal.
o Current thread if signal is unmasked.
o First thread found with signal unmasked.
Collapse machine dependent support into macros defined in
pthread_private.h. These should probably eventually be moved
into separate MD files.
Change the range of settable priorities to be compliant with
POSIX (0-31). The threads library uses higher priorities
internally for real-time threads (not yet implemented) and
threads executing signal handlers. Real-time threads and
threads running signal handlers add 64 and 32, respectively,
to a threads base priority.
Some other small changes and cleanups.
PR: 17757 18559 21943
Reviewed by: jasone
not have a user-supplied signal handler, when a signal is delivered, one
thread will receive the signal, and then the code reverts to having no
signal handler for the signal. This can leave the other sigwait()ing
threads stranded permanently if the signal is later ignored, or can result
in process termination when the process should have delivered the signal to
one of the threads in sigwait().
To fix this problem, maintain a count of sigwait()ers for each signal that
has no default signal handler. Use the count to correctly install/uninstall
dummy signal handlers.
Reviewed by: deischen
not allowed to return EINTR, but use of pthread_suspend_np() could cause
EINTR to be returned. To fix this, restructure pthread_suspend_np() so that
it does not interrupt a thread that is waiting on a mutex or condition, and
keep enough state around that pthread_resume_np() can fix things up
afterwards.
Reviewed by: deischen
thread waiting on an event (I/O, condvar, etc) will, when resumed using
pthread_resume_np, return with EINTR. For example, suspending and resuming
a thread blocked on read() will not requeue the thread for the read, but
will return -1 with errno = EINTR. If the suspended thread is in a critical
region, the thread is suspended as soon as it leaves the critical region.
Fix a bogon in pthread_kill() where a signal was being delivered twice
to threads waiting in sigwait().
Reported by (suspend/resume bug): jdp
Reviewed by: jasone
are not supported by this implementation, and the error return values
from sem_init(), sem_open(), sem_close(), and sem_unlink() reflect this.
Approved by: jkh
signal handler. Explicitly check for jumps to anywhere other than the
current stack, since such jumps are undefined according to POSIX.
While we're at it, convert thread cancellation to use continuations, since
it's cleaner than the original cancellation code.
Avoid delivering a signal to a thread twice. This was a pre-existing bug,
but was likely unexposed until these other changes were made.
Defer signals generated by pthread_kill() so that they can be delivered on
the appropriate stack. deischen claims that this is unnecessary, which is
likely true, but without this change, pthread_kill() can cause undefined
priority queue states and/or PANICs in [sig|_]longjmp(), so I'm leaving
this in for now. To compile this code out and exercise the bug, define
the _NO_UNDISPATCH cpp macro. Defining _PTHREADS_INVARIANTS as well will
cause earlier crashes.
PR: kern/14685
Collaboration with: deischen
the initial thread). Instead, just leave an unmapped gap between thread
stacks and make sure that the thread stacks won't grow into these gaps,
simply by limiting the size of the stacks with the 'len' argument to
mmap(). This (if I understand correctly) reduces VM overhead
considerably.
Reviewed by: deischen
o Don't call signal handlers with the signal handler access lock
held.
o Remove pending signals before calling signal handlers. If
pending signals were not removed prior to handling them,
invocation of the handler could cause the handler to be
called more than once for the same signal. Found by: JB
o When SIGCHLD arrives, wake up all threads in PS_WAIT_WAIT
(wait4).
PR: bin/15328
Reviewed by: jasone
Before this change, a signal was delivered to each thread that
didn't have the signal masked. Signals also improperly woke up
threads waiting on I/O. With this change, signals are now
handled in the following way:
o If a thread is waiting in a sigwait for the signal,
then the thread is woken up.
o If no threads are sigwait'ing on the signal and a
thread is in a sigsuspend waiting for the signal,
then the thread is woken up.
o In the case that no threads are waiting or suspended
on the signal, then the signal is delivered to the
first thread we find that has the signal unmasked.
o If no threads are waiting or suspended on the signal,
and no threads have the signal unmasked, then the signal
is added to the process wide pending signal set. The
signal will be delivered to the first thread that unmasks
the signal.
If there is an installed signal handler, it is only invoked
if the chosen thread was not in a sigwait.
In the case that multiple threads are waiting or suspended
on a signal, or multiple threads have the signal unmasked,
we wake up/deliver the signal to the first thread we find.
The above rules still apply.
Reported by: Scott Hess <scott@avantgo.com>
Reviewed by: jb, jasone
to use mmap(..., MAP_STACK, ...) on alpha too since that should work
now.
* Add hooks to allow GDB to access the internals of pthreads without
having to know the exact layout of struct pthread.
Reviewed by: deischen
eischen (Daniel Eischen) added wrappers to protect against cancled
threads orphaning internal resources.
the cancelability code is still a bit fuzzy but works for test
programs of my own, OpenBSD's and some examples from ORA's books.
add readdir_r to both libc and libc_r
add some 'const' attributes to function parameters
Reviewed by: eischen, jasone
-----------------------------
Most of the userland changes are in libc. For both the alpha
and the i386 setjmp has been changed to accomodate for the
new sigset_t. Internally, libc is mostly rewritten to use the
new syscalls. The exception is in compat-43/sigcompat.c
The POSIX thread library has also been rewritten to use the
new sigset_t. Except, that it currently only handles NSIG
signals instead of the maximum _SIG_MAXSIG. This should not
be a problem because current applications don't use any
signals higher than NSIG.
There are version bumps for the following libraries:
libdialog
libreadline
libc
libc_r
libedit
libftpio
libss
These libraries either a) have one of the modified structures
visible in the interface, or b) use sigset_t internally and
may cause breakage if new binaries are used against libraries
that don't have the sigset_t change. This not an immediate
issue, but will be as soon as applications start using the
new range to its fullest.
NOTE: libncurses already had an version bump and has not been
given one now.
NOTE: doscmd is a real casualty and has been disconnected for
the moment. Reconnection will eventually happen after
doscmd has been fixed. I'm aware that being the last one
to touch it, I'm automaticly promoted to being maintainer.
According to good taste this means that I will receive a
badge which either will be glued or mechanically stapled,
drilled or otherwise violently forced onto me :-)
NOTE: pcvt/vttest cannot be compiled with -traditional. The
change cause sys/types to be included along the way which
contains the const and volatile modifiers. I don't consider
this a solution, but more a workaround.
Always use mmap() for default-size stack allocation. Use MAP_ANON instead
of MAP_STACK on the alpha architecture.
Reduce the amount of code executed while owning _gc_mutex during stack
allocation.
Cache discarded default thread stacks for use in subsequent thread creations.
Create a red zone at the end of each stack (including the initial thread
stack), with the hope of causing a segfault if a stack overflows.
To activate these modifications, add -D_PTHREAD_GSTACK to CFLAGS in
src/lib/libc_r/Makefile. Since the modifications depend on the VM_STACK
kernel option, I'm not sure how to safely use growable stacks by default.
Testing, as well as algorithmic and stylistic comments are welcome.
o The polling mechanism for I/O readiness was changed from
select() to poll(). In additon, a wrapped version of poll()
is now provided.
o The wrapped select routine now converts each fd_set to a
poll array so that the thread scheduler doesn't have to
perform a bitwise search for selected fds each time file
descriptors are polled for I/O readiness.
o The thread scheduler was modified to use a new queue (_workq)
for threads that need work. Threads waiting for I/O readiness
and spinblocks are added to the work queue in addition to the
waiting queue. This reduces the time spent forming/searching
the array of file descriptors being polled.
o The waiting queue (_waitingq) is now maintained in order of
thread wakeup time. This allows the thread scheduler to
find the nearest wakeup time by looking at the first thread
in the queue instead of searching the entire queue.
o Removed file descriptor locking for select/poll routines. An
application should not rely on the threads library for providing
this locking; if necessary, the application should use mutexes
to protect selecting/polling of file descriptors.
o Retrieve and use the kernel clock rate/resolution at startup
instead of hardcoding the clock resolution to 10 msec (tested
with kernel running at 1000 HZ).
o All queues have been changed to use queue.h macros. These
include the queues of all threads, dead threads, and threads
waiting for file descriptor locks.
o Added reinitialization of the GC mutex and condition variable
after a fork. Also prevented reallocation of the ready queue
after a fork.
o Prevented the wrapped close routine from closing the thread
kernel pipes.
o Initialized file descriptor table for stdio entries at thread
init.
o Provided additional flags to indicate to what queues threads
belong.
o Moved TAILQ initialization for statically allocated mutex and
condition variables to after the spinlock.
o Added dispatching of signals to pthread_kill. Removing the
dispatching of signals from thread activation broke sigsuspend
when pthread_kill was used to send a signal to a thread.
o Temporarily set the state of a thread to PS_SUSPENDED when it
is first created and placed in the list of threads so that it
will not be accidentally scheduled before becoming a member
of one of the scheduling queues.
o Change the signal handler to queue signals to the thread kernel
pipe if the scheduling queues are protected. When scheduling
queues are unprotected, signals are then dequeued and handled.
o Ensured that all installed signal handlers block the scheduling
signal and that the scheduling signal handler blocks all
other signals. This ensures that the signal handler is only
interruptible for and by non-scheduling signals. An atomic
lock is used to decide which instance of the signal handler
will handle pending signals.
o Removed _lock_thread_list and _unlock_thread_list as they are
no longer used to protect the thread list.
o Added missing RCS IDs to modified files.
o Added checks for appropriate queue membership and activity when
adding, removing, and searching the scheduling queues. These
checks add very little overhead and are enabled when compiled
with _PTHREADS_INVARIANTS defined. Suggested and implemented
by Tor Egge with some modification by me.
o Close a race condition in uthread_close. (Tor Egge)
o Protect the scheduling queues while modifying them in
pthread_cond_signal and _thread_fd_unlock. (Tor Egge)
o Ensure that when a thread gets a mutex, the mutex is on that
threads list of owned mutexes. (Tor Egge)
o Set the kernel-in-scheduler flag in _thread_kern_sched_state
and _thread_kern_sched_state_unlock to prevent a scheduling
signal from calling the scheduler again. (Tor Egge)
o Don't use TAILQ_FOREACH macro while searching the waiting
queue for threads in a sigwait state, because a change of
state destroys the TAILQ link. It is actually safe to do
so, though, because once a sigwaiting thread is found, the
loop ends and the function returns. (Tor Egge)
o When dispatching signals to threads, make the thread inherit
the signal deferral flag of the currently running thread.
(Tor Egge)
Submitted by: Daniel Eischen <eischen@vigrid.com> and
Tor Egge <Tor.Egge@fast.no>