diff options
-rw-r--r-- | lib/libkse/thread/thr_create.c | 1 | ||||
-rw-r--r-- | lib/libkse/thread/thr_private.h | 1 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sig.c | 6 | ||||
-rw-r--r-- | lib/libkse/thread/thr_sigsuspend.c | 39 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_create.c | 1 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_private.h | 1 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sig.c | 6 | ||||
-rw-r--r-- | lib/libpthread/thread/thr_sigsuspend.c | 39 |
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; |