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 kthreads and tasks

see pull/12320 for test logs.

Signed-off-by: Yanfeng Liu <[email protected]>
  • Loading branch information
yf13 committed May 19, 2024
1 parent dea7866 commit 0186a69
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 53 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
23 changes: 20 additions & 3 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);

ttype &= TCB_FLAG_TTYPE_MASK;

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

if (NULL == g_kthread_group.tg_info)
{
sinfo("group=%zu task=%zu kthread=%zu\n", sizeof(*group),
sizeof(struct task_tcb_s), sizeof(struct tcb_s));
}

/* Allocate the group structure and assign it to the TCB */

group = &tcb->group;
group = (ttype == TCB_FLAG_TTYPE_KERNEL) ? &g_kthread_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
67 changes: 34 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 All @@ -533,6 +532,7 @@ static void idle_group_initialize(void)

void nx_start(void)
{
FAR struct task_tcb_s *ttcb;
int i;

sinfo("Entry\n");
Expand Down Expand Up @@ -727,17 +727,18 @@ 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 */

for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
ttcb = (FAR struct task_tcb_s *)&g_idletcb[i];
if (i > 0)
{
/* Clone stdout, stderr, stdin from the CPU0 IDLE task. */

DEBUGVERIFY(group_setuptaskfiles(&g_idletcb[i], NULL, true));
DEBUGVERIFY(group_setuptaskfiles(ttcb, NULL, true));
}
else
{
Expand Down
5 changes: 4 additions & 1 deletion sched/task/task_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,15 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority,
FAR char * const argv[], FAR char * const envp[])
{
FAR struct task_tcb_s *tcb;
volatile size_t size;
pid_t pid;
int ret;

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

tcb = kmm_zalloc(sizeof(struct task_tcb_s));
size = (ttype == TCB_FLAG_TTYPE_KERNEL) ? sizeof(struct tcb_s) :
sizeof(struct task_tcb_s);
tcb = kmm_zalloc(size);
if (!tcb)
{
serr("ERROR: Failed to allocate TCB\n");
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
24 changes: 12 additions & 12 deletions sched/task/task_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,18 @@
void nxtask_start(void)
{
FAR struct tcb_s *tcb = this_task();
const uint8_t ttype = tcb->flags & TCB_FLAG_TTYPE_MASK;
#ifdef CONFIG_SCHED_STARTHOOK
FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb;
#endif
int exitcode = EXIT_FAILURE;
FAR char **argv;
int argc;

DEBUGASSERT((tcb->flags & TCB_FLAG_TTYPE_MASK) != \
TCB_FLAG_TTYPE_PTHREAD);
DEBUGASSERT(ttype != TCB_FLAG_TTYPE_PTHREAD);

#ifdef CONFIG_SIG_DEFAULT
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
if (ttype != TCB_FLAG_TTYPE_KERNEL)
{
/* Set up default signal actions for NON-kernel thread */

Expand All @@ -87,33 +88,32 @@ void nxtask_start(void)
/* Execute the start hook if one has been registered */

#ifdef CONFIG_SCHED_STARTHOOK
if (ttcb->starthook != NULL)
if (ttype != TCB_FLAG_TTYPE_KERNEL && ttcb->starthook != NULL)
{
ttcb->starthook(ttcb->starthookarg);
}
#endif

/* Add program name */
/* Take args from stack, as group is shared for kthreads */

argc = tcb->group->tg_info->ta_argc + 1;
argv = nxsched_get_stackargs(tcb);
for (argc = 0; argv && argv[argc]; argc++);

/* Call the 'main' entry point passing argc and argv. In the kernel build
* this has to be handled differently if we are starting a user-space task;
* we have to switch to user-mode before calling the task.
*/

if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL)
if (ttype == TCB_FLAG_TTYPE_KERNEL)
{
exitcode = tcb->entry.main(argc, tcb->group->tg_info->ta_argv);
exitcode = tcb->entry.main(argc, argv);
}
else
{
#ifdef CONFIG_BUILD_FLAT
nxtask_startup(tcb->entry.main, argc,
tcb->group->tg_info->ta_argv);
nxtask_startup(tcb->entry.main, argc, argv);
#else
up_task_start(tcb->entry.main, argc,
tcb->group->tg_info->ta_argv);
up_task_start(tcb->entry.main, argc, argv);
#endif
}

Expand Down

0 comments on commit 0186a69

Please sign in to comment.