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

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


The following commit(s) were added to refs/heads/master by this push:
     new ee39e7a4a20 sched/group: add spinlock in group_childstatus.c
ee39e7a4a20 is described below

commit ee39e7a4a2015a4121091ab30bc081829f650997
Author: hujun5 <[email protected]>
AuthorDate: Fri May 9 09:58:47 2025 +0800

    sched/group: add spinlock in group_childstatus.c
    
    Add spinlock protection to child task pool allocation and deallocation in
    group_childstatus.c. Protects g_child_pool freelist and group child list
    traversal/modification operations against concurrent access in SMP systems.
    
    Signed-off-by: hujun5 <[email protected]>
---
 sched/group/group_childstatus.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/sched/group/group_childstatus.c b/sched/group/group_childstatus.c
index 1485d9a81cb..b9ce8879b05 100644
--- a/sched/group/group_childstatus.c
+++ b/sched/group/group_childstatus.c
@@ -66,6 +66,7 @@ struct child_pool_s
  ****************************************************************************/
 
 static struct child_pool_s g_child_pool;
+static spinlock_t g_child_pool_lock = SP_UNLOCKED;
 
 /****************************************************************************
  * Private Functions
@@ -169,17 +170,21 @@ void task_initialize(void)
 FAR struct child_status_s *group_alloc_child(void)
 {
   FAR struct child_status_s *ret;
+  irqstate_t flags;
 
   /* Return the status block at the head of the free list */
 
+  flags = spin_lock_irqsave(&g_child_pool_lock);
   ret = g_child_pool.freelist;
   if (ret)
     {
       g_child_pool.freelist = ret->flink;
       ret->flink            = NULL;
+      spin_unlock_irqrestore(&g_child_pool_lock, flags);
     }
   else
     {
+      spin_unlock_irqrestore(&g_child_pool_lock, flags);
       ret = kmm_zalloc(sizeof(*ret));
     }
 
@@ -206,12 +211,16 @@ FAR struct child_status_s *group_alloc_child(void)
 
 void group_free_child(FAR struct child_status_s *child)
 {
+  irqstate_t flags;
+
   /* Return the child status structure to the free list  */
 
   if (child)
     {
+      flags = spin_lock_irqsave(&g_child_pool_lock);
       child->flink          = g_child_pool.freelist;
       g_child_pool.freelist = child;
+      spin_unlock_irqrestore(&g_child_pool_lock, flags);
     }
 }
 
@@ -271,19 +280,23 @@ FAR struct child_status_s *group_find_child(FAR struct 
task_group_s *group,
                                             pid_t pid)
 {
   FAR struct child_status_s *child;
+  irqstate_t flags;
 
   DEBUGASSERT(group);
 
   /* Find the status structure with the matching PID  */
 
+  flags = spin_lock_irqsave(&group->tg_lock);
   for (child = group->tg_children; child; child = child->flink)
     {
       if (child->ch_pid == pid)
         {
+          spin_unlock_irqrestore(&group->tg_lock, flags);
           return child;
         }
     }
 
+  spin_unlock_irqrestore(&group->tg_lock, flags);
   return NULL;
 }
 
@@ -309,17 +322,21 @@ FAR struct child_status_s *group_find_child(FAR struct 
task_group_s *group,
 FAR struct child_status_s *group_exit_child(FAR struct task_group_s *group)
 {
   FAR struct child_status_s *child;
+  irqstate_t flags;
 
   /* Find the status structure of any child task that has exited. */
 
+  flags = spin_lock_irqsave(&group->tg_lock);
   for (child = group->tg_children; child; child = child->flink)
     {
       if ((child->ch_flags & CHILD_FLAG_EXITED) != 0)
         {
+          spin_unlock_irqrestore(&group->tg_lock, flags);
           return child;
         }
     }
 
+  spin_unlock_irqrestore(&group->tg_lock, flags);
   return NULL;
 }
 
@@ -350,11 +367,13 @@ FAR struct child_status_s *group_remove_child(FAR struct 
task_group_s *group,
 {
   FAR struct child_status_s *curr;
   FAR struct child_status_s *prev;
+  irqstate_t flags;
 
   DEBUGASSERT(group);
 
   /* Find the status structure with the matching PID */
 
+  flags = spin_lock_irqsave(&group->tg_lock);
   for (prev = NULL, curr = group->tg_children;
        curr;
        prev = curr, curr = curr->flink)
@@ -381,9 +400,12 @@ FAR struct child_status_s *group_remove_child(FAR struct 
task_group_s *group,
         }
 
       curr->flink = NULL;
+      spin_unlock_irqrestore(&group->tg_lock, flags);
       group_dump_children(group, "group_remove_child");
+      return curr;
     }
 
+  spin_unlock_irqrestore(&group->tg_lock, flags);
   return curr;
 }
 
@@ -409,11 +431,13 @@ void group_remove_children(FAR struct task_group_s *group)
 {
   FAR struct child_status_s *curr;
   FAR struct child_status_s *next;
+  irqstate_t flags;
 
   /* Remove all child structures for the TCB and return them to the
    * freelist.
    */
 
+  flags = spin_lock_irqsave(&group->tg_lock);
   for (curr = group->tg_children; curr; curr = next)
     {
       next = curr->flink;
@@ -421,6 +445,8 @@ void group_remove_children(FAR struct task_group_s *group)
     }
 
   group->tg_children = NULL;
+  spin_unlock_irqrestore(&group->tg_lock, flags);
+
   group_dump_children(group, "group_remove_children");
 }
 

Reply via email to