Skip to content

Commit

Permalink
sched/tcb: use shared group for kthreads
Browse files Browse the repository at this point in the history
Kthreads can share the group data so that to reduce overheads.
This implements shared kthread group via:

- use `tcb_s` instead of `task_tcb_s` for kthreads
- use `g_kthread_group` when creating kthreads
- use stackargs to start tasks and kthreads

see pull/12320 for test logs.

Signed-off-by: Yanfeng Liu <[email protected]>
  • Loading branch information
yf13 committed Jun 5, 2024
1 parent fb41833 commit fb1e2d5
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 60 deletions.
2 changes: 1 addition & 1 deletion sched/environ/env_dup.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * const *envcp)

/* Is there an environment ? */

if (envcp != NULL)
if (envcp != NULL && group->tg_envp == NULL)
{
/* Pre-emption must be disabled throughout the following because the
* environment may be shared.
Expand Down
25 changes: 21 additions & 4 deletions sched/group/group_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
#include "tls/tls.h"

/****************************************************************************
* Public Data
* Private Data
****************************************************************************/

static struct task_group_s g_kthread_group; /* Shared among kthreads */

/****************************************************************************
* Private Functions
****************************************************************************/
Expand Down Expand Up @@ -119,9 +121,23 @@ int group_initialize(FAR struct task_tcb_s *tcb, uint8_t ttype)

DEBUGASSERT(tcb && !tcb->cmn.group);

/* Allocate the group structure and assign it to the TCB */
ttype &= TCB_FLAG_TTYPE_MASK;

/* Initialize group pointer and assign to TCB */

group = &tcb->group;
if (ttype == TCB_FLAG_TTYPE_KERNEL)
{
group = &g_kthread_group;
tcb->cmn.group = group;
if (group->tg_info)
{
return OK;
}
}
else
{
group = &tcb->group;
}

#if defined(CONFIG_MM_KERNEL_HEAP)
/* If this group is being created for a privileged thread, then all
Expand Down Expand Up @@ -222,5 +238,6 @@ void group_postinitialize(FAR struct task_tcb_s *tcb)
* task has exited.
*/

group->tg_pid = tcb->cmn.pid;
group->tg_pid = (group == &g_kthread_group) ? group->tg_pid :
tcb->cmn.pid;
}
3 changes: 2 additions & 1 deletion sched/group/group_setuptaskfiles.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ int group_setuptaskfiles(FAR struct task_tcb_s *tcb,

/* Duplicate the parent task's file descriptors */

ret = files_duplist(&rtcb->group->tg_filelist,
ret = (group == rtcb->group) ? OK :
files_duplist(&rtcb->group->tg_filelist,
&group->tg_filelist, actions, cloexec);
if (ret >= 0 && actions != NULL)
{
Expand Down
66 changes: 33 additions & 33 deletions sched/init/nx_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ uint8_t g_nx_initstate; /* See enum nx_initstate_e */
* bringing up the rest of the system.
*/

static struct task_tcb_s g_idletcb[CONFIG_SMP_NCPUS];
static struct tcb_s g_idletcb[CONFIG_SMP_NCPUS];

/* This is the name of the idle task */

Expand Down Expand Up @@ -350,10 +350,11 @@ static void tasklist_initialize(void)

static void idle_task_initialize(void)
{
FAR struct task_tcb_s *tcb;
FAR struct tcb_s *tcb;
FAR dq_queue_t *tasklist;
int i;

memset(g_idletcb, 0, sizeof(g_idletcb));
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
tcb = &g_idletcb[i];
Expand All @@ -365,9 +366,8 @@ static void idle_task_initialize(void)
* that has pid == 0 and sched_priority == 0.
*/

memset(tcb, 0, sizeof(struct task_tcb_s));
tcb->cmn.pid = i;
tcb->cmn.task_state = TSTATE_TASK_RUNNING;
tcb->pid = i;
tcb->task_state = TSTATE_TASK_RUNNING;

/* Set the entry point. This is only for debug purposes. NOTE: that
* the start_t entry point is not saved. That is acceptable, however,
Expand All @@ -378,23 +378,23 @@ static void idle_task_initialize(void)
#ifdef CONFIG_SMP
if (i > 0)
{
tcb->cmn.start = nx_idle_trampoline;
tcb->cmn.entry.main = (main_t)nx_idle_trampoline;
tcb->start = nx_idle_trampoline;
tcb->entry.main = (main_t)nx_idle_trampoline;
}
else
#endif
{
tcb->cmn.start = nx_start;
tcb->cmn.entry.main = (main_t)nx_start;
tcb->start = nx_start;
tcb->entry.main = (main_t)nx_start;
}

/* Set the task flags to indicate that this is a kernel thread and, if
* configured for SMP, that this task is locked to this CPU.
*/

#ifdef CONFIG_SMP
tcb->cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_LOCKED);
tcb->cmn.cpu = i;
tcb->flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_LOCKED);
tcb->cpu = i;

/* Set the affinity mask to allow the thread to run on all CPUs. No,
* this IDLE thread can only run on its assigned CPU. That is
Expand All @@ -404,19 +404,19 @@ static void idle_task_initialize(void)
* the IDLE task.
*/

tcb->cmn.affinity =
tcb->affinity =
(cpu_set_t)(CONFIG_SMP_DEFAULT_CPUSET & SCHED_ALL_CPUS);
#else
tcb->cmn.flags = TCB_FLAG_TTYPE_KERNEL;
tcb->flags = TCB_FLAG_TTYPE_KERNEL;
#endif

#if CONFIG_TASK_NAME_SIZE > 0
/* Set the IDLE task name */

# ifdef CONFIG_SMP
snprintf(tcb->cmn.name, CONFIG_TASK_NAME_SIZE, "CPU%d IDLE", i);
snprintf(tcb->name, CONFIG_TASK_NAME_SIZE, "CPU%d IDLE", i);
# else
strlcpy(tcb->cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE);
strlcpy(tcb->name, g_idlename, CONFIG_TASK_NAME_SIZE);
# endif

/* Configure the task name in the argument list. The IDLE task does
Expand All @@ -427,7 +427,7 @@ static void idle_task_initialize(void)
* stack and there is no support that yet.
*/

g_idleargv[i][0] = tcb->cmn.name;
g_idleargv[i][0] = tcb->name;
#else
g_idleargv[i][0] = (FAR char *)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
Expand All @@ -437,15 +437,15 @@ static void idle_task_initialize(void)
*/

#ifdef CONFIG_SMP
tasklist = TLIST_HEAD(&tcb->cmn, i);
tasklist = TLIST_HEAD(tcb, i);
#else
tasklist = TLIST_HEAD(&tcb->cmn);
tasklist = TLIST_HEAD(tcb);
#endif
dq_addfirst((FAR dq_entry_t *)tcb, tasklist);

/* Mark the idle task as the running task */

g_running_tasks[i] = &tcb->cmn;
g_running_tasks[i] = tcb;
}
}

