From 340a72b7cdfb3c1c79044f53decc055ee6c06f19 Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 23 Jan 2013 22:23:46 +0000 Subject: Add logic to retain child task exit status if so configured git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5553 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/sched/task_childstatus.c | 125 +++++++++++++++++++++++++---------------- 1 file changed, 78 insertions(+), 47 deletions(-) (limited to 'nuttx/sched/task_childstatus.c') diff --git a/nuttx/sched/task_childstatus.c b/nuttx/sched/task_childstatus.c index ab5ace43a..0f6d36c29 100644 --- a/nuttx/sched/task_childstatus.c +++ b/nuttx/sched/task_childstatus.c @@ -39,24 +39,44 @@ #include +#include #include +#include #include "os_internal.h" #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) /***************************************************************************** - * Private Types + * Pre-processor Definitions *****************************************************************************/ -/* Globals are maintained in a structure to minimize name collisions. Note - * that there cannot be more that CONFIG_MAX_TASKS tasks in total. So using - * CONFIG_MAX_TASKS should be sufficient (at least one task, the IDLE thread, - * will have no parent). +/* Note that there cannot be more that CONFIG_MAX_TASKS tasks in total. + * However, the number of child status structures may need to be significantly + * larger because this number includes the maximum number of tasks that are + * running PLUS the number of tasks that have exit'ed without having their + * exit status reaped (via wait(), waitid(), or waitpid()). + * + * Obviously, if tasks spawn children indefinitely and never have the exit + * status reaped, then you have a memory leak! */ +#if !defined(CONFIG_PREALLOC_CHILDSTATUS) || CONFIG_PREALLOC_CHILDSTATUS == 0 +# undef CONFIG_PREALLOC_CHILDSTATUS +# define CONFIG_PREALLOC_CHILDSTATUS (2*CONFIG_MAX_TASKS) +#endif + +#ifndef CONFIG_DEBUG +# undef CONFIG_DEBUG_CHILDSTATUS +#endif + +/***************************************************************************** + * Private Types + *****************************************************************************/ +/* Globals are maintained in a structure to minimize name collisions. */ + struct child_pool_s { - struct child_status_s alloc[CONFIG_MAX_TASKS]; + struct child_status_s alloc[CONFIG_PREALLOC_CHILDSTATUS]; FAR struct child_status_s *freelist; }; @@ -70,6 +90,40 @@ static struct child_pool_s g_child_pool; * Private Functions *****************************************************************************/ +/***************************************************************************** + * Name: task_dumpchildren + * + * Description: + * Dump all of the children when the part TCB list is modified. + * + * Parameters: + * tcb - The parent TCB. + * + * Return Value: + * None. + * + * Assumptions: + * Called early in initialization. No special precautions are required. + * + *****************************************************************************/ + +#ifdef CONFIG_DEBUG_CHILDSTATUS +static void task_dumpchildren(FAR _TCB *tcb, FAR const char *msg) +{ + FAR struct child_status_s *child; + int i; + + dbg("Parent TCB=%p: %s\n", tcb, msg); + for (i = 0, child = tcb->children; child; i++, child = child->flink) + { + dbg(" %d. ch_flags=%02x ch_pid=%d ch_status=%d\n", + i, child->ch_flags, child->ch_pid, child->ch_status); + } +} +#else +# task_dumpchildren(t,m) +#endif + /***************************************************************************** * Public Functions *****************************************************************************/ @@ -88,7 +142,7 @@ static struct child_pool_s g_child_pool; * None. * * Assumptions: - * Called early in initializatin. No special precautions are required. + * Called early in initialization. No special precautions are required. * *****************************************************************************/ @@ -102,11 +156,11 @@ void task_initialize(void) prev = &g_child_pool.alloc[0]; g_child_pool.freelist = prev; - for (i = 0; i < CONFIG_MAX_TASKS; i++) + for (i = 0; i < CONFIG_PREALLOC_CHILDSTATUS; i++) { - curr = &g_child_pool.alloc[i] + curr = &g_child_pool.alloc[i]; prev->flink = curr; - prev = curr; + prev = curr; } } @@ -140,7 +194,7 @@ FAR struct child_status_s *task_allocchild(void) if (ret) { g_child_pool.freelist = ret->flink; - ret->flink = NULL; + ret->flink = NULL; } return ret; @@ -170,7 +224,7 @@ void task_freechild(FAR struct child_status_s *child) if (child) { - child->flink = g_child_pool.freelist; + child->flink = g_child_pool.freelist; g_child_pool.freelist = child; } } @@ -179,18 +233,14 @@ void task_freechild(FAR struct child_status_s *child) * Name: task_addchild * * Description: - * Find a child status structure in the given TCB. + * Add a child status structure in the given TCB. * * Parameters: * tcb - The TCB of the parent task to containing the child status. - * pid - The ID of the child to create - * status - Child exit status (should be zero) - * flags - Child flags (see CHILD_FLAGS_* defininitions) + * child - The structure to be added * * Return Value: - * On success, a non-NULL pointer to a child status structure. NULL is - * returned if (1) there are no free status structures, or (2) an entry - * with this PID already exists. + * N * * Assumptions: * Called during task creation processing in a safe context. No special @@ -198,37 +248,14 @@ void task_freechild(FAR struct child_status_s *child) * *****************************************************************************/ -FAR struct child_status_s *task_addchild(FAR _TCB *tcb, pid_t pid, int status, - uint8_t flags) +void task_addchild(FAR _TCB *tcb, FAR struct child_status_s *child) { - FAR struct child_status_s *child; + /* Add the entry into the TCB list of children */ - /* Make sure that there is not already a structure for this PID */ + child->flink = tcb->children; + tcb->children = child; - child = task_findchild(tcb, pid); - if (child) - { - return NULL; - } - - /* Allocate a new status structure */ - - child = task_allocchild(void); - if (child) - { - /* Initialize the structure */ - - child->ch_flags = flags; - child->ch_pid = pid; - child->ch_status = status; - - /* Add the entry into the TCB list of children */ - - status->flink = tcb->children; - tcb->childen = status; - } - - return child; + task_dumpchildren(tcb, "task_addchild"); } /***************************************************************************** @@ -325,6 +352,7 @@ FAR struct child_status_s *task_removechild(FAR _TCB *tcb, pid_t pid) } curr->flink = NULL; + task_dumpchildren(tcb, "task_removechild"); } return curr; @@ -360,6 +388,9 @@ void task_removechildren(FAR _TCB *tcb) next = curr->flink; task_freechild(curr); } + + tcb->children = NULL; + task_dumpchildren(tcb, "task_removechildren"); } #endif /* CONFIG_SCHED_HAVE_PARENT && CONFIG_SCHED_CHILD_STATUS */ -- cgit v1.2.3