This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7a5d3334544c38d8f45070d7b8f3c6a7c8a2a812
Author: hujun5 <[email protected]>
AuthorDate: Wed Jan 28 18:52:24 2026 +0800

    sched_waitid.c: HIS_metric_violation: CCM
    
    Extract the core waitid logic into a separate waittcb() helper function to 
reduce the
    cyclomatic complexity of the main waitid() function. This improves code 
maintainability,
    reduces nested conditions, and enhances code clarity while preserving all 
functionality.
    
    Signed-off-by: hujun5 <[email protected]>
---
 sched/sched/sched_waitid.c | 354 +++++++++++++++++++++++----------------------
 1 file changed, 184 insertions(+), 170 deletions(-)

diff --git a/sched/sched/sched_waitid.c b/sched/sched/sched_waitid.c
index 530f2537f7e..81955e44d15 100644
--- a/sched/sched/sched_waitid.c
+++ b/sched/sched/sched_waitid.c
@@ -79,183 +79,21 @@ static void exited_child(FAR struct tcb_s *rtcb,
 }
 #endif
 
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: waitid
- *
- * Description:
- *   The waitid() function suspends the calling thread until one child of
- *   the process containing the calling thread changes state. It records the
- *   current state of a child in the structure pointed to by 'info'. If a
- *   child process changed state prior to the call to waitid(), waitid()
- *   returns immediately. If more than one thread is suspended in wait() or
- *   waitpid() waiting termination of the same process, exactly one thread
- *   will return the process status at the time of the target process
- *   termination
- *
- *   The idtype and id arguments are used to specify which children waitid()
- *   will wait for.
- *
- *     If idtype is P_PID, waitid() will wait for the child with a process
- *     ID equal to (pid_t)id.
- *
- *     If idtype is P_PGID, waitid() will wait for any child with a process
- *     group ID equal to (pid_t)id.
- *
- *     If idtype is P_ALL, waitid() will wait for any children and id is
- *     ignored.
- *
- *   The options argument is used to specify which state changes waitid()
- *   will will wait for. It is formed by OR-ing together one or more of the
- *   following flags:
- *
- *     WEXITED - Wait for processes that have exited.
- *     WSTOPPED - Status will be returned for any child that has stopped
- *       upon receipt of a signal.
- *     WCONTINUED - Status will be returned for any child that was stopped
- *       and has been continued.
- *     WNOHANG - Return immediately if there are no children to wait for.
- *     WNOWAIT - Keep the process whose status is returned in 'info' in a
- *       waitable state. This will not affect the state of the process; the
- *       process may be waited for again after this call completes.
- *
- *   The 'info' argument must point to a siginfo_t structure. If waitid()
- *   returns because a child process was found that satisfied the conditions
- *   indicated by the arguments idtype and options, then the structure
- *   pointed to by 'info' will be filled in by the system with the status of
- *   the process. The si_signo member will always be equal to SIGCHLD.
- *
- * Input Parameters:
- *   See description.
- *
- * Returned Value:
- *   If waitid() returns due to the change of state of one of its children,
- *   0 is returned. Otherwise, -1 is returned and errno is set to indicate
- *   the error.
- *
- *   The waitid() function will fail if:
- *
- *     ECHILD - The calling process has no existing unwaited-for child
- *       processes.
- *     EINTR - The waitid() function was interrupted by a signal.
- *     EINVAL - An invalid value was specified for options, or idtype and id
- *       specify an invalid set of processes.
- *
- ****************************************************************************/
-
-int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
+static inline_function
+int waittcb(FAR struct tcb_s *rtcb, idtype_t idtype, int options,
+            id_t id, FAR siginfo_t *info, bool retains)
 {
-  FAR struct tcb_s *rtcb = this_task();
-  FAR struct tcb_s *ctcb;
 #ifdef CONFIG_SCHED_CHILD_STATUS
   FAR struct child_status_s *child;
-  bool retains;
 #endif
-  irqstate_t flags;
+  int errcode = OK;
   sigset_t set;
-  int errcode = ENOSYS;
   int ret;
 
-  /* waitid() is a cancellation point */
-
-  enter_cancellation_point();
-
-  flags = enter_critical_section();
-
-  /* MISSING LOGIC:   If WNOHANG is provided in the options, then this
-   * function should returned immediately.  However, there is no mechanism
-   * available now know if the thread has child:  The children remember
-   * their parents (if CONFIG_SCHED_HAVE_PARENT) but the parents do not
-   * remember their children.
-   */
-
-#ifdef CONFIG_DEBUG_FEATURES
-  /* Only ID types P_PID and P_ALL are supported */
-
-  if ((idtype == P_PID || idtype == P_ALL) &&
-      (options & WEXITED) != 0 &&
-      (options & ~(WEXITED | WNOHANG)) == 0)
-#endif
-    {
-      /* Create a signal set that contains only SIGCHLD */
-
-      sigemptyset(&set);
-      nxsig_addset(&set, SIGCHLD);
-      errcode = OK;
-
-      /* Verify that this task actually has children and that the requested
-       * TCB is actually a child of this task.
-       */
-
-#ifdef CONFIG_SCHED_CHILD_STATUS
-      /* Does this task retain child status? */
+  /* Create a signal set that contains only SIGCHLD */
 
-      retains = ((rtcb->group->tg_flags & GROUP_FLAG_NOCLDWAIT) == 0);
-
-      if (rtcb->group->tg_children == NULL && retains)
-        {
-          /* There are no children */
-
-          errcode = ECHILD;
-        }
-      else if (idtype == P_PID)
-        {
-          /* Get the TCB corresponding to this PID and make sure that the
-           * thread it is our child.
-           */
-
-          ctcb = nxsched_get_tcb((pid_t)id);
-          if (ctcb && ctcb->group)
-            {
-              /* Make sure that the thread it is our child. */
-
-              if (ctcb->group->tg_ppid != rtcb->pid)
-                {
-                  errcode = ECHILD;
-                }
-            }
-
-          /* Does this task retain child status? */
-
-          if (retains && errcode == OK)
-            {
-              /* Check if this specific pid has allocated child status? */
-
-              if (group_find_child(rtcb->group, (pid_t)id) == NULL)
-                {
-                  /* This specific pid is not a child */
-
-                  errcode = ECHILD;
-                }
-            }
-        }
-#else
-      /* Child status is not retained. */
-
-      if (rtcb->group->tg_nchildren == 0)
-        {
-          /* There are no children */
-
-          errcode = ECHILD;
-        }
-      else if (idtype == P_PID)
-        {
-          /* Get the TCB corresponding to this PID and make sure that the
-           * thread is our child.
-           */
-
-          ctcb = nxsched_get_tcb((pid_t)id);
-
-          if (!ctcb || !ctcb->group || ctcb->group->tg_ppid != rtcb->pid)
-            {
-              errcode = ECHILD;
-            }
-        }
-#endif
-    }
+  sigemptyset(&set);
+  nxsig_addset(&set, SIGCHLD);
 
   /* Loop until the child that we are waiting for dies */
 
@@ -435,8 +273,184 @@ int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, 
int options)
         }
     }
 
