Skip to content

Commit 97e96a8

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 9166c08 commit 97e96a8

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
@@ -121,6 +121,9 @@ typedef struct {
121121

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

126129
/* Global pointer to the singleton Kernel Control Block */
@@ -316,5 +319,19 @@ void _sched_block_mutex(list_t *waiters);
316319
*/
317320
int32_t app_main(void);
318321

322+
/* Initialize the idle task
323+
*
324+
* This function statically creates and initializes the idle task structure.
325+
* It should be called once during system startup.
326+
*
327+
* The idle task is a permanent system task that runs when no other
328+
* ready tasks exist. It is never enqueued into any ready queue and
329+
* cannot be suspended, canceled, or priority modified.
330+
*
331+
* Only one idle task exists per hart. Its priority is fixed to the
332+
* lowest level and its time slice is zero.
333+
*/
334+
void idle_task_init(void);
335+
319336
/* Wake up and enqueue task into ready queue */
320337
void sched_wakeup_task(tcb_t *);

kernel/task.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,20 @@ void sched_wakeup_task(tcb_t *task)
486486
sched_enqueue_task(task);
487487
}
488488

489+
/* System idle task, it will be executed when no ready tasks in ready queue */
490+
static void sched_idle(void)
491+
{
492+
if (!kcb->preemptive)
493+
/* Cooperative mode idle */
494+
while (1)
495+
mo_task_yield();
496+
497+
/* Preemptive mode idle */
498+
while (1)
499+
mo_task_wfi();
500+
}
501+
502+
489503
/* Efficient Round-Robin Task Selection with O(n) Complexity
490504
*
491505
* Selects the next ready task using circular traversal of the master task list.
@@ -779,6 +793,52 @@ static bool init_task_stack(tcb_t *tcb, size_t stack_size)
779793
return true;
780794
}
781795

796+
/* Initialize idle task */
797+
void idle_task_init(void)
798+
{
799+
/* Ensure proper alignment */
800+
size_t stack_size = DEFAULT_STACK_SIZE;
801+
stack_size = (stack_size + 0xF) & ~0xFU;
802+
803+
/* Allocate and initialize TCB */
804+
tcb_t *idle = malloc(sizeof(tcb_t));
805+
if (!idle)
806+
panic(ERR_TCB_ALLOC);
807+
808+
idle->entry = &sched_idle;
809+
idle->delay = 0;
810+
idle->rt_prio = NULL;
811+
idle->state = TASK_READY;
812+
idle->flags = 0;
813+
814+
/* Set idle task priority */
815+
idle->prio = TASK_PRIO_IDLE;
816+
idle->prio_level = 0;
817+
idle->time_slice = 0;
818+
819+
/* Set idle task id and task count */
820+
idle->id = kcb->next_tid++;
821+
kcb->task_count++;
822+
823+
/* Initialize stack */
824+
if (!init_task_stack(idle, stack_size)) {
825+
free(idle);
826+
panic(ERR_STACK_ALLOC);
827+
}
828+
829+
/* Binding idle task into kcb */
830+
kcb->task_idle.data = idle;
831+
832+
/* Initialize idle task execution context */
833+
hal_context_init(&idle->context, (size_t) idle->stack, stack_size,
834+
(size_t) &sched_idle);
835+
836+
printf("idle id %u: entry=%p stack=%p size=%u\n", idle->id, &sched_idle,
837+
idle->stack, (unsigned int) stack_size);
838+
839+
return;
840+
}
841+
782842
/* Task Management API */
783843

784844
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)

0 commit comments

Comments
 (0)