summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libkse/thread/thr_create.c1
-rw-r--r--lib/libkse/thread/thr_private.h1
-rw-r--r--lib/libkse/thread/thr_sig.c6
-rw-r--r--lib/libkse/thread/thr_sigsuspend.c39
-rw-r--r--lib/libpthread/thread/thr_create.c1
-rw-r--r--lib/libpthread/thread/thr_private.h1
-rw-r--r--lib/libpthread/thread/thr_sig.c6
-rw-r--r--lib/libpthread/thread/thr_sigsuspend.c39
8 files changed, 50 insertions, 44 deletions
diff --git a/lib/libkse/thread/thr_create.c b/lib/libkse/thread/thr_create.c
index 38c2fc4..0f7cbab 100644
--- a/lib/libkse/thread/thr_create.c
+++ b/lib/libkse/thread/thr_create.c
@@ -256,6 +256,7 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->sigstk.ss_sp = 0;
new_thread->sigstk.ss_size = 0;
new_thread->sigstk.ss_flags = SS_DISABLE;
+ new_thread->oldsigmask = NULL;
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
new_thread->state = PS_SUSPENDED;
diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h
index 191f9c1..98c967b 100644
--- a/lib/libkse/thread/thr_private.h
+++ b/lib/libkse/thread/thr_private.h
@@ -657,6 +657,7 @@ struct pthread {
*/
sigset_t sigmask;
sigset_t sigpend;
+ sigset_t *oldsigmask;
volatile int check_pending;
int refcount;
diff --git a/lib/libkse/thread/thr_sig.c b/lib/libkse/thread/thr_sig.c
index 2a8d667..010a999 100644
--- a/lib/libkse/thread/thr_sig.c
+++ b/lib/libkse/thread/thr_sig.c
@@ -463,7 +463,11 @@ thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
ucp->uc_stack = curthread->sigstk;
ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
- ucp->uc_sigmask = sigmask;
+ if (curthread->oldsigmask) {
+ ucp->uc_sigmask = *(curthread->oldsigmask);
+ curthread->oldsigmask = NULL;
+ } else
+ ucp->uc_sigmask = sigmask;
shi.sigfunc = sigfunc;
shi.sig = sig;
shi.sa_flags = sa_flags;
diff --git a/lib/libkse/thread/thr_sigsuspend.c b/lib/libkse/thread/thr_sigsuspend.c
index cad5745..b7802e3 100644
--- a/lib/libkse/thread/thr_sigsuspend.c
+++ b/lib/libkse/thread/thr_sigsuspend.c
@@ -44,7 +44,7 @@ int
_sigsuspend(const sigset_t *set)
{
struct pthread *curthread = _get_curthread();
- sigset_t oldmask, newmask;
+ sigset_t oldmask, newmask, tempset;
int ret = -1;
if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
@@ -54,32 +54,29 @@ _sigsuspend(const sigset_t *set)
if (set != NULL) {
newmask = *set;
SIG_CANTMASK(newmask);
-
THR_LOCK_SWITCH(curthread);
- /* Save current sigmask */
- memcpy(&oldmask, &curthread->sigmask, sizeof(sigset_t));
+ /* Save current sigmask: */
+ oldmask = curthread->sigmask;
+ curthread->oldsigmask = &oldmask;
/* Change the caller's mask: */
- memcpy(&curthread->sigmask, &newmask, sizeof(sigset_t));
-
- THR_SET_STATE(curthread, PS_SIGSUSPEND);
-
- /* Wait for a signal: */
- _thr_sched_switch_unlocked(curthread);
-
+ curthread->sigmask = newmask;
+ tempset = curthread->sigpend;
+ SIGSETNAND(tempset, newmask);
+ if (SIGISEMPTY(tempset)) {
+ THR_SET_STATE(curthread, PS_SIGSUSPEND);
+ /* Wait for a signal: */
+ _thr_sched_switch_unlocked(curthread);
+ } else {
+ THR_UNLOCK_SWITCH(curthread);
+ /* check pending signal I can handle: */
+ _thr_sig_check_pending(curthread);
+ }
+ THR_ASSERT(curthread->oldsigmask == NULL,
+ "oldsigmask is not cleared");
/* Always return an interrupted error: */
errno = EINTR;
-
- THR_SCHED_LOCK(curthread, curthread);
- /* Restore the signal mask: */
- memcpy(&curthread->sigmask, &oldmask, sizeof(sigset_t));
- THR_SCHED_UNLOCK(curthread, curthread);
- /*
- * signal mask is reloaded, need to check if there is
- * pending proc signal I can handle.
- */
- _thr_sig_check_pending(curthread);
} else {
/* Return an invalid argument error: */
errno = EINVAL;
diff --git a/lib/libpthread/thread/thr_create.c b/lib/libpthread/thread/thr_create.c
index 38c2fc4..0f7cbab 100644
--- a/lib/libpthread/thread/thr_create.c
+++ b/lib/libpthread/thread/thr_create.c
@@ -256,6 +256,7 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->sigstk.ss_sp = 0;
new_thread->sigstk.ss_size = 0;
new_thread->sigstk.ss_flags = SS_DISABLE;
+ new_thread->oldsigmask = NULL;
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
new_thread->state = PS_SUSPENDED;
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
index 191f9c1..98c967b 100644
--- a/lib/libpthread/thread/thr_private.h
+++ b/lib/libpthread/thread/thr_private.h
@@ -657,6 +657,7 @@ struct pthread {
*/
sigset_t sigmask;
sigset_t sigpend;
+ sigset_t *oldsigmask;
volatile int check_pending;
int refcount;
diff --git a/lib/libpthread/thread/thr_sig.c b/lib/libpthread/thread/thr_sig.c
index 2a8d667..010a999 100644
--- a/lib/libpthread/thread/thr_sig.c
+++ b/lib/libpthread/thread/thr_sig.c
@@ -463,7 +463,11 @@ thr_sig_invoke_handler(struct pthread *curthread, int sig, siginfo_t *info,
ucp->uc_stack = curthread->sigstk;
ucp->uc_stack.ss_flags = (curthread->sigstk.ss_flags & SS_DISABLE)
? SS_DISABLE : ((onstack) ? SS_ONSTACK : 0);
- ucp->uc_sigmask = sigmask;
+ if (curthread->oldsigmask) {
+ ucp->uc_sigmask = *(curthread->oldsigmask);
+ curthread->oldsigmask = NULL;
+ } else
+ ucp->uc_sigmask = sigmask;
shi.sigfunc = sigfunc;
shi.sig = sig;
shi.sa_flags = sa_flags;
diff --git a/lib/libpthread/thread/thr_sigsuspend.c b/lib/libpthread/thread/thr_sigsuspend.c
index cad5745..b7802e3 100644
--- a/lib/libpthread/thread/thr_sigsuspend.c
+++ b/lib/libpthread/thread/thr_sigsuspend.c
@@ -44,7 +44,7 @@ int
_sigsuspend(const sigset_t *set)
{
struct pthread *curthread = _get_curthread();
- sigset_t oldmask, newmask;
+ sigset_t oldmask, newmask, tempset;
int ret = -1;
if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
@@ -54,32 +54,29 @@ _sigsuspend(const sigset_t *set)
if (set != NULL) {
newmask = *set;
SIG_CANTMASK(newmask);
-
THR_LOCK_SWITCH(curthread);
- /* Save current sigmask */
- memcpy(&oldmask, &curthread->sigmask, sizeof(sigset_t));
+ /* Save current sigmask: */
+ oldmask = curthread->sigmask;
+ curthread->oldsigmask = &oldmask;
/* Change the caller's mask: */
- memcpy(&curthread->sigmask, &newmask, sizeof(sigset_t));
-
- THR_SET_STATE(curthread, PS_SIGSUSPEND);
-
- /* Wait for a signal: */
- _thr_sched_switch_unlocked(curthread);
-
+ curthread->sigmask = newmask;
+ tempset = curthread->sigpend;
+ SIGSETNAND(tempset, newmask);
+ if (SIGISEMPTY(tempset)) {
+ THR_SET_STATE(curthread, PS_SIGSUSPEND);
+ /* Wait for a signal: */
+ _thr_sched_switch_unlocked(curthread);
+ } else {
+ THR_UNLOCK_SWITCH(curthread);
+ /* check pending signal I can handle: */
+ _thr_sig_check_pending(curthread);
+ }
+ THR_ASSERT(curthread->oldsigmask == NULL,
+ "oldsigmask is not cleared");
/* Always return an interrupted error: */
errno = EINTR;
-
- THR_SCHED_LOCK(curthread, curthread);
- /* Restore the signal mask: */
- memcpy(&curthread->sigmask, &oldmask, sizeof(sigset_t));
- THR_SCHED_UNLOCK(curthread, curthread);
- /*
- * signal mask is reloaded, need to check if there is
- * pending proc signal I can handle.
- */
- _thr_sig_check_pending(curthread);
} else {
/* Return an invalid argument error: */
errno = EINVAL;
OpenPOWER on IntegriCloud