From 2b4002d9add83ebab041ef6dbe76576fd436f853 Mon Sep 17 00:00:00 2001
From: chao an <anchao@lixiang.com>
Date: Thu, 14 Mar 2024 17:35:30 +0800
Subject: [PATCH] sched/signal: move unblock signal info to stack

struct tcb_s will reduce by 24 bytes

Signed-off-by: chao an <anchao@lixiang.com>
---
 include/nuttx/sched.h        |  2 +-
 sched/signal/sig_dispatch.c  |  4 +--
 sched/signal/sig_timedwait.c | 48 +++++++++++++++++-------------------
 3 files changed, 26 insertions(+), 28 deletions(-)

diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 16db2f11bb..a024bac498 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 e261b52b3c..7f2785acf5 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 c75eaf8eda..d14daefe9f 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);
     }