sched/init: move idle task initialize to inline function

N/A, help to extend the multi-core implementation

Signed-off-by: chao an <anchao@lixiang.com>
This commit is contained in:
chao an 2024-03-22 09:19:34 +08:00 committed by Xiang Xiao
parent 738bdb95b7
commit 7cc89bbd0e
1 changed files with 177 additions and 140 deletions

View File

@ -294,6 +294,181 @@ static const char g_idlename[] = "Idle_Task";
static FAR char *g_idleargv[CONFIG_SMP_NCPUS][2];
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: idle_task_initialize
*
* Description:
* IDLE Task Initialization
*
****************************************************************************/
static void idle_task_initialize(void)
{
FAR struct task_tcb_s *tcb;
FAR dq_queue_t *tasklist;
int i;
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
tcb = &g_idletcb[i];
/* Initialize a TCB for this thread of execution. NOTE: The default
* value for most components of the g_idletcb are zero. The entire
* structure is set to zero. Then only the (potentially) non-zero
* elements are initialized. NOTE: The idle task is the only task in
* 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;
/* Set the entry point. This is only for debug purposes. NOTE: that
* the start_t entry point is not saved. That is acceptable, however,
* because it can be used only for restarting a task: The IDLE task
* cannot be restarted.
*/
#ifdef CONFIG_SMP
if (i > 0)
{
tcb->cmn.start = nx_idle_trampoline;
tcb->cmn.entry.main = (main_t)nx_idle_trampoline;
}
else
#endif
{
tcb->cmn.start = nx_start;
tcb->cmn.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;
/* 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
* enforced by the TCB_FLAG_CPU_LOCKED which overrides the affinity
* mask. This is essential because all tasks inherit the affinity
* mask from their parent and, ultimately, the parent of all tasks is
* the IDLE task.
*/
tcb->cmn.affinity =
(cpu_set_t)(CONFIG_SMP_DEFAULT_CPUSET & SCHED_ALL_CPUS);
#else
tcb->cmn.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);
# else
strlcpy(tcb->cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE);
# endif
/* Configure the task name in the argument list. The IDLE task does
* not really have an argument list, but this name is still useful
* for things like the NSH PS command.
*
* In the kernel mode build, the arguments are saved on the task's
* stack and there is no support that yet.
*/
g_idleargv[i][0] = tcb->cmn.name;
#else
g_idleargv[i][0] = (FAR char *)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
/* Then add the idle task's TCB to the head of the current ready to
* run list.
*/
#ifdef CONFIG_SMP
tasklist = TLIST_HEAD(&tcb->cmn, i);
#else
tasklist = TLIST_HEAD(&tcb->cmn);
#endif
dq_addfirst((FAR dq_entry_t *)tcb, tasklist);
/* Mark the idle task as the running task */
g_running_tasks[i] = &tcb->cmn;
}
}
/****************************************************************************
* Name: idle_group_initialize
*
* Description:
* IDLE Group Initialization
*
****************************************************************************/
static void idle_group_initialize(void)
{
FAR struct task_tcb_s *tcb;
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];
hashndx = PIDHASH(i);
nxsched_pidhash()[hashndx] = &tcb->cmn;
/* Allocate the IDLE group */
DEBUGVERIFY(group_initialize(tcb, tcb->cmn.flags));
tcb->cmn.group->tg_info->ta_argv = &g_idleargv[i][0];
/* Initialize the task join */
nxtask_joininit(&tcb->cmn);
#ifdef CONFIG_SMP
/* Create a stack for all CPU IDLE threads (except CPU0 which already
* has a stack).
*/
if (i > 0)
{
DEBUGVERIFY(up_cpu_idlestack(i, &tcb->cmn,
CONFIG_IDLETHREAD_STACKSIZE));
}
#endif
/* Initialize the processor-specific portion of the TCB */
up_initial_state(&tcb->cmn);
/* Initialize the thread local storage */
tls_init_info(&tcb->cmn);
/* 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;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -330,100 +505,7 @@ void nx_start(void)
/* Initialize the IDLE task TCB *******************************************/
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
FAR dq_queue_t *tasklist;
/* Initialize a TCB for this thread of execution. NOTE: The default
* value for most components of the g_idletcb are zero. The entire
* structure is set to zero. Then only the (potentially) non-zero
* elements are initialized. NOTE: The idle task is the only task in
* that has pid == 0 and sched_priority == 0.
*/
memset((void *)&g_idletcb[i], 0, sizeof(struct task_tcb_s));
g_idletcb[i].cmn.pid = i;
g_idletcb[i].cmn.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,
* because it can be used only for restarting a task: The IDLE task
* cannot be restarted.
*/
#ifdef CONFIG_SMP
if (i > 0)
{
g_idletcb[i].cmn.start = nx_idle_trampoline;
g_idletcb[i].cmn.entry.main = (main_t)nx_idle_trampoline;
}
else
#endif
{
g_idletcb[i].cmn.start = nx_start;
g_idletcb[i].cmn.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
g_idletcb[i].cmn.flags = (TCB_FLAG_TTYPE_KERNEL | TCB_FLAG_CPU_LOCKED);
g_idletcb[i].cmn.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
* enforced by the TCB_FLAG_CPU_LOCKED which overrides the affinity
* mask. This is essential because all tasks inherit the affinity
* mask from their parent and, ultimately, the parent of all tasks is
* the IDLE task.
*/
g_idletcb[i].cmn.affinity =
(cpu_set_t)(CONFIG_SMP_DEFAULT_CPUSET & SCHED_ALL_CPUS);
#else
g_idletcb[i].cmn.flags = TCB_FLAG_TTYPE_KERNEL;
#endif
#if CONFIG_TASK_NAME_SIZE > 0
/* Set the IDLE task name */
# ifdef CONFIG_SMP
snprintf(g_idletcb[i].cmn.name, CONFIG_TASK_NAME_SIZE, "CPU%d IDLE",
i);
# else
strlcpy(g_idletcb[i].cmn.name, g_idlename, CONFIG_TASK_NAME_SIZE);
# endif
/* Configure the task name in the argument list. The IDLE task does
* not really have an argument list, but this name is still useful
* for things like the NSH PS command.
*
* In the kernel mode build, the arguments are saved on the task's
* stack and there is no support that yet.
*/
g_idleargv[i][0] = g_idletcb[i].cmn.name;
#else
g_idleargv[i][0] = (FAR char *)g_idlename;
#endif /* CONFIG_TASK_NAME_SIZE */
/* Then add the idle task's TCB to the head of the current ready to
* run list.
*/
#ifdef CONFIG_SMP
tasklist = TLIST_HEAD(&g_idletcb[i].cmn, i);
#else
tasklist = TLIST_HEAD(&g_idletcb[i].cmn);
#endif
dq_addfirst((FAR dq_entry_t *)&g_idletcb[i], tasklist);
/* Mark the idle task as the running task */
g_running_tasks[i] = &g_idletcb[i].cmn;
}
idle_task_initialize();
/* Task lists are initialized */
@ -507,52 +589,7 @@ void nx_start(void)
/* IDLE Group Initialization **********************************************/
for (i = 0; i < CONFIG_SMP_NCPUS; i++)
{
int hashndx;
/* Assign the process ID(s) of ZERO to the idle task(s) */
hashndx = PIDHASH(i);
nxsched_pidhash()[hashndx] = &g_idletcb[i].cmn;
/* Allocate the IDLE group */
DEBUGVERIFY(group_initialize(&g_idletcb[i], g_idletcb[i].cmn.flags));
g_idletcb[i].cmn.group->tg_info->ta_argv = &g_idleargv[i][0];
/* Initialize the task join */
nxtask_joininit(&g_idletcb[i].cmn);
#ifdef CONFIG_SMP
/* Create a stack for all CPU IDLE threads (except CPU0 which already
* has a stack).
*/
if (i > 0)
{
DEBUGVERIFY(up_cpu_idlestack(i, &g_idletcb[i].cmn,
CONFIG_IDLETHREAD_STACKSIZE));
}
#endif
/* Initialize the processor-specific portion of the TCB */
up_initial_state(&g_idletcb[i].cmn);
/* Initialize the thread local storage */
tls_init_info(&g_idletcb[i].cmn);
/* Complete initialization of the IDLE group. Suppress retention
* of child status in the IDLE group.
*/
group_postinitialize(&g_idletcb[i]);
g_idletcb[i].cmn.group->tg_flags = GROUP_FLAG_NOCLDWAIT |
GROUP_FLAG_PRIVILEGED;
}
idle_group_initialize();
nxsched_lastpid() = CONFIG_SMP_NCPUS - 1;