diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index 61ba077882b..9019f2ccbbd 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -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;