Skip to content

Commit b09d2c2

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 c9a07e7 commit b09d2c2

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
@@ -621,6 +636,63 @@ static bool init_task_stack(tcb_t *tcb, size_t stack_size)
621636
return true;
622637
}
623638

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

626698
int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)

0 commit comments

Comments
 (0)