DragonFly kernel List (threaded) for 2005-05
Re: cvs commit: src/sys/i386/include tls.h src/gnu/usr.bin/cc34/cc_prep/config dragonfly-spec.h src/gnu/usr.bin/cc34/cc_prep/config/i386 dragonfly.h src/lib/csu/i386 crt1.c src/lib/libc/gen tls.c src/lib/libc/i386/sys cerror.S src/lib/libc/include libc_private.h ...
Joerg Sonnenberger wrote:
[redirected to kernel@]
On Wed, May 11, 2005 at 10:10:29PM -0700, Matthew Dillon wrote:
:I need fast critical section, otherwise I can just use sigprocmask
:everywhere, the critical section has to be per-thread based, a
:shared memory page won't work. one thread blocking signal shouldn't
:stop other threads to process signal.
sigprocmask works for now, but it is semantically different.
Well, each thread could have its own block of memory. But that could
add up fairly quickly.
Well, the same block used by the syscall layer could be used here too.
It has to be thread-local [thread-index is not an option, there can be
an arbitrary high number of threads]. TCB is not good, the kernel sohuld
not depend on %gs mappings of userland programs.
Another option would be to implement a code path critical section.
Basically we would inform the kernel not to interrupt userland if
the userland instruction pointer is within a specified range of
addresses. This would also be easy to implement.
I already suggested one possible implementation before.
But let us first define the requirements, I'm not 100% sure what we need
after reading SUS. As I read the situation is as following:
(1) We have a single canonical PID for each process, which is constant.
The thread PIDs should either go away or be mapped to this PID for the
purpose of sending signals or otherwise identifying processes.
(2) Each process has a global signal mask, which determines which signals
are allowed by other processes and how to handle them (default action,
ignore, deliver to process).
Process does not have global signal mask, it is each thread in a process
has its own signal mask. there is a global pending signal set in the
process.Each thread has its own pending set, signal masks, but share
signal action with other threads
If a signal is sent to a process, and one of thread does not mask the
signal, the thread should receive the signal, put the signal into the
thread's pending set, and wake up the thread.
If all thread masked the signal, the signal should be put in the process
global pending set. once a thread unmasks the signal, the signal in
global pending set should be moved to thread's pending set.
Whenever the thread is at user boundary, unmasked signal in its pending
set should be delivered to user code.
Any job control signal which can suspend a single thread process now
should suspend all threads for multiple threads process.
signals like SIGSTOP (unmaskable), SIGTSTP, SIGTTOUT... should suspend
all threads, a SIGCONT should unsuspend all threads.
There are synchronous signal and asynchronous signal.
signals like SIGTRAP, SIGSEGV, SIGILL, SIGFPE are generated by hardware
in the thread's context, it should be only be sent to the thread
triggered it (here, libc_r has the serious bug).
Other signals sent by kill() syscall and others, should be delivered to
any thread which does not mask it or waiting for it in sigwait()
syscall, a signal sent by kill() syscall and others is a asynchronous
signal despite it is SIGTRAP or SIGSEGV...
(3) When a signal is arrives which should be delivered the process,
the corresponding entry in the sigpending mask is set.
(4) An upcall to the process is issued to handle one (all?) pending
signals, further attempts to deliver signals are temporary masked.
The interesting question is: to which thread does the upcall occur?
For a n:1 implementation like libc_r, it doesn't matter. Does it make
sense to mark a special signal thread which gets the normal "external"
signals? We could extend this to allow "internal" signals aka upcalls
into other threads. Another possible option is to issue the upcall to
the next running thread.
Does sigprocmask apply to signals with default handler too?Yes