sched/group: Simplify the allocation and deallocation logic

1.Move tg_membe allocation to group_alloc
2.Merge group_deallocate to group_release

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
Xiang Xiao 2022-03-02 02:24:05 +08:00 committed by Masayuki Ishikawa
parent 4910879848
commit a50d87d5b7
7 changed files with 72 additions and 129 deletions

View File

@ -73,8 +73,7 @@ void weak_function task_initialize(void);
/* Task group data structure management */
int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype);
void group_deallocate(FAR struct task_group_s *group);
int group_initialize(FAR struct task_tcb_s *tcb);
void group_initialize(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);

View File

@ -152,7 +152,6 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
}
# if defined(CONFIG_FILE_STREAM)
/* In a flat, single-heap build. The stream list is allocated with the
* group structure. But in a kernel build with a kernel allocator, it
* must be separately allocated using a user-space allocator.
@ -163,7 +162,6 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
group->tg_streamlist = (FAR struct streamlist *)
group_zalloc(group, sizeof(struct streamlist));
if (!group->tg_streamlist)
{
goto errout_with_group;
@ -172,19 +170,28 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
# endif /* defined(CONFIG_FILE_STREAM) */
#endif /* defined(CONFIG_MM_KERNEL_HEAP) */
/* Alloc task info for group */
#ifdef HAVE_GROUP_MEMBERS
/* Allocate space to hold GROUP_INITIAL_MEMBERS members of the group */
group->tg_info = (FAR struct task_info_s *)
group_zalloc(group, sizeof(struct task_info_s));
if (!group->tg_info)
group->tg_members = kmm_malloc(GROUP_INITIAL_MEMBERS * sizeof(pid_t));
if (!group->tg_members)
{
goto errout_with_stream;
}
/* Initial user space semaphore */
/* Number of members in allocation */
nxsem_init(&group->tg_info->ta_sem, 0, 1);
group->tg_mxmembers = GROUP_INITIAL_MEMBERS;
#endif
/* Alloc task info for group */
group->tg_info = (FAR struct task_info_s *)
group_zalloc(group, sizeof(struct task_info_s));
if (!group->tg_info)
{
goto errout_with_member;
}
/* Attach the group to the TCB */
@ -200,9 +207,13 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
if (ret < 0)
{
tcb->cmn.group = NULL;
goto errout_with_group;
goto errout_with_taskinfo;
}
/* Initial user space semaphore */
nxsem_init(&group->tg_info->ta_sem, 0, 1);
/* Initialize file descriptors for the TCB */
files_initlist(&group->tg_filelist);
@ -232,66 +243,21 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype)
return OK;
errout_with_taskinfo:
group_free(group, group->tg_info);
errout_with_member:
#ifdef HAVE_GROUP_MEMBERS
kmm_free(group->tg_members);
errout_with_stream:
#endif
#if defined(CONFIG_FILE_STREAM) && defined(CONFIG_MM_KERNEL_HEAP)
group_free(group, group->tg_streamlist);
#endif
errout_with_group:
group_deallocate(group);
#endif
kmm_free(group);
return ret;
}
/****************************************************************************
* Name: group_deallocate
*
* Description:
* Free an existing task group structure.
*
* Input Parameters:
* group = The group structure
*
****************************************************************************/
void group_deallocate(FAR struct task_group_s *group)
{
if (group)
{
#ifdef CONFIG_ARCH_ADDRENV
save_addrenv_t oldenv;
/* NOTE: switch the addrenv before accessing group->tg_info
* located in the userland, also save the current addrenv
*/
up_addrenv_select(&group->tg_addrenv, &oldenv);
#endif
if (group->tg_info)
{
nxsem_destroy(&group->tg_info->ta_sem);
group_free(group, group->tg_info);
}
#ifdef CONFIG_ARCH_ADDRENV
/* Destroy the group address environment */
up_addrenv_destroy(&group->tg_addrenv);
/* Mark no address environment */
g_pid_current = INVALID_PROCESS_ID;
#endif
kmm_free(group);
#ifdef CONFIG_ARCH_ADDRENV
/* Restore the previous addrenv */
up_addrenv_restore(&oldenv);
#endif
}
}
/****************************************************************************
* Name: group_initialize
*
@ -305,7 +271,7 @@ void group_deallocate(FAR struct task_group_s *group)
* tcb - The tcb in need of the task group.
*
* Returned Value:
* 0 (OK) on success; a negated errno value on failure.
* None.
*
* Assumptions:
* Called during task creation in a safe context. No special precautions
@ -313,7 +279,7 @@ void group_deallocate(FAR struct task_group_s *group)
*
****************************************************************************/
int group_initialize(FAR struct task_tcb_s *tcb)
void group_initialize(FAR struct task_tcb_s *tcb)
{
FAR struct task_group_s *group;
#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
@ -324,35 +290,9 @@ int group_initialize(FAR struct task_tcb_s *tcb)
group = tcb->cmn.group;
#ifdef HAVE_GROUP_MEMBERS
/* Allocate space to hold GROUP_INITIAL_MEMBERS members of the group */
group->tg_members = kmm_malloc(GROUP_INITIAL_MEMBERS * sizeof(pid_t));
if (!group->tg_members)
{
group_deallocate(group);
tcb->cmn.group = NULL;
return -ENOMEM;
}
/* Assign the PID of this new task as a member of the group. */
group->tg_members[0] = tcb->cmn.pid;
/* Initialize the non-zero elements of group structure and assign it to
* the tcb.
*/
group->tg_mxmembers = GROUP_INITIAL_MEMBERS; /* Number of members in allocation */
#endif
#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
/* Add the initialized entry to the list of groups */
flags = enter_critical_section();
group->flink = g_grouphead;
g_grouphead = group;
leave_critical_section(flags);
#endif
/* Save the ID of the main task within the group of threads. This needed
@ -366,5 +306,13 @@ int group_initialize(FAR struct task_tcb_s *tcb)
/* Mark that there is one member in the group, the main task */
group->tg_nmembers = 1;
return OK;
#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
/* Add the initialized entry to the list of groups */
flags = enter_critical_section();
group->flink = g_grouphead;
g_grouphead = group;
leave_critical_section(flags);
#endif
}