Expand All @@ -459,7 +459,7 @@ static void idle_task_initialize(void)

static void idle_group_initialize(void)
{
FAR struct task_tcb_s *tcb;
FAR struct tcb_s *tcb;
int hashndx;
int i;

Expand All @@ -470,16 +470,17 @@ static void idle_group_initialize(void)
tcb = &g_idletcb[i];

hashndx = PIDHASH(i);
nxsched_pidhash()[hashndx] = &tcb->cmn;
nxsched_pidhash()[hashndx] = tcb;

/* Allocate the IDLE group */

DEBUGVERIFY(group_initialize(tcb, tcb->cmn.flags));
tcb->cmn.group->tg_info->ta_argv = &g_idleargv[i][0];
DEBUGVERIFY(
group_initialize((FAR struct task_tcb_s *)tcb, tcb->flags));
tcb->group->tg_info->ta_argv = &g_idleargv[i][0];

/* Initialize the task join */

nxtask_joininit(&tcb->cmn);
nxtask_joininit(tcb);

#ifdef CONFIG_SMP
/* Create a stack for all CPU IDLE threads (except CPU0 which already
Expand All @@ -488,26 +489,24 @@ static void idle_group_initialize(void)

if (i > 0)
{
DEBUGVERIFY(up_cpu_idlestack(i, &tcb->cmn,
CONFIG_IDLETHREAD_STACKSIZE));
DEBUGVERIFY(up_cpu_idlestack(i, tcb, CONFIG_IDLETHREAD_STACKSIZE));
}
#endif

/* Initialize the processor-specific portion of the TCB */

up_initial_state(&tcb->cmn);
up_initial_state(tcb);

/* Initialize the thread local storage */

tls_init_info(&tcb->cmn);
tls_init_info(tcb);

/* Complete initialization of the IDLE group. Suppress retention
* of child status in the IDLE group.
*/

group_postinitialize(tcb);
tcb->cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT |
GROUP_FLAG_PRIVILEGED;
group_postinitialize((FAR struct task_tcb_s *)tcb);
tcb->group->tg_flags = GROUP_FLAG_NOCLDWAIT | GROUP_FLAG_PRIVILEGED;
}
}

