Skip to content

Commit df3b2d7

Browse files
committed
Add idle task and initialization API
This commit introduces the system idle task and its initialization API (idle_task_init()). The idle task serves as the default execution context when no other runnable tasks exist in the system. The sched_idle() function supports both preemptive and cooperative modes. In sched_t, a list node named task_idle is added to record the idle task sentinel. The idle task never enters any ready queue and its priority level cannot be changed. When idle_task_init() is called, the idle task is initialized as the first execution context. This eliminates the need for additional APIs in main() to set up the initial high-priority task during system launch. This design allows task priorities to be adjusted safely during app_main(), while keeping the scheduler’s entry point consistent.
1 parent 40cbc78 commit df3b2d7

File tree

2 files changed

+88
-2
lines changed

2 files changed

+88
-2
lines changed

include/sys/task.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ typedef struct sched {
9595
list_node_t *rr_cursors[TASK_PRIORITY_LEVELS]; /* Round-robin position */
9696

9797
/* Hart-Specific Data */
98-
uint8_t hart_id; /* RISC-V hart identifier */
99-
98+
uint8_t hart_id; /* RISC-V hart identifier */
99+
list_node_t *task_idle; /* Idle task */
100100
} sched_t;
101101

102102
/* Kernel Control Block (KCB)
@@ -303,3 +303,17 @@ void _sched_block(queue_t *wait_q);
303303
* Returns 'true' to enable preemptive scheduling, or 'false' for cooperative
304304
*/
305305
int32_t app_main(void);
306+
307+
/* Initialize the idle task
308+
*
309+
* This function statically creates and initializes the idle task structure.
310+
* It should be called once during system startup.
311+
*
312+
* The idle task is a permanent system task that runs when no other
313+
* ready tasks exist. It is never enqueued into any ready queue and
314+
* cannot be suspended, canceled, or priority modified.
315+
*
316+
* Only one idle task exists per hart. Its priority is fixed to the
317+
* lowest level and its time slice is zero.
318+
*/
319+
void idle_task_init(void);

kernel/task.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static sched_t hart0 = {
2121
.ready_queues = {NULL},
2222
.rr_cursors = {NULL},
2323
.hart_id = 0,
24+
.task_idle = NULL,
2425
};
2526

2627
/* Kernel-wide control block (KCB) */
@@ -463,6 +464,20 @@ void sched_wakeup_task(tcb_t *task)
463464
sched_enqueue_task(task);
464465
}
465466

467+
/* System idle task, it will be executed when no ready tasks in ready queue */
468+
static void sched_idle(void)
469+
{
470+
if (!kcb->preemptive)
471+
/* Cooperative mode idle */
472+
while (1)
473+
mo_task_yield();
474+
475+
/* Preemptive mode idle */
476+
while (1)
477+
mo_task_wfi();
478+
}
479+
480+
466481
/* Efficient Round-Robin Task Selection (Cursor-Based, O(1) Complexity)
467482
*
468483
* Selects the next ready task by advancing the per-priority round-robin
@@ -627,6 +642,63 @@ static bool init_task_stack(tcb_t *tcb, size_t stack_size)
627642
return true;
628643
}
629644

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

632704
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)

0 commit comments

Comments
 (0)