Avoid accessing user provided parameters in critical region.
Reviewed by: deischen
This commit is contained in:
parent
dce6e6518b
commit
91f7616aff
@ -37,6 +37,7 @@ int
|
||||
_pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
struct pthread_attr attr;
|
||||
int ret;
|
||||
|
||||
if (pid == NULL || dst == NULL || *dst == NULL)
|
||||
@ -45,9 +46,9 @@ _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst)
|
||||
curthread = _get_curthread();
|
||||
if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0)
|
||||
return (ret);
|
||||
|
||||
memcpy(*dst, &pid->attr, sizeof(struct pthread_attr));
|
||||
attr = pid->attr;
|
||||
_thr_ref_delete(curthread, pid);
|
||||
memcpy(*dst, &attr, sizeof(struct pthread_attr));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -146,16 +146,12 @@ _pthread_setcancelstate(int state, int *oldstate)
|
||||
|
||||
switch (state) {
|
||||
case PTHREAD_CANCEL_ENABLE:
|
||||
if (oldstate != NULL)
|
||||
*oldstate = ostate;
|
||||
curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE;
|
||||
if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)
|
||||
need_exit = checkcancel(curthread);
|
||||
ret = 0;
|
||||
break;
|
||||
case PTHREAD_CANCEL_DISABLE:
|
||||
if (oldstate != NULL)
|
||||
*oldstate = ostate;
|
||||
curthread->cancelflags |= PTHREAD_CANCEL_DISABLE;
|
||||
ret = 0;
|
||||
break;
|
||||
@ -169,6 +165,9 @@ _pthread_setcancelstate(int state, int *oldstate)
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
PANIC("cancel");
|
||||
}
|
||||
if (ret == 0 && oldstate != NULL)
|
||||
*oldstate = ostate;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@ -186,15 +185,11 @@ _pthread_setcanceltype(int type, int *oldtype)
|
||||
otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS;
|
||||
switch (type) {
|
||||
case PTHREAD_CANCEL_ASYNCHRONOUS:
|
||||
if (oldtype != NULL)
|
||||
*oldtype = otype;
|
||||
curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS;
|
||||
need_exit = checkcancel(curthread);
|
||||
ret = 0;
|
||||
break;
|
||||
case PTHREAD_CANCEL_DEFERRED:
|
||||
if (oldtype != NULL)
|
||||
*oldtype = otype;
|
||||
curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
|
||||
ret = 0;
|
||||
break;
|
||||
@ -208,6 +203,9 @@ _pthread_setcanceltype(int type, int *oldtype)
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
PANIC("cancel");
|
||||
}
|
||||
if (ret == 0 && oldtype != NULL)
|
||||
*oldtype = otype;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
|
||||
struct sched_param *param)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
int ret;
|
||||
int ret, tmp;
|
||||
|
||||
if ((param == NULL) || (policy == NULL))
|
||||
/* Return an invalid argument error: */
|
||||
@ -55,8 +55,9 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
param->sched_priority =
|
||||
THR_BASE_PRIORITY(pthread->base_priority);
|
||||
*policy = pthread->attr.sched_policy;
|
||||
tmp = pthread->attr.sched_policy;
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
*policy = tmp;
|
||||
ret = 0;
|
||||
}
|
||||
/* Find the thread in the list of active threads. */
|
||||
@ -65,9 +66,10 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
|
||||
THR_SCHED_LOCK(curthread, pthread);
|
||||
param->sched_priority =
|
||||
THR_BASE_PRIORITY(pthread->base_priority);
|
||||
*policy = pthread->attr.sched_policy;
|
||||
tmp = pthread->attr.sched_policy;
|
||||
THR_SCHED_UNLOCK(curthread, pthread);
|
||||
_thr_ref_delete(curthread, pthread);
|
||||
*policy = tmp;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ int
|
||||
_pthread_join(pthread_t pthread, void **thread_return)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
void *tmp;
|
||||
kse_critical_t crit;
|
||||
int ret = 0;
|
||||
|
||||
@ -80,9 +81,8 @@ _pthread_join(pthread_t pthread, void **thread_return)
|
||||
} else {
|
||||
/* Lock the target thread while checking its state. */
|
||||
if (pthread->state == PS_DEAD) {
|
||||
if (thread_return != NULL)
|
||||
/* Return the thread's return value: */
|
||||
*thread_return = pthread->ret;
|
||||
/* Return the thread's return value: */
|
||||
tmp = pthread->ret;
|
||||
|
||||
/* Detach the thread. */
|
||||
pthread->attr.flags |= PTHREAD_DETACHED;
|
||||
@ -103,6 +103,8 @@ _pthread_join(pthread_t pthread, void **thread_return)
|
||||
|
||||
/* Remove the reference. */
|
||||
_thr_ref_delete(curthread, pthread);
|
||||
if (thread_return != NULL)
|
||||
*thread_return = tmp;
|
||||
}
|
||||
else if (pthread->joiner != NULL) {
|
||||
/* Unlock the thread and remove the reference. */
|
||||
|
@ -93,6 +93,7 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
|
||||
int prioceiling, int *old_ceiling)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp;
|
||||
|
||||
if ((mutex == NULL) || (*mutex == NULL))
|
||||
ret = EINVAL;
|
||||
@ -100,12 +101,15 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
|
||||
ret = EINVAL;
|
||||
/* Lock the mutex: */
|
||||
else if ((ret = pthread_mutex_lock(mutex)) == 0) {
|
||||
/* Return the old ceiling and set the new ceiling: */
|
||||
*old_ceiling = (*mutex)->m_prio;
|
||||
tmp = (*mutex)->m_prio;
|
||||
/* Set the new ceiling: */
|
||||
(*mutex)->m_prio = prioceiling;
|
||||
|
||||
/* Unlock the mutex: */
|
||||
ret = pthread_mutex_unlock(mutex);
|
||||
|
||||
/* Return the old ceiling: */
|
||||
*old_ceiling = tmp;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ int
|
||||
_sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sigaction gact;
|
||||
struct sigaction newact, oldact;
|
||||
struct pthread *curthread;
|
||||
kse_critical_t crit;
|
||||
kse_critical_t crit;
|
||||
|
||||
/* Check if the signal number is out of range: */
|
||||
if (sig < 1 || sig > _SIG_MAXSIG) {
|
||||
@ -55,6 +55,9 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
if (!_kse_isthreaded())
|
||||
return __sys_sigaction(sig, act, oact);
|
||||
|
||||
if (act)
|
||||
newact = *act;
|
||||
|
||||
crit = _kse_critical_enter();
|
||||
curthread = _get_curthread();
|
||||
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
|
||||
@ -64,17 +67,13 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
*/
|
||||
if (oact != NULL) {
|
||||
/* Return the existing signal action contents: */
|
||||
oact->sa_handler = _thread_sigact[sig - 1].sa_handler;
|
||||
oact->sa_mask = _thread_sigact[sig - 1].sa_mask;
|
||||
oact->sa_flags = _thread_sigact[sig - 1].sa_flags;
|
||||
oldact = _thread_sigact[sig - 1];
|
||||
}
|
||||
|
||||
/* Check if a signal action was supplied: */
|
||||
if (act != NULL) {
|
||||
/* Set the new signal handler: */
|
||||
_thread_sigact[sig - 1].sa_mask = act->sa_mask;
|
||||
_thread_sigact[sig - 1].sa_flags = act->sa_flags;
|
||||
_thread_sigact[sig - 1].sa_handler = act->sa_handler;
|
||||
_thread_sigact[sig - 1] = newact;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -82,30 +81,30 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
* in signal action:
|
||||
*/
|
||||
if (act != NULL && sig != SIGINFO) {
|
||||
gact.sa_mask = act->sa_mask;
|
||||
gact.sa_flags = SA_SIGINFO | act->sa_flags;
|
||||
|
||||
newact.sa_flags |= SA_SIGINFO;
|
||||
|
||||
/*
|
||||
* Check if the signal handler is being set to
|
||||
* the default or ignore handlers:
|
||||
*/
|
||||
if (act->sa_handler == SIG_DFL ||
|
||||
act->sa_handler == SIG_IGN)
|
||||
/* Specify the built in handler: */
|
||||
gact.sa_handler = act->sa_handler;
|
||||
else
|
||||
if (newact.sa_handler != SIG_DFL &&
|
||||
newact.sa_handler != SIG_IGN) {
|
||||
/*
|
||||
* Specify the thread kernel signal
|
||||
* handler:
|
||||
*/
|
||||
gact.sa_handler = (void (*) ())_thr_sig_handler;
|
||||
|
||||
newact.sa_handler = (void (*) ())_thr_sig_handler;
|
||||
}
|
||||
/* Change the signal action in the kernel: */
|
||||
if (__sys_sigaction(sig, &gact, NULL) != 0)
|
||||
if (__sys_sigaction(sig, &newact, NULL) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
|
||||
_kse_critical_leave(crit);
|
||||
|
||||
if (oact != NULL)
|
||||
*oact = oldact;
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
|
@ -46,16 +46,21 @@ int
|
||||
_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
sigset_t oldset, newset;
|
||||
int ret;
|
||||
|
||||
if (! _kse_isthreaded())
|
||||
_kse_setthreaded(1);
|
||||
|
||||
if (set)
|
||||
newset = *set;
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
|
||||
ret = 0;
|
||||
if (oset != NULL)
|
||||
/* Return the current mask: */
|
||||
*oset = curthread->sigmask;
|
||||
oldset = curthread->sigmask;
|
||||
|
||||
/* Check if a new signal set was provided by the caller: */
|
||||
if (set != NULL) {
|
||||
@ -64,19 +69,19 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
/* Block signals: */
|
||||
case SIG_BLOCK:
|
||||
/* Add signals to the existing mask: */
|
||||
SIGSETOR(curthread->sigmask, *set);
|
||||
SIGSETOR(curthread->sigmask, newset);
|
||||
break;
|
||||
|
||||
/* Unblock signals: */
|
||||
case SIG_UNBLOCK:
|
||||
/* Clear signals from the existing mask: */
|
||||
SIGSETNAND(curthread->sigmask, *set);
|
||||
SIGSETNAND(curthread->sigmask, newset);
|
||||
break;
|
||||
|
||||
/* Set the signal process mask: */
|
||||
case SIG_SETMASK:
|
||||
/* Set the new mask: */
|
||||
curthread->sigmask = *set;
|
||||
curthread->sigmask = newset;
|
||||
break;
|
||||
|
||||
/* Trap invalid actions: */
|
||||
@ -96,5 +101,8 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
_thr_sig_check_pending(curthread);
|
||||
} else
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
if (ret == 0 && oset != NULL)
|
||||
*oset = oldset;
|
||||
return (ret);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ _sigpending(sigset_t *set)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
kse_critical_t crit;
|
||||
sigset_t sigset;
|
||||
int ret = 0;
|
||||
|
||||
/* Check for a null signal set pointer: */
|
||||
@ -59,12 +60,13 @@ _sigpending(sigset_t *set)
|
||||
|
||||
crit = _kse_critical_enter();
|
||||
KSE_SCHED_LOCK(curthread->kse, curthread->kseg);
|
||||
*set = curthread->sigpend;
|
||||
sigset = curthread->sigpend;
|
||||
KSE_SCHED_UNLOCK(curthread->kse, curthread->kseg);
|
||||
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
|
||||
SIGSETOR(*set, _thr_proc_sigpending);
|
||||
SIGSETOR(sigset, _thr_proc_sigpending);
|
||||
KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
|
||||
_kse_critical_leave(crit);
|
||||
*set = sigset;
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
|
@ -43,20 +43,23 @@ int
|
||||
_sigsuspend(const sigset_t *set)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
sigset_t oldmask, newmask;
|
||||
int ret = -1;
|
||||
sigset_t osigmask;
|
||||
|
||||
if (!_kse_isthreaded())
|
||||
return __sys_sigsuspend(set);
|
||||
|
||||
/* Check if a new signal set was provided by the caller: */
|
||||
if (set != NULL) {
|
||||
newmask = *set;
|
||||
|
||||
THR_LOCK_SWITCH(curthread);
|
||||
|
||||
/* Save current sigmask */
|
||||
memcpy(&osigmask, &curthread->sigmask, sizeof(osigmask));
|
||||
memcpy(&oldmask, &curthread->sigmask, sizeof(sigset_t));
|
||||
|
||||
/* Change the caller's mask: */
|
||||
memcpy(&curthread->sigmask, set, sizeof(sigset_t));
|
||||
memcpy(&curthread->sigmask, &newmask, sizeof(sigset_t));
|
||||
|
||||
THR_SET_STATE(curthread, PS_SIGSUSPEND);
|
||||
|
||||
@ -68,7 +71,7 @@ _sigsuspend(const sigset_t *set)
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Restore the signal mask: */
|
||||
memcpy(&curthread->sigmask, &osigmask, sizeof(sigset_t));
|
||||
memcpy(&curthread->sigmask, &oldmask, sizeof(sigset_t));
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
/*
|
||||
* signal mask is reloaded, need to check if there is
|
||||
|
@ -37,6 +37,7 @@ int
|
||||
_pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst)
|
||||
{
|
||||
struct pthread *curthread;
|
||||
struct pthread_attr attr;
|
||||
int ret;
|
||||
|
||||
if (pid == NULL || dst == NULL || *dst == NULL)
|
||||
@ -45,9 +46,9 @@ _pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst)
|
||||
curthread = _get_curthread();
|
||||
if ((ret = _thr_ref_add(curthread, pid, /*include dead*/0)) != 0)
|
||||
return (ret);
|
||||
|
||||
memcpy(*dst, &pid->attr, sizeof(struct pthread_attr));
|
||||
attr = pid->attr;
|
||||
_thr_ref_delete(curthread, pid);
|
||||
memcpy(*dst, &attr, sizeof(struct pthread_attr));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -146,16 +146,12 @@ _pthread_setcancelstate(int state, int *oldstate)
|
||||
|
||||
switch (state) {
|
||||
case PTHREAD_CANCEL_ENABLE:
|
||||
if (oldstate != NULL)
|
||||
*oldstate = ostate;
|
||||
curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE;
|
||||
if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)
|
||||
need_exit = checkcancel(curthread);
|
||||
ret = 0;
|
||||
break;
|
||||
case PTHREAD_CANCEL_DISABLE:
|
||||
if (oldstate != NULL)
|
||||
*oldstate = ostate;
|
||||
curthread->cancelflags |= PTHREAD_CANCEL_DISABLE;
|
||||
ret = 0;
|
||||
break;
|
||||
@ -169,6 +165,9 @@ _pthread_setcancelstate(int state, int *oldstate)
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
PANIC("cancel");
|
||||
}
|
||||
if (ret == 0 && oldstate != NULL)
|
||||
*oldstate = ostate;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@ -186,15 +185,11 @@ _pthread_setcanceltype(int type, int *oldtype)
|
||||
otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS;
|
||||
switch (type) {
|
||||
case PTHREAD_CANCEL_ASYNCHRONOUS:
|
||||
if (oldtype != NULL)
|
||||
*oldtype = otype;
|
||||
curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS;
|
||||
need_exit = checkcancel(curthread);
|
||||
ret = 0;
|
||||
break;
|
||||
case PTHREAD_CANCEL_DEFERRED:
|
||||
if (oldtype != NULL)
|
||||
*oldtype = otype;
|
||||
curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
|
||||
ret = 0;
|
||||
break;
|
||||
@ -208,6 +203,9 @@ _pthread_setcanceltype(int type, int *oldtype)
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
PANIC("cancel");
|
||||
}
|
||||
if (ret == 0 && oldtype != NULL)
|
||||
*oldtype = otype;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
|
||||
struct sched_param *param)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
int ret;
|
||||
int ret, tmp;
|
||||
|
||||
if ((param == NULL) || (policy == NULL))
|
||||
/* Return an invalid argument error: */
|
||||
@ -55,8 +55,9 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
param->sched_priority =
|
||||
THR_BASE_PRIORITY(pthread->base_priority);
|
||||
*policy = pthread->attr.sched_policy;
|
||||
tmp = pthread->attr.sched_policy;
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
*policy = tmp;
|
||||
ret = 0;
|
||||
}
|
||||
/* Find the thread in the list of active threads. */
|
||||
@ -65,9 +66,10 @@ _pthread_getschedparam(pthread_t pthread, int *policy,
|
||||
THR_SCHED_LOCK(curthread, pthread);
|
||||
param->sched_priority =
|
||||
THR_BASE_PRIORITY(pthread->base_priority);
|
||||
*policy = pthread->attr.sched_policy;
|
||||
tmp = pthread->attr.sched_policy;
|
||||
THR_SCHED_UNLOCK(curthread, pthread);
|
||||
_thr_ref_delete(curthread, pthread);
|
||||
*policy = tmp;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ int
|
||||
_pthread_join(pthread_t pthread, void **thread_return)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
void *tmp;
|
||||
kse_critical_t crit;
|
||||
int ret = 0;
|
||||
|
||||
@ -80,9 +81,8 @@ _pthread_join(pthread_t pthread, void **thread_return)
|
||||
} else {
|
||||
/* Lock the target thread while checking its state. */
|
||||
if (pthread->state == PS_DEAD) {
|
||||
if (thread_return != NULL)
|
||||
/* Return the thread's return value: */
|
||||
*thread_return = pthread->ret;
|
||||
/* Return the thread's return value: */
|
||||
tmp = pthread->ret;
|
||||
|
||||
/* Detach the thread. */
|
||||
pthread->attr.flags |= PTHREAD_DETACHED;
|
||||
@ -103,6 +103,8 @@ _pthread_join(pthread_t pthread, void **thread_return)
|
||||
|
||||
/* Remove the reference. */
|
||||
_thr_ref_delete(curthread, pthread);
|
||||
if (thread_return != NULL)
|
||||
*thread_return = tmp;
|
||||
}
|
||||
else if (pthread->joiner != NULL) {
|
||||
/* Unlock the thread and remove the reference. */
|
||||
|
@ -93,6 +93,7 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
|
||||
int prioceiling, int *old_ceiling)
|
||||
{
|
||||
int ret = 0;
|
||||
int tmp;
|
||||
|
||||
if ((mutex == NULL) || (*mutex == NULL))
|
||||
ret = EINVAL;
|
||||
@ -100,12 +101,15 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
|
||||
ret = EINVAL;
|
||||
/* Lock the mutex: */
|
||||
else if ((ret = pthread_mutex_lock(mutex)) == 0) {
|
||||
/* Return the old ceiling and set the new ceiling: */
|
||||
*old_ceiling = (*mutex)->m_prio;
|
||||
tmp = (*mutex)->m_prio;
|
||||
/* Set the new ceiling: */
|
||||
(*mutex)->m_prio = prioceiling;
|
||||
|
||||
/* Unlock the mutex: */
|
||||
ret = pthread_mutex_unlock(mutex);
|
||||
|
||||
/* Return the old ceiling: */
|
||||
*old_ceiling = tmp;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ int
|
||||
_sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sigaction gact;
|
||||
struct sigaction newact, oldact;
|
||||
struct pthread *curthread;
|
||||
kse_critical_t crit;
|
||||
kse_critical_t crit;
|
||||
|
||||
/* Check if the signal number is out of range: */
|
||||
if (sig < 1 || sig > _SIG_MAXSIG) {
|
||||
@ -55,6 +55,9 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
if (!_kse_isthreaded())
|
||||
return __sys_sigaction(sig, act, oact);
|
||||
|
||||
if (act)
|
||||
newact = *act;
|
||||
|
||||
crit = _kse_critical_enter();
|
||||
curthread = _get_curthread();
|
||||
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
|
||||
@ -64,17 +67,13 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
*/
|
||||
if (oact != NULL) {
|
||||
/* Return the existing signal action contents: */
|
||||
oact->sa_handler = _thread_sigact[sig - 1].sa_handler;
|
||||
oact->sa_mask = _thread_sigact[sig - 1].sa_mask;
|
||||
oact->sa_flags = _thread_sigact[sig - 1].sa_flags;
|
||||
oldact = _thread_sigact[sig - 1];
|
||||
}
|
||||
|
||||
/* Check if a signal action was supplied: */
|
||||
if (act != NULL) {
|
||||
/* Set the new signal handler: */
|
||||
_thread_sigact[sig - 1].sa_mask = act->sa_mask;
|
||||
_thread_sigact[sig - 1].sa_flags = act->sa_flags;
|
||||
_thread_sigact[sig - 1].sa_handler = act->sa_handler;
|
||||
_thread_sigact[sig - 1] = newact;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -82,30 +81,30 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
|
||||
* in signal action:
|
||||
*/
|
||||
if (act != NULL && sig != SIGINFO) {
|
||||
gact.sa_mask = act->sa_mask;
|
||||
gact.sa_flags = SA_SIGINFO | act->sa_flags;
|
||||
|
||||
newact.sa_flags |= SA_SIGINFO;
|
||||
|
||||
/*
|
||||
* Check if the signal handler is being set to
|
||||
* the default or ignore handlers:
|
||||
*/
|
||||
if (act->sa_handler == SIG_DFL ||
|
||||
act->sa_handler == SIG_IGN)
|
||||
/* Specify the built in handler: */
|
||||
gact.sa_handler = act->sa_handler;
|
||||
else
|
||||
if (newact.sa_handler != SIG_DFL &&
|
||||
newact.sa_handler != SIG_IGN) {
|
||||
/*
|
||||
* Specify the thread kernel signal
|
||||
* handler:
|
||||
*/
|
||||
gact.sa_handler = (void (*) ())_thr_sig_handler;
|
||||
|
||||
newact.sa_handler = (void (*) ())_thr_sig_handler;
|
||||
}
|
||||
/* Change the signal action in the kernel: */
|
||||
if (__sys_sigaction(sig, &gact, NULL) != 0)
|
||||
if (__sys_sigaction(sig, &newact, NULL) != 0)
|
||||
ret = -1;
|
||||
}
|
||||
KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
|
||||
_kse_critical_leave(crit);
|
||||
|
||||
if (oact != NULL)
|
||||
*oact = oldact;
|
||||
}
|
||||
|
||||
/* Return the completion status: */
|
||||
|
@ -46,16 +46,21 @@ int
|
||||
_pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
sigset_t oldset, newset;
|
||||
int ret;
|
||||
|
||||
if (! _kse_isthreaded())
|
||||
_kse_setthreaded(1);
|
||||
|
||||
if (set)
|
||||
newset = *set;
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
|
||||
ret = 0;
|
||||
if (oset != NULL)
|
||||
/* Return the current mask: */
|
||||
*oset = curthread->sigmask;
|
||||
oldset = curthread->sigmask;
|
||||
|
||||
/* Check if a new signal set was provided by the caller: */
|
||||
if (set != NULL) {
|
||||
@ -64,19 +69,19 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
/* Block signals: */
|
||||
case SIG_BLOCK:
|
||||
/* Add signals to the existing mask: */
|
||||
SIGSETOR(curthread->sigmask, *set);
|
||||
SIGSETOR(curthread->sigmask, newset);
|
||||
break;
|
||||
|
||||
/* Unblock signals: */
|
||||
case SIG_UNBLOCK:
|
||||
/* Clear signals from the existing mask: */
|
||||
SIGSETNAND(curthread->sigmask, *set);
|
||||
SIGSETNAND(curthread->sigmask, newset);
|
||||
break;
|
||||
|
||||
/* Set the signal process mask: */
|
||||
case SIG_SETMASK:
|
||||
/* Set the new mask: */
|
||||
curthread->sigmask = *set;
|
||||
curthread->sigmask = newset;
|
||||
break;
|
||||
|
||||
/* Trap invalid actions: */
|
||||
@ -96,5 +101,8 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
_thr_sig_check_pending(curthread);
|
||||
} else
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
if (ret == 0 && oset != NULL)
|
||||
*oset = oldset;
|
||||
return (ret);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ _sigpending(sigset_t *set)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
kse_critical_t crit;
|
||||
sigset_t sigset;
|
||||
int ret = 0;
|
||||
|
||||
/* Check for a null signal set pointer: */
|
||||
@ -59,12 +60,13 @@ _sigpending(sigset_t *set)
|
||||
|
||||
crit = _kse_critical_enter();
|
||||
KSE_SCHED_LOCK(curthread->kse, curthread->kseg);
|
||||
*set = curthread->sigpend;
|
||||
sigset = curthread->sigpend;
|
||||
KSE_SCHED_UNLOCK(curthread->kse, curthread->kseg);
|
||||
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock);
|
||||
SIGSETOR(*set, _thr_proc_sigpending);
|
||||
SIGSETOR(sigset, _thr_proc_sigpending);
|
||||
KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock);
|
||||
_kse_critical_leave(crit);
|
||||
*set = sigset;
|
||||
}
|
||||
/* Return the completion status: */
|
||||
return (ret);
|
||||
|
@ -43,20 +43,23 @@ int
|
||||
_sigsuspend(const sigset_t *set)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
sigset_t oldmask, newmask;
|
||||
int ret = -1;
|
||||
sigset_t osigmask;
|
||||
|
||||
if (!_kse_isthreaded())
|
||||
return __sys_sigsuspend(set);
|
||||
|
||||
/* Check if a new signal set was provided by the caller: */
|
||||
if (set != NULL) {
|
||||
newmask = *set;
|
||||
|
||||
THR_LOCK_SWITCH(curthread);
|
||||
|
||||
/* Save current sigmask */
|
||||
memcpy(&osigmask, &curthread->sigmask, sizeof(osigmask));
|
||||
memcpy(&oldmask, &curthread->sigmask, sizeof(sigset_t));
|
||||
|
||||
/* Change the caller's mask: */
|
||||
memcpy(&curthread->sigmask, set, sizeof(sigset_t));
|
||||
memcpy(&curthread->sigmask, &newmask, sizeof(sigset_t));
|
||||
|
||||
THR_SET_STATE(curthread, PS_SIGSUSPEND);
|
||||
|
||||
@ -68,7 +71,7 @@ _sigsuspend(const sigset_t *set)
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Restore the signal mask: */
|
||||
memcpy(&curthread->sigmask, &osigmask, sizeof(sigset_t));
|
||||
memcpy(&curthread->sigmask, &oldmask, sizeof(sigset_t));
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
/*
|
||||
* signal mask is reloaded, need to check if there is
|
||||
|
Loading…
x
Reference in New Issue
Block a user