diff --git a/include/nuttx/mm/map.h b/include/nuttx/mm/map.h index 53c45c26b1..f447d943f3 100644 --- a/include/nuttx/mm/map.h +++ b/include/nuttx/mm/map.h @@ -125,7 +125,7 @@ void mm_map_unlock(void); * Name: mm_map_initialize * * Description: - * Initialization function, called only by group_initialize + * Initialization function, called only by group_postinitialize * * Input Parameters: * mm - Pointer to the mm_map structure to be initialized diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 879619874d..35c7a1b5bb 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -680,6 +680,10 @@ struct task_tcb_s struct tcb_s cmn; /* Common TCB fields */ + /* Task Group *************************************************************/ + + struct task_group_s group; /* Pointer to shared task group data */ + /* Task Management Fields *************************************************/ #ifdef CONFIG_SCHED_STARTHOOK diff --git a/sched/group/group.h b/sched/group/group.h index cfb3436808..484239d82c 100644 --- a/sched/group/group.h +++ b/sched/group/group.h @@ -56,8 +56,8 @@ void task_initialize(void); /* Task group data structure management */ -int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype); -void group_initialize(FAR struct task_tcb_s *tcb); +int group_initialize(FAR struct task_tcb_s *tcb, uint8_t ttype); +void group_postinitialize(FAR struct task_tcb_s *tcb); #ifndef CONFIG_DISABLE_PTHREAD int group_bind(FAR struct pthread_tcb_s *tcb); int group_join(FAR struct pthread_tcb_s *tcb); diff --git a/sched/group/group_create.c b/sched/group/group_create.c index 01262d64bf..75324aba7e 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -88,7 +88,7 @@ static inline void group_inherit_identity(FAR struct task_group_s *group) ****************************************************************************/ /**************************************************************************** - * Name: group_allocate + * Name: group_initialize * * Description: * Create and a new task group structure for the specified TCB. This @@ -96,8 +96,8 @@ static inline void group_inherit_identity(FAR struct task_group_s *group) * allocated and zeroed, but otherwise uninitialized. The full creation * of the group of a two step process: (1) First, this function allocates * group structure early in the task creation sequence in order to provide - * a group container, then (2) group_initialize() is called to set up the - * group membership. + * a group container, then (2) group_postinitialize() is called to set up + * the group membership. * * Input Parameters: * tcb - The tcb in need of the task group. @@ -112,7 +112,7 @@ static inline void group_inherit_identity(FAR struct task_group_s *group) * ****************************************************************************/ -int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) +int group_initialize(FAR struct task_tcb_s *tcb, uint8_t ttype) { FAR struct task_group_s *group; int ret; @@ -121,11 +121,7 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) /* Allocate the group structure and assign it to the TCB */ - group = kmm_zalloc(sizeof(struct task_group_s)); - if (!group) - { - return -ENOMEM; - } + group = &tcb->group; #if defined(CONFIG_MM_KERNEL_HEAP) /* If this group is being created for a privileged thread, then all @@ -161,7 +157,7 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) ret = task_init_info(group); if (ret < 0) { - goto errout_with_group; + return ret; } #ifndef CONFIG_DISABLE_PTHREAD @@ -177,20 +173,17 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) #endif return OK; - -errout_with_group: - kmm_free(group); - return ret; } /**************************************************************************** - * Name: group_initialize + * Name: group_postinitialize * * Description: * Add the task as the initial member of the group. The full creation of * the group of a two step process: (1) First, this group structure is - * allocated by group_allocate() early in the task creation sequence, then - * (2) this function is called to set up the initial group membership. + * allocated by group_initialize() early in the task creation sequence, + * then (2) this function is called to set up the initial group + * membership. * * Input Parameters: * tcb - The tcb in need of the task group. @@ -204,7 +197,7 @@ errout_with_group: * ****************************************************************************/ -void group_initialize(FAR struct task_tcb_s *tcb) +void group_postinitialize(FAR struct task_tcb_s *tcb) { FAR struct task_group_s *group; diff --git a/sched/group/group_foreachchild.c b/sched/group/group_foreachchild.c index 827b53a651..1fd38bac3b 100644 --- a/sched/group/group_foreachchild.c +++ b/sched/group/group_foreachchild.c @@ -62,7 +62,7 @@ int group_foreachchild(FAR struct task_group_s *group, { FAR sq_entry_t *curr; FAR sq_entry_t *next; - int ret; + int ret = OK; DEBUGASSERT(group); diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c index 04d4134aac..b4bde70463 100644 --- a/sched/group/group_leave.c +++ b/sched/group/group_leave.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -67,7 +68,8 @@ * ****************************************************************************/ -static inline void group_release(FAR struct task_group_s *group) +static inline void +group_release(FAR struct task_group_s *group, uint8_t ttype) { task_uninit_info(group); @@ -124,7 +126,12 @@ static inline void group_release(FAR struct task_group_s *group) /* Then drop the group freeing the allocated memory */ - group_drop(group); +#ifndef CONFIG_DISABLE_PTHREAD + if (ttype == TCB_FLAG_TTYPE_PTHREAD) + { + group_drop(group); + } +#endif } /**************************************************************************** @@ -166,6 +173,12 @@ void group_leave(FAR struct tcb_s *tcb) group = tcb->group; if (group) { + /* In any event, we can detach the group from the TCB so that we won't + * do this again. + */ + + tcb->group = NULL; + /* Remove the member from group. */ #ifdef HAVE_GROUP_MEMBERS @@ -180,14 +193,8 @@ void group_leave(FAR struct tcb_s *tcb) { /* Yes.. Release all of the resource held by the task group */ - group_release(group); + group_release(group, tcb->flags & TCB_FLAG_TTYPE_MASK); } - - /* In any event, we can detach the group from the TCB so that we won't - * do this again. - */ - - tcb->group = NULL; } } @@ -214,6 +221,8 @@ void group_leave(FAR struct tcb_s *tcb) void group_drop(FAR struct task_group_s *group) { + FAR struct task_tcb_s *tcb; + #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) /* If there are threads waiting for this group to be freed, then we cannot * yet free the memory resources. Instead just mark the group deleted @@ -228,13 +237,17 @@ void group_drop(FAR struct task_group_s *group) } else #endif - /* Finally, if no one needs the group and it has been deleted, remove it */ if (group->tg_flags & GROUP_FLAG_DELETED) { + tcb = container_of(group, struct task_tcb_s, group); + /* Release the group container itself */ - kmm_free(group); + if (tcb->cmn.flags & TCB_FLAG_FREE_TCB) + { + kmm_free(tcb); + } } } diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index d45bb35300..93be286898 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -516,7 +516,7 @@ void nx_start(void) /* Allocate the IDLE group */ - DEBUGVERIFY(group_allocate(&g_idletcb[i], g_idletcb[i].cmn.flags)); + DEBUGVERIFY(group_initialize(&g_idletcb[i], g_idletcb[i].cmn.flags)); g_idletcb[i].cmn.group->tg_info->ta_argv = &g_idleargv[i][0]; #ifdef CONFIG_SMP @@ -543,7 +543,7 @@ void nx_start(void) * of child status in the IDLE group. */ - group_initialize(&g_idletcb[i]); + group_postinitialize(&g_idletcb[i]); g_idletcb[i].cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT | GROUP_FLAG_PRIVILEGED; } diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index 8728e8d90a..3edfff06aa 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -208,8 +208,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, /* Allocate a TCB for the new task. */ - ptcb = (FAR struct pthread_tcb_s *) - kmm_zalloc(sizeof(struct pthread_tcb_s)); + ptcb = kmm_zalloc(sizeof(struct pthread_tcb_s)); if (!ptcb) { serr("ERROR: Failed to allocate TCB\n"); diff --git a/sched/sched/sched_releasetcb.c b/sched/sched/sched_releasetcb.c index 6ba7aaf87d..005ab60482 100644 --- a/sched/sched/sched_releasetcb.c +++ b/sched/sched/sched_releasetcb.c @@ -97,6 +97,9 @@ static void nxsched_releasepid(pid_t pid) int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype) { +#ifndef CONFIG_DISABLE_PTHREAD + FAR struct task_tcb_s *ttcb; +#endif int ret = OK; if (tcb) @@ -161,6 +164,23 @@ int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype) group_leave(tcb); + /* Kernel thread and group still reference by pthread */ + +#ifndef CONFIG_DISABLE_PTHREAD + if (ttype != TCB_FLAG_TTYPE_PTHREAD) + { + ttcb = (FAR struct task_tcb_s *)tcb; + if (!sq_empty(&ttcb->group.tg_members) +#if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) + || ttcb->group.tg_nwaiters > 0 +#endif + ) + { + return ret; + } + } +#endif + /* And, finally, release the TCB itself */ if (tcb->flags & TCB_FLAG_FREE_TCB) diff --git a/sched/task/task_fork.c b/sched/task/task_fork.c index a3dc7ccfe6..dfeb73cd2d 100644 --- a/sched/task/task_fork.c +++ b/sched/task/task_fork.c @@ -142,9 +142,11 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr) goto errout; } + child->cmn.flags |= TCB_FLAG_FREE_TCB; + /* Allocate a new task group with the same privileges as the parent */ - ret = group_allocate(child, ttype); + ret = group_initialize(child, ttype); if (ret < 0) { goto errout_with_tcb; @@ -214,7 +216,7 @@ FAR struct task_tcb_s *nxtask_setup_fork(start_t retaddr) /* Now we have enough in place that we can join the group */ - group_initialize(child); + group_postinitialize(child); sinfo("parent=%p, returning child=%p\n", parent, child); return child; diff --git a/sched/task/task_init.c b/sched/task/task_init.c index bce71184cd..5820c8e5d0 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -111,7 +111,7 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, /* Create a new task group */ - ret = group_allocate(tcb, tcb->cmn.flags); + ret = group_initialize(tcb, tcb->cmn.flags); if (ret < 0) { sched_trace_end(); @@ -179,7 +179,7 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, /* Now we have enough in place that we can join the group */ - group_initialize(tcb); + group_postinitialize(tcb); sched_trace_end(); return ret;