View File

@ -128,10 +128,17 @@ static void group_remove(FAR struct task_group_s *group)
static inline void group_release(FAR struct task_group_s *group)
{
#ifdef CONFIG_ARCH_ADDRENV
save_addrenv_t oldenv;
#endif
#if CONFIG_TLS_TASK_NELEM > 0
task_tls_destruct();
#endif
nxsem_destroy(&group->tg_info->ta_sem);
group_free(group, group->tg_info);
#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
/* Free all un-reaped child exit status */
@ -174,17 +181,6 @@ static inline void group_release(FAR struct task_group_s *group)
shm_group_release(group);
#endif
#ifdef CONFIG_ARCH_ADDRENV
/* NOTE:
* We do not destroy the group address environment here.
* It will be done in the group_deallocate().
* However, we mark no address environment here,
* so that group_addrenv() can work correctly
*/
g_pid_current = INVALID_PROCESS_ID;
#endif
#if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV)
/* Remove the group from the list of groups */
@ -241,6 +237,24 @@ static inline void group_release(FAR struct task_group_s *group)
}
#endif
#ifdef CONFIG_ARCH_ADDRENV
/* Switch the addrenv and also save the current addrenv */
up_addrenv_select(&group->tg_addrenv, &oldenv);
/* Destroy the group address environment */
up_addrenv_destroy(&group->tg_addrenv);
/* Mark no address environment */
g_pid_current = INVALID_PROCESS_ID;
/* Restore the previous addrenv */
up_addrenv_restore(&oldenv);
#endif
#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
@ -256,7 +270,7 @@ static inline void group_release(FAR struct task_group_s *group)
{
/* Release the group container itself */
group_deallocate(group);
kmm_free(group);
}
}

View File

@ -76,7 +76,7 @@ void group_del_waiter(FAR struct task_group_s *group)
* freed).
*/
group_deallocate(group);
kmm_free(group);
}
}

View File

@ -588,7 +588,7 @@ void nx_start(void)
* of child status in the IDLE group.
*/
DEBUGVERIFY(group_initialize(&g_idletcb[i]));
group_initialize(&g_idletcb[i]);
g_idletcb[i].cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT;
}

View File

@ -161,20 +161,10 @@ 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 */
ret = group_initialize(tcb);
if (ret == OK)
{
return ret;
}
/* The TCB was added to the inactive task list by
* nxtask_setup_scheduler().
*/
dq_rem((FAR dq_entry_t *)tcb, (FAR dq_queue_t *)&g_inactivetasks);
group_initialize(tcb);
return ret;
errout_with_group:
if (!stack && tcb->cmn.stack_alloc_ptr)
{
#ifdef CONFIG_BUILD_KERNEL
@ -196,7 +186,6 @@ errout_with_group:
}
group_leave(&tcb->cmn);
return ret;
}

View File

@ -210,17 +210,10 @@ FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr)
/* Now we have enough in place that we can join the group */
ret = group_initialize(child);
if (ret < OK)
{
goto errout_with_list;
}
group_initialize(child);
sinfo("parent=%p, returning child=%p\n", parent, child);
return child;
errout_with_list:
dq_rem((FAR dq_entry_t *)child, (FAR dq_queue_t *)&g_inactivetasks);
errout_with_tcb:
nxsched_release_tcb((FAR struct tcb_s *)child, ttype);
errout: