Skip to content

Commit 7fb0bd3

Browse files
committed
Add idle task and initialization API
This commit adds the system idle task and its initialization routine, idle_task_init(). The idle task serves as the default execution context when no runnable tasks exist. It never enters any ready queue and always uses the fixed priority TASK_PRIO_IDLE. Introducing a dedicated idle task ensures consistent scheduler entry during startup, strict ordering for user tasks, and allows priority adjustments before user tasks run for the first time.
1 parent 168c94a commit 7fb0bd3

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

include/sys/task.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ typedef struct {
120120

121121
/* Weighted Round-Robin State per Priority Level */
122122
list_node_t *rr_cursors[TASK_PRIORITY_LEVELS]; /* Round-robin position */
123+
124+
/* System idle task */
125+
list_node_t task_idle;
123126
} kcb_t;
124127

125128
/* Global pointer to the singleton Kernel Control Block */
@@ -304,5 +307,19 @@ void _sched_block(queue_t *wait_q);
304307
*/
305308
int32_t app_main(void);
306309

310+
/* Initialize the idle task
311+
*
312+
* This function statically creates and initializes the idle task structure.
313+
* It should be called once during system startup.
314+
*
315+
* The idle task is a permanent system task that runs when no other
316+
* ready tasks exist. It is never enqueued into any ready queue and
317+
* cannot be suspended, canceled, or priority modified.
318+
*
319+
* Only one idle task exists per hart. Its priority is fixed to the
320+
* lowest level and its time slice is zero.
321+
*/
322+
void idle_task_init(void);
323+
307324
/* Wake up and enqueue task into ready queue */
308325
void sched_wakeup_task(tcb_t *);

kernel/task.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,20 @@ void sched_wakeup_task(tcb_t *task)
460460
sched_enqueue_task(task);
461461
}
462462

463+
/* System idle task, it will be executed when no ready tasks in ready queue */
464+
static void sched_idle(void)
465+
{
466+
if (!kcb->preemptive)
467+
/* Cooperative mode idle */
468+
while (1)
469+
mo_task_yield();
470+
471+
/* Preemptive mode idle */
472+
while (1)
473+
mo_task_wfi();
474+
}
475+
476+
463477
/* Efficient Round-Robin Task Selection with O(n) Complexity
464478
*
465479
* Selects the next ready task using circular traversal of the master task list.
@@ -627,6 +641,52 @@ static bool init_task_stack(tcb_t *tcb, size_t stack_size)
627641
return true;
628642
}
629643

644+
/* Initialize idle task */
645+
void idle_task_init(void)
646+
{
647+
/* Ensure proper alignment */
648+
size_t stack_size = DEFAULT_STACK_SIZE;
649+
stack_size = (stack_size + 0xF) & ~0xFU;
650+
651+
/* Allocate and initialize TCB */
652+
tcb_t *idle = malloc(sizeof(tcb_t));
653+
if (!idle)
654+
panic(ERR_TCB_ALLOC);
655+
656+
idle->entry = &sched_idle;
657+
idle->delay = 0;
658+
idle->rt_prio = NULL;
659+
idle->state = TASK_READY;
660+
idle->flags = 0;
661+
662+
/* Set idle task priority */
663+
idle->prio = TASK_PRIO_IDLE;
664+
idle->prio_level = 0;
665+
idle->time_slice = 0;
666+
667+
/* Set idle task id and task count */
668+
idle->id = kcb->next_tid++;
669+
kcb->task_count++;
670+
671+
/* Initialize stack */
672+
if (!init_task_stack(idle, stack_size)) {
673+
free(idle);
674+
panic(ERR_STACK_ALLOC);
675+
}
676+
677+
/* Binding idle task into kcb */
678+
kcb->task_idle.data = idle;
679+
680+
/* Initialize idle task execution context */
681+
hal_context_init(&idle->context, (size_t) idle->stack, stack_size,
682+
(size_t) &sched_idle);
683+
684+
printf("idle id %u: entry=%p stack=%p size=%u\n", idle->id, &sched_idle,
685+
idle->stack, (unsigned int) stack_size);
686+
687+
return;
688+
}
689+
630690
/* Task Management API */
631691

632692
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)

0 commit comments

Comments
 (0)