summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/thread/thr_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/thread/thr_kern.c')
-rw-r--r--lib/libpthread/thread/thr_kern.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c
index 4d92385..2b7b270 100644
--- a/lib/libpthread/thread/thr_kern.c
+++ b/lib/libpthread/thread/thr_kern.c
@@ -71,6 +71,7 @@ thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in);
/* Static variables: */
static int last_tick = 0;
+static int called_from_handler = 0;
/*
* This is called when a signal handler finishes and wants to
@@ -106,20 +107,12 @@ _thread_kern_sched(ucontext_t *scp)
/* Check if this function was called from the signal handler: */
if (scp != NULL) {
- /*
- * The signal handler should have saved the state of
- * the current thread. Restore the process signal
- * mask.
- */
- if (_thread_sys_sigprocmask(SIG_SETMASK,
- &_process_sigmask, NULL) != 0)
- PANIC("Unable to restore process mask after signal");
+ called_from_handler = 1;
/*
* We're running on the signal stack; just call the
* kernel scheduler directly.
*/
DBG_MSG("Entering scheduler due to signal\n");
- _thread_kern_scheduler();
} else {
/* Save the state of the current thread: */
if (_setjmp(_thread_run->ctx.jb) == 0) {
@@ -162,9 +155,9 @@ _thread_kern_sched(ucontext_t *scp)
}
return;
}
- /* Switch to the thread scheduler: */
- ___longjmp(_thread_kern_sched_jb, 1);
}
+ /* Switch to the thread scheduler: */
+ ___longjmp(_thread_kern_sched_jb, 1);
}
void
@@ -188,6 +181,26 @@ _thread_kern_scheduler(void)
if ((_thread_run->flags & PTHREAD_FLAGS_PRIVATE) == 0)
_last_user_thread = _thread_run;
+ if (called_from_handler != 0) {
+ called_from_handler = 0;
+
+ /*
+ * The signal handler should have saved the state of
+ * the current thread. Restore the process signal
+ * mask.
+ */
+ if (_thread_sys_sigprocmask(SIG_SETMASK,
+ &_process_sigmask, NULL) != 0)
+ PANIC("Unable to restore process mask after signal");
+
+ /*
+ * Since the signal handler didn't return normally, we
+ * have to tell the kernel to reuse the signal stack.
+ */
+ if (_thread_sys_sigaltstack(&_thread_sigstack, NULL) != 0)
+ PANIC("Unable to restore alternate signal stack");
+ }
+
/* Are there pending signals for this thread? */
if (_thread_run->check_pending != 0) {
_thread_run->check_pending = 0;
OpenPOWER on IntegriCloud