Expand Down Expand Up @@ -727,7 +726,7 @@ void nx_start(void)

/* Announce that the CPU0 IDLE task has started */

sched_note_start(&g_idletcb[0].cmn);
sched_note_start(&g_idletcb[0]);

/* Initialize stdio for the IDLE task of each CPU */

Expand All @@ -737,7 +736,8 @@ void nx_start(void)
{
/* Clone stdout, stderr, stdin from the CPU0 IDLE task. */

DEBUGVERIFY(group_setuptaskfiles(&g_idletcb[i], NULL, true));
DEBUGVERIFY(group_setuptaskfiles(
(FAR struct task_tcb_s *)&g_idletcb[i], NULL, true));
}
else
{
Expand Down
15 changes: 8 additions & 7 deletions sched/task/task_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority,
FAR void *stack_addr, int stack_size, main_t entry,
FAR char * const argv[], FAR char * const envp[])
{
FAR struct task_tcb_s *tcb;
FAR struct tcb_s *tcb;
pid_t pid;
int ret;

/* Allocate a TCB for the new task. */

tcb = kmm_zalloc(sizeof(struct task_tcb_s));
tcb = kmm_zalloc(ttype == TCB_FLAG_TTYPE_KERNEL ? sizeof(struct tcb_s) :
sizeof(struct task_tcb_s));
if (!tcb)
{
serr("ERROR: Failed to allocate TCB\n");
Expand All @@ -91,12 +92,12 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority,

/* Setup the task type */

tcb->cmn.flags = ttype | TCB_FLAG_FREE_TCB;
tcb->flags = ttype | TCB_FLAG_FREE_TCB;

/* Initialize the task */

ret = nxtask_init(tcb, name, priority, stack_addr, stack_size,
entry, argv, envp, NULL);
ret = nxtask_init((FAR struct task_tcb_s *)tcb, name, priority,
stack_addr, stack_size, entry, argv, envp, NULL);
if (ret < OK)
{
kmm_free(tcb);
Expand All @@ -105,11 +106,11 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority,

/* Get the assigned pid before we start the task */

pid = tcb->cmn.pid;
pid = tcb->pid;

/* Activate the task */

nxtask_activate(&tcb->cmn);
nxtask_activate(tcb);

return pid;
}
Expand Down
9 changes: 7 additions & 2 deletions sched/task/task_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ static void nxtask_setup_name(FAR struct task_tcb_s *tcb,
*
* Input Parameters:
* tcb - Address of the new task's TCB
* name - Name of the new task
* argv - A pointer to an array of input parameters. The array should be
* terminated with a NULL argv[] value. If no parameters are
* required, argv may be NULL.
Expand All @@ -527,6 +528,7 @@ static int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb,
FAR const char *name,
FAR char * const argv[])
{
const uint8_t ttype = tcb->cmn.flags & TCB_FLAG_TTYPE_MASK;
FAR char **stackargv;
FAR char *str;
size_t strtablen;
Expand Down Expand Up @@ -630,8 +632,11 @@ static int nxtask_setup_stackargs(FAR struct task_tcb_s *tcb,

stackargv[argc + 1] = NULL;

tcb->cmn.group->tg_info->ta_argc = argc;
tcb->cmn.group->tg_info->ta_argv = stackargv;
if (ttype != TCB_FLAG_TTYPE_KERNEL)
{
tcb->cmn.group->tg_info->ta_argc = argc;
tcb->cmn.group->tg_info->ta_argv = stackargv;
}

return OK;
}
Expand Down
Loading

0 comments on commit fb1e2d5

Please sign in to comment.