diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 16db2f11bb2..a024bac4988 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -628,7 +628,7 @@ struct tcb_s sigset_t sigwaitmask; /* Waiting for pending signals */ sq_queue_t sigpendactionq; /* List of pending signal actions */ sq_queue_t sigpostedq; /* List of posted signals */ - siginfo_t sigunbinfo; /* Signal info when task unblocked */ + siginfo_t *sigunbinfo; /* Signal info when task unblocked */ /* Robust mutex support ***************************************************/ diff --git a/sched/signal/sig_dispatch.c b/sched/signal/sig_dispatch.c index e261b52b3c9..7f2785acf5d 100644 --- a/sched/signal/sig_dispatch.c +++ b/sched/signal/sig_dispatch.c @@ -398,7 +398,7 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) (masked == 0 || nxsig_ismember(&stcb->sigwaitmask, info->si_signo))) { - memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); + memcpy(stcb->sigunbinfo, info, sizeof(siginfo_t)); sigemptyset(&stcb->sigwaitmask); if (WDOG_ISACTIVE(&stcb->waitdog)) @@ -461,7 +461,7 @@ int nxsig_tcbdispatch(FAR struct tcb_s *stcb, siginfo_t *info) if (stcb->task_state == TSTATE_WAIT_SIG) { - memcpy(&stcb->sigunbinfo, info, sizeof(siginfo_t)); + memcpy(stcb->sigunbinfo, info, sizeof(siginfo_t)); sigemptyset(&stcb->sigwaitmask); if (WDOG_ISACTIVE(&stcb->waitdog)) diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index c75eaf8eda8..d14daefe9fe 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -99,13 +99,13 @@ static void nxsig_timeout(wdparm_t arg) { FAR struct tcb_s *rtcb = this_task(); - wtcb->sigunbinfo.si_signo = SIG_WAIT_TIMEOUT; - wtcb->sigunbinfo.si_code = SI_TIMER; - wtcb->sigunbinfo.si_errno = ETIMEDOUT; - wtcb->sigunbinfo.si_value.sival_int = 0; + wtcb->sigunbinfo->si_signo = SIG_WAIT_TIMEOUT; + wtcb->sigunbinfo->si_code = SI_TIMER; + wtcb->sigunbinfo->si_errno = ETIMEDOUT; + wtcb->sigunbinfo->si_value.sival_int = 0; #ifdef CONFIG_SCHED_HAVE_PARENT - wtcb->sigunbinfo.si_pid = 0; /* Not applicable */ - wtcb->sigunbinfo.si_status = OK; + wtcb->sigunbinfo->si_pid = 0; /* Not applicable */ + wtcb->sigunbinfo->si_status = OK; #endif /* Remove the task from waitting list */ @@ -166,13 +166,13 @@ void nxsig_wait_irq(FAR struct tcb_s *wtcb, int errcode) { FAR struct tcb_s *rtcb = this_task(); - wtcb->sigunbinfo.si_signo = SIG_CANCEL_TIMEOUT; - wtcb->sigunbinfo.si_code = SI_USER; - wtcb->sigunbinfo.si_errno = errcode; - wtcb->sigunbinfo.si_value.sival_int = 0; + wtcb->sigunbinfo->si_signo = SIG_CANCEL_TIMEOUT; + wtcb->sigunbinfo->si_code = SI_USER; + wtcb->sigunbinfo->si_errno = errcode; + wtcb->sigunbinfo->si_value.sival_int = 0; #ifdef CONFIG_SCHED_HAVE_PARENT - wtcb->sigunbinfo.si_pid = 0; /* Not applicable */ - wtcb->sigunbinfo.si_status = OK; + wtcb->sigunbinfo->si_pid = 0; /* Not applicable */ + wtcb->sigunbinfo->si_status = OK; #endif /* Remove the task from waitting list */ @@ -244,6 +244,7 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, irqstate_t flags; sclock_t waitticks; bool switch_needed; + siginfo_t sinfo; int ret; DEBUGASSERT(set != NULL); @@ -311,6 +312,8 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, } #endif + rtcb->sigunbinfo = (info == NULL) ? &sinfo : info; + /* Check if we should wait for the timeout */ if (timeout != NULL) @@ -418,26 +421,19 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, * or timeout) that awakened us. */ - if (GOOD_SIGNO(rtcb->sigunbinfo.si_signo)) + if (GOOD_SIGNO(rtcb->sigunbinfo->si_signo)) { /* We were awakened by a signal... but is it one of the signals * that we were waiting for? */ - if (nxsig_ismember(set, rtcb->sigunbinfo.si_signo)) + if (nxsig_ismember(set, rtcb->sigunbinfo->si_signo)) { - /* Return the signal info to the caller if so requested */ - - if (info != NULL) - { - memcpy(info, &rtcb->sigunbinfo, sizeof(struct siginfo)); - } - /* Yes.. the return value is the number of the signal that * awakened us. */ - ret = rtcb->sigunbinfo.si_signo; + ret = rtcb->sigunbinfo->si_signo; } else { @@ -453,11 +449,11 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, */ #ifdef CONFIG_CANCELLATION_POINTS - if (rtcb->sigunbinfo.si_signo == SIG_CANCEL_TIMEOUT) + if (rtcb->sigunbinfo->si_signo == SIG_CANCEL_TIMEOUT) { /* The wait was canceled */ - ret = -rtcb->sigunbinfo.si_errno; + ret = -rtcb->sigunbinfo->si_errno; DEBUGASSERT(ret < 0); } else @@ -467,11 +463,13 @@ int nxsig_timedwait(FAR const sigset_t *set, FAR struct siginfo *info, * error. */ - DEBUGASSERT(rtcb->sigunbinfo.si_signo == SIG_WAIT_TIMEOUT); + DEBUGASSERT(rtcb->sigunbinfo->si_signo == SIG_WAIT_TIMEOUT); ret = -EAGAIN; } } + rtcb->sigunbinfo = NULL; + leave_critical_section(flags); }