summaryrefslogtreecommitdiffstats
path: root/lib/libpthread
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/thread/thr_init.c15
-rw-r--r--lib/libpthread/thread/thr_kern.c35
-rw-r--r--lib/libpthread/thread/thr_private.h5
-rw-r--r--lib/libpthread/thread/thr_sig.c2
4 files changed, 38 insertions, 19 deletions
diff --git a/lib/libpthread/thread/thr_init.c b/lib/libpthread/thread/thr_init.c
index 35731c4..be671a1 100644
--- a/lib/libpthread/thread/thr_init.c
+++ b/lib/libpthread/thread/thr_init.c
@@ -92,7 +92,6 @@ _thread_init(void)
int mib[2];
struct clockinfo clockinfo;
struct sigaction act;
- struct sigaltstack alt;
/* Check if this function has already been called: */
if (_thread_initial)
@@ -281,11 +280,15 @@ _thread_init(void)
/* Clear the signal queue: */
memset(_thread_sigq, 0, sizeof(_thread_sigq));
- /* Create and install an alternate signal stack: */
- alt.ss_sp = malloc(SIGSTKSZ); /* recommended stack size */
- alt.ss_size = SIGSTKSZ;
- alt.ss_flags = 0;
- if (_thread_sys_sigaltstack(&alt, NULL) != 0)
+ /*
+ * Create and install an alternate signal stack of
+ * the recommended size:
+ */
+ _thread_sigstack.ss_sp = malloc(SIGSTKSZ);
+ _thread_sigstack.ss_size = SIGSTKSZ;
+ _thread_sigstack.ss_flags = 0;
+ if ((_thread_sigstack.ss_sp == NULL) ||
+ (_thread_sys_sigaltstack(&_thread_sigstack, NULL) != 0))
PANIC("Unable to install alternate signal stack");
/* Enter a loop to get the existing signal status: */
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;
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
index e8fff12..9d6bc31 100644
--- a/lib/libpthread/thread/thr_private.h
+++ b/lib/libpthread/thread/thr_private.h
@@ -1127,6 +1127,9 @@ SCLASS volatile int _sigq_check_reqd
#endif
;
+/* The signal stack. */
+SCLASS struct sigaltstack _thread_sigstack;
+
/* Thread switch hook. */
SCLASS pthread_switch_routine_t _sched_switch_hook
#ifdef GLOBAL_PTHREAD_PRIVATE
@@ -1268,7 +1271,7 @@ int _thread_sys_sigsuspend(const sigset_t *);
int _thread_sys_siginterrupt(int, int);
int _thread_sys_sigpause(int);
int _thread_sys_sigreturn(ucontext_t *);
-int _thread_sys_sigaltstack(const struct sigaltstack *, struct sigstack *);
+int _thread_sys_sigaltstack(const struct sigaltstack *, struct sigaltstack *);
int _thread_sys_sigstack(const struct sigstack *, struct sigstack *);
int _thread_sys_sigvec(int, struct sigvec *, struct sigvec *);
void _thread_sys_psignal(unsigned int, const char *);
diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c
index 3bcd9c1..3ac9740 100644
--- a/lib/libpthread/thread/thr_sig.c
+++ b/lib/libpthread/thread/thr_sig.c
@@ -1066,7 +1066,7 @@ thread_sigframe_add(pthread_t thread, int sig, int has_args)
/*
* Set up the context:
*/
- stackp += sizeof(double);
+ stackp -= sizeof(double);
_setjmp(thread->ctx.jb);
SET_STACK_JB(thread->ctx.jb, stackp);
SET_RETURN_ADDR_JB(thread->ctx.jb, _thread_sig_wrapper);
OpenPOWER on IntegriCloud