-  leave_critical_section(flags);
+  return errcode;
+}
 
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: waitid
+ *
+ * Description:
+ *   The waitid() function suspends the calling thread until one child of
+ *   the process containing the calling thread changes state. It records the
+ *   current state of a child in the structure pointed to by 'info'. If a
+ *   child process changed state prior to the call to waitid(), waitid()
+ *   returns immediately. If more than one thread is suspended in wait() or
+ *   waitpid() waiting termination of the same process, exactly one thread
+ *   will return the process status at the time of the target process
+ *   termination
+ *
+ *   The idtype and id arguments are used to specify which children waitid()
+ *   will wait for.
+ *
+ *     If idtype is P_PID, waitid() will wait for the child with a process
+ *     ID equal to (pid_t)id.
+ *
+ *     If idtype is P_PGID, waitid() will wait for any child with a process
+ *     group ID equal to (pid_t)id.
+ *
+ *     If idtype is P_ALL, waitid() will wait for any children and id is
+ *     ignored.
+ *
+ *   The options argument is used to specify which state changes waitid()
+ *   will will wait for. It is formed by OR-ing together one or more of the
+ *   following flags:
+ *
+ *     WEXITED - Wait for processes that have exited.
+ *     WSTOPPED - Status will be returned for any child that has stopped
+ *       upon receipt of a signal.
+ *     WCONTINUED - Status will be returned for any child that was stopped
+ *       and has been continued.
+ *     WNOHANG - Return immediately if there are no children to wait for.
+ *     WNOWAIT - Keep the process whose status is returned in 'info' in a
+ *       waitable state. This will not affect the state of the process; the
+ *       process may be waited for again after this call completes.
+ *
+ *   The 'info' argument must point to a siginfo_t structure. If waitid()
+ *   returns because a child process was found that satisfied the conditions
+ *   indicated by the arguments idtype and options, then the structure
+ *   pointed to by 'info' will be filled in by the system with the status of
+ *   the process. The si_signo member will always be equal to SIGCHLD.
+ *
+ * Input Parameters:
+ *   See description.
+ *
+ * Returned Value:
+ *   If waitid() returns due to the change of state of one of its children,
+ *   0 is returned. Otherwise, -1 is returned and errno is set to indicate
+ *   the error.
+ *
+ *   The waitid() function will fail if:
+ *
+ *     ECHILD - The calling process has no existing unwaited-for child
+ *       processes.
+ *     EINTR - The waitid() function was interrupted by a signal.
+ *     EINVAL - An invalid value was specified for options, or idtype and id
+ *       specify an invalid set of processes.
+ *
+ ****************************************************************************/
+
+int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options)
+{
+  FAR struct tcb_s *rtcb = this_task();
+  FAR struct tcb_s *ctcb;
+  bool retains = false;
+  int errcode = ENOSYS;
+  irqstate_t flags;
+  int ret;
+
+  /* waitid() is a cancellation point */
+
+  enter_cancellation_point();
+  flags = enter_critical_section();
+
+  /* MISSING LOGIC:   If WNOHANG is provided in the options, then this
+   * function should returned immediately.  However, there is no mechanism
+   * available now know if the thread has child:  The children remember
+   * their parents (if CONFIG_SCHED_HAVE_PARENT) but the parents do not
+   * remember their children.
+   */
+
+#ifdef CONFIG_DEBUG_FEATURES
+  /* Only ID types P_PID and P_ALL are supported */
+
+  if ((idtype == P_PID || idtype == P_ALL) &&
+      (options & WEXITED) != 0 &&
+      (options & ~(WEXITED | WNOHANG)) == 0)
+#endif
+    {
+      errcode = OK;
+
+      /* Verify that this task actually has children and that the requested
+       * TCB is actually a child of this task.
+       */
+
+#ifdef CONFIG_SCHED_CHILD_STATUS
+      /* Does this task retain child status? */
+
+      retains = ((rtcb->group->tg_flags & GROUP_FLAG_NOCLDWAIT) == 0);
+
+      if (rtcb->group->tg_children == NULL && retains)
+        {
+          /* There are no children */
+
+          errcode = ECHILD;
+        }
+      else if (idtype == P_PID)
+        {
+          /* Get the TCB corresponding to this PID and make sure that the
+           * thread it is our child.
+           */
+
+          ctcb = nxsched_get_tcb((pid_t)id);
+          if (ctcb && ctcb->group)
+            {
+              /* Make sure that the thread it is our child. */
+
+              if (ctcb->group->tg_ppid != rtcb->pid)
+                {
+                  errcode = ECHILD;
+                }
+            }
+
+          /* Does this task retain child status? */
+
+          if (retains && errcode == OK)
+            {
+              /* Check if this specific pid has allocated child status? */
+
+              if (group_find_child(rtcb->group, (pid_t)id) == NULL)
+                {
+                  /* This specific pid is not a child */
+
+                  errcode = ECHILD;
+                }
+            }
+        }
+#else
+      /* Child status is not retained. */
+
+      if (rtcb->group->tg_nchildren == 0)
+        {
+          /* There are no children */
+
+          errcode = ECHILD;
+        }
+      else if (idtype == P_PID)
+        {
+          /* Get the TCB corresponding to this PID and make sure that the
+           * thread is our child.
+           */
+
+          ctcb = nxsched_get_tcb((pid_t)id);
+
+          if (!ctcb || !ctcb->group || ctcb->group->tg_ppid != rtcb->pid)
+            {
+              errcode = ECHILD;
+            }
+        }
+#endif
+    }
+
+  if (errcode == OK)
+    {
+      errcode = waittcb(rtcb, idtype, options, id, info, retains);
+    }
+
+  leave_critical_section(flags);
   leave_cancellation_point();
   if (errcode != OK)
     {

Reply via email to