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 stack args to start kthreads or tasks, args in group are to
  please commands like `ps`.

Signed-off-by: Yanfeng Liu <[email protected]>
  • Loading branch information
yf13 committed May 17, 2024
1 parent dea7866 commit b613d76
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 26 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
18 changes: 12 additions & 6 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 @@ -352,11 +352,14 @@ static void idle_task_initialize(void)
{
FAR struct task_tcb_s *tcb;
FAR dq_queue_t *tasklist;
volatile uintptr_t p;
int i;

memset(g_idletcb, 0, sizeof(g_idletcb));
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
tcb = &g_idletcb[i];
p = (uintptr_t)&g_idletcb[i];
tcb = (FAR struct task_tcb_s *)p;

/* Initialize a TCB for this thread of execution. NOTE: The default
* value for most components of the g_idletcb are zero. The entire
Expand All @@ -365,7 +368,6 @@ 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;

Expand Down Expand Up @@ -460,14 +462,16 @@ static void idle_task_initialize(void)
static void idle_group_initialize(void)
{
FAR struct task_tcb_s *tcb;
volatile uintptr_t p;
int hashndx;
int i;

/* Assign the process ID(s) of ZERO to the idle task(s) */

for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
tcb = &g_idletcb[i];
p = (uintptr_t)&g_idletcb[i];
tcb = (FAR struct task_tcb_s *)p;

hashndx = PIDHASH(i);
nxsched_pidhash()[hashndx] = &tcb->cmn;
Expand Down Expand Up @@ -533,6 +537,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 +732,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 b613d76

Please sign in to comment.