summaryrefslogtreecommitdiffstats
path: root/lib/libkse/thread/thr_sig.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkse/thread/thr_sig.c')
-rw-r--r--lib/libkse/thread/thr_sig.c226
1 files changed, 109 insertions, 117 deletions
diff --git a/lib/libkse/thread/thr_sig.c b/lib/libkse/thread/thr_sig.c
index ba31073..3ec0eca 100644
--- a/lib/libkse/thread/thr_sig.c
+++ b/lib/libkse/thread/thr_sig.c
@@ -45,7 +45,7 @@
/* Prototypes: */
static void build_siginfo(siginfo_t *info, int signo);
-static void thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info);
+/* static void thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info); */
static void thr_sig_check_state(struct pthread *pthread, int sig);
static struct pthread *thr_sig_find(struct kse *curkse, int sig,
siginfo_t *info);
@@ -158,7 +158,7 @@ _thr_sig_dispatch(struct kse *curkse, int sig, siginfo_t *info)
*/
DBG_MSG("Got signal %d, selecting thread %p\n", sig, thread);
KSE_SCHED_LOCK(curkse, thread->kseg);
- thr_sig_add(thread, sig, info);
+ _thr_sig_add(thread, sig, info);
KSE_SCHED_UNLOCK(curkse, thread->kseg);
}
}
@@ -571,146 +571,138 @@ handle_special_signals(struct kse *curkse, int sig)
*
* This must be called with the thread's scheduling lock held.
*/
-static void
-thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
+void
+_thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
{
int restart;
int suppress_handler = 0;
- restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
+ if (pthread->curframe == NULL) {
+ /*
+ * This thread is active. Just add it to the
+ * thread's pending set.
+ */
+ sigaddset(&pthread->sigpend, sig);
+ pthread->check_pending = 1;
+ if (info == NULL)
+ build_siginfo(&pthread->siginfo[sig], sig);
+ else if (info != &pthread->siginfo[sig])
+ memcpy(&pthread->siginfo[sig], info,
+ sizeof(*info));
+ if ((pthread->blocked != 0) && !THR_IN_CRITICAL(pthread))
+ kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */);
+ }
+ else {
+ restart = _thread_sigact[sig - 1].sa_flags & SA_RESTART;
- /* Make sure this signal isn't still in the pending set: */
- sigdelset(&pthread->sigpend, sig);
+ /* Make sure this signal isn't still in the pending set: */
+ sigdelset(&pthread->sigpend, sig);
- /*
- * Process according to thread state:
- */
- switch (pthread->state) {
- /*
- * States which do not change when a signal is trapped:
- */
- case PS_DEAD:
- case PS_DEADLOCK:
- case PS_LOCKWAIT:
- case PS_SUSPENDED:
- case PS_STATE_MAX:
/*
- * You can't call a signal handler for threads in these
- * states.
+ * Process according to thread state:
*/
- suppress_handler = 1;
- break;
-
- /*
- * States which do not need any cleanup handling when signals
- * occur:
- */
- case PS_RUNNING:
+ switch (pthread->state) {
/*
- * Remove the thread from the queue before changing its
- * priority:
+ * States which do not change when a signal is trapped:
*/
- if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0)
- THR_RUNQ_REMOVE(pthread);
- else {
+ case PS_DEAD:
+ case PS_DEADLOCK:
+ case PS_LOCKWAIT:
+ case PS_SUSPENDED:
+ case PS_STATE_MAX:
/*
- * This thread is active; add the signal to the
- * pending set and mark it as having pending
- * signals.
+ * You can't call a signal handler for threads in these
+ * states.
*/
suppress_handler = 1;
- sigaddset(&pthread->sigpend, sig);
- build_siginfo(&pthread->siginfo[sig], sig);
- pthread->check_pending = 1;
- if ((pthread->blocked != 0) &&
- !THR_IN_CRITICAL(pthread))
- kse_thr_interrupt(&pthread->tmbx /* XXX - restart?!?! */);
- }
- break;
+ break;
- /*
- * States which cannot be interrupted but still require the
- * signal handler to run:
- */
- case PS_COND_WAIT:
- case PS_MUTEX_WAIT:
/*
- * Remove the thread from the wait queue. It will
- * be added back to the wait queue once all signal
- * handlers have been invoked.
+ * States which do not need any cleanup handling when signals
+ * occur:
*/
- KSE_WAITQ_REMOVE(pthread->kse, pthread);
- break;
+ case PS_RUNNING:
+ /*
+ * Remove the thread from the queue before changing its
+ * priority:
+ */
+ if ((pthread->flags & THR_FLAGS_IN_RUNQ) != 0)
+ THR_RUNQ_REMOVE(pthread);
+ break;
- case PS_SLEEP_WAIT:
/*
- * Unmasked signals always cause sleep to terminate early,
- * regardless of SA_RESTART:
+ * States which cannot be interrupted but still require the
+ * signal handler to run:
*/
- pthread->interrupted = 1;
- KSE_WAITQ_REMOVE(pthread->kse, pthread);
- THR_SET_STATE(pthread, PS_RUNNING);
- break;
-
- case PS_JOIN:
- case PS_SIGSUSPEND:
- KSE_WAITQ_REMOVE(pthread->kse, pthread);
- THR_SET_STATE(pthread, PS_RUNNING);
- break;
+ case PS_COND_WAIT:
+ case PS_MUTEX_WAIT:
+ /*
+ * Remove the thread from the wait queue. It will
+ * be added back to the wait queue once all signal
+ * handlers have been invoked.
+ */
+ KSE_WAITQ_REMOVE(pthread->kse, pthread);
+ break;
- case PS_SIGWAIT:
- /* The signal handler is not called for threads in SIGWAIT. */
- suppress_handler = 1;
- /* Wake up the thread if the signal is blocked. */
- if (sigismember(pthread->data.sigwait, sig)) {
- /* Return the signal number: */
- pthread->signo = sig;
+ case PS_SLEEP_WAIT:
+ /*
+ * Unmasked signals always cause sleep to terminate
+ * early regardless of SA_RESTART:
+ */
+ pthread->interrupted = 1;
+ KSE_WAITQ_REMOVE(pthread->kse, pthread);
+ THR_SET_STATE(pthread, PS_RUNNING);
+ break;
- /* Make the thread runnable: */
- _thr_setrunnable_unlocked(pthread);
- } else
- /* Increment the pending signal count. */
- sigaddset(&pthread->sigpend, sig);
- break;
- }
+ case PS_JOIN:
+ case PS_SIGSUSPEND:
+ KSE_WAITQ_REMOVE(pthread->kse, pthread);
+ THR_SET_STATE(pthread, PS_RUNNING);
+ break;
- if (suppress_handler == 0) {
- if (pthread->curframe == NULL) {
+ case PS_SIGWAIT:
/*
- * This thread is active. Just add it to the
- * thread's pending set.
+ * The signal handler is not called for threads in
+ * SIGWAIT.
*/
- sigaddset(&pthread->sigpend, sig);
- pthread->check_pending = 1;
- if (info == NULL)
- build_siginfo(&pthread->siginfo[sig], sig);
- else
- memcpy(&pthread->siginfo[sig], info,
- sizeof(*info));
- } else {
+ suppress_handler = 1;
+ /* Wake up the thread if the signal is blocked. */
+ if (sigismember(pthread->data.sigwait, sig)) {
+ /* Return the signal number: */
+ pthread->signo = sig;
+
+ /* Make the thread runnable: */
+ _thr_setrunnable_unlocked(pthread);
+ } else
+ /* Increment the pending signal count. */
+ sigaddset(&pthread->sigpend, sig);
+ break;
+ }
+
+ if (suppress_handler == 0) {
/*
* Setup a signal frame and save the current threads
* state:
*/
thr_sigframe_add(pthread, sig, info);
- }
- if (pthread->state != PS_RUNNING)
- THR_SET_STATE(pthread, PS_RUNNING);
+ if (pthread->state != PS_RUNNING)
+ THR_SET_STATE(pthread, PS_RUNNING);
- /*
- * The thread should be removed from all scheduling
- * queues at this point. Raise the priority and
- * place the thread in the run queue. It is also
- * possible for a signal to be sent to a suspended
- * thread, mostly via pthread_kill(). If a thread
- * is suspended, don't insert it into the priority
- * queue; just set its state to suspended and it
- * will run the signal handler when it is resumed.
- */
- pthread->active_priority |= THR_SIGNAL_PRIORITY;
- if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
- THR_RUNQ_INSERT_TAIL(pthread);
+ /*
+ * The thread should be removed from all scheduling
+ * queues at this point. Raise the priority and
+ * place the thread in the run queue. It is also
+ * possible for a signal to be sent to a suspended
+ * thread, mostly via pthread_kill(). If a thread
+ * is suspended, don't insert it into the priority
+ * queue; just set its state to suspended and it
+ * will run the signal handler when it is resumed.
+ */
+ pthread->active_priority |= THR_SIGNAL_PRIORITY;
+ if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
+ THR_RUNQ_INSERT_TAIL(pthread);
+ }
}
}
@@ -834,7 +826,7 @@ _thr_sig_send(struct pthread *pthread, int sig)
* Perform any state changes due to signal
* arrival:
*/
- thr_sig_add(pthread, sig, NULL);
+ _thr_sig_add(pthread, sig, NULL);
THR_SCHED_UNLOCK(curthread, pthread);
}
}
@@ -846,20 +838,20 @@ thr_sigframe_add(struct pthread *thread, int sig, siginfo_t *info)
if (thread->curframe == NULL)
PANIC("Thread doesn't have signal frame ");
- if (thread->check_pending == 0) {
+ if (thread->have_signals == 0) {
/*
* Multiple signals can be added to the same signal
* frame. Only save the thread's state the first time.
*/
thr_sigframe_save(thread, thread->curframe);
- thread->check_pending = 1;
+ thread->have_signals = 1;
thread->flags &= THR_FLAGS_PRIVATE;
}
sigaddset(&thread->curframe->psf_sigset, sig);
- if (info != NULL)
- memcpy(&thread->siginfo[sig], info, sizeof(*info));
- else
+ if (info == NULL)
build_siginfo(&thread->siginfo[sig], sig);
+ else if (info != &thread->siginfo[sig])
+ memcpy(&thread->siginfo[sig], info, sizeof(*info));
/* Setup the new signal mask. */
SIGSETOR(thread->tmbx.tm_context.uc_sigmask,
OpenPOWER on IntegriCloud