Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
279364e
Add sched_t to kcb for O(1) scheduler support
vicLin8712 Sep 17, 2025
56c1926
Add list_unlink() for safe node removal from ready queue
vicLin8712 Oct 22, 2025
6bd43f1
Add three marcos for ready queue bitmap operation
vicLin8712 Oct 24, 2025
f5934fb
Refactor sched_enqueue_task() for O(1) scheduler support
vicLin8712 Oct 24, 2025
e5f828c
Implement sched_dequeue_task() to dequeue task from ready queue
vicLin8712 Oct 24, 2025
6a7149d
Refactor mo_task_spawn() for O(1) scheduler support
vicLin8712 Oct 22, 2025
e986cd5
Refactor scheduler to RR cursor-based O(1) design
vicLin8712 Oct 22, 2025
debd486
Add ready queue dequeue path in mo_task_suspend()
vicLin8712 Oct 19, 2025
5c0fe59
Add ready queue dequeue path in mo_task_cancel()
vicLin8712 Oct 24, 2025
88c9619
Add sched_enqueue_task() in mo_task_resume()
vicLin8712 Oct 24, 2025
dae030a
Add ready queue enqueue path in mo_task_wakeup()
vicLin8712 Oct 19, 2025
9047532
Add sched_migrate_task() helper
vicLin8712 Oct 21, 2025
40cbc78
Use mo_task_migration() in mo_task_priority()
vicLin8712 Oct 22, 2025
df3b2d7
Add idle task and initialization API
vicLin8712 Oct 21, 2025
f80f535
Add sched_switch_to_idle() helper
vicLin8712 Oct 23, 2025
b0ea730
Add sched_switch_to_idle() helper in the scheduler
vicLin8712 Oct 23, 2025
b38a1d0
Add idle_task_init() call in main()
vicLin8712 Oct 23, 2025
7257b07
Refactor launch sequence in main() for scheduler initialization
vicLin8712 Oct 23, 2025
e31e079
Remove first-task binding from task initialization
vicLin8712 Oct 23, 2025
a0c40a0
Add De Bruijn LUT for future O(1) priority selection
vicLin8712 Oct 26, 2025
9e21688
Implement De Bruijn-based top priority helper
vicLin8712 Oct 26, 2025
0b002a8
Use De Brujin-based top priority helper in scheduler
vicLin8712 Oct 26, 2025
3572bea
Add dequeuing ready queue path in _sched_block()
vicLin8712 Nov 5, 2025
29b76cf
Make sched_wakeup_task() globally visible
vicLin8712 Nov 5, 2025
f6b0f58
Add sched_wakeup_task() in mo_sem_signal()
vicLin8712 Nov 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/lib/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,25 @@ static inline void *list_remove(list_t *list, list_node_t *target)
return data;
}

/* Unlink a node from list without freeing node */
static inline void list_unlink(list_t *list, list_node_t *target)
{
if (unlikely(!list || !target || list_is_empty(list)))
return;

list_node_t *prev = list->head;
while (prev->next != list->tail && prev->next != target)
prev = prev->next;

if (unlikely(prev->next != target))
return; /* node not found */

prev->next = target->next;
target->next = NULL;
list->length--;
return;
}

/* Iteration */

/* Callback should return non-NULL to stop early, NULL to continue */
Expand Down
37 changes: 35 additions & 2 deletions include/sys/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ typedef struct tcb {
void *rt_prio; /* Opaque pointer for custom real-time scheduler hook */
} tcb_t;

/* Scheduler attribution */
typedef struct sched {
uint8_t ready_bitmap; /* 8-bit priority bitmap */
list_t
*ready_queues[TASK_PRIORITY_LEVELS]; /* Separate queue per priority */
uint16_t queue_counts[TASK_PRIORITY_LEVELS]; /* O(1) size tracking */

/* Weighted Round-Robin State per Priority Level */
list_node_t *rr_cursors[TASK_PRIORITY_LEVELS]; /* Round-robin position */

/* Hart-Specific Data */
uint8_t hart_id; /* RISC-V hart identifier */
list_node_t *task_idle; /* Idle task */
} sched_t;

/* Kernel Control Block (KCB)
*
* Singleton structure holding global kernel state, including task lists,
Expand All @@ -104,14 +119,15 @@ typedef struct {
/* Timer Management */
list_t *timer_list; /* List of active software timers */
volatile uint32_t ticks; /* Global system tick, incremented by timer */

/* per-hart scheduler management */
sched_t *harts;
} kcb_t;

/* Global pointer to the singleton Kernel Control Block */
extern kcb_t *kcb;

/* System Configuration Constants */
#define SCHED_IMAX \
500 /* Safety limit for scheduler iterations to prevent livelock */
#define MIN_TASK_STACK_SIZE \
256 /* Minimum stack size to prevent stack overflow */
#define TASK_CACHE_SIZE \
Expand Down Expand Up @@ -287,3 +303,20 @@ void _sched_block(queue_t *wait_q);
* Returns 'true' to enable preemptive scheduling, or 'false' for cooperative
*/
int32_t app_main(void);

/* Initialize the idle task
*
* This function statically creates and initializes the idle task structure.
* It should be called once during system startup.
*
* The idle task is a permanent system task that runs when no other
* ready tasks exist. It is never enqueued into any ready queue and
* cannot be suspended, canceled, or priority modified.
*
* Only one idle task exists per hart. Its priority is fixed to the
* lowest level and its time slice is zero.
*/
void idle_task_init(void);

/* Wake up and enqueue task into ready queue */
void sched_wakeup_task(tcb_t *);
25 changes: 11 additions & 14 deletions kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,29 @@ int32_t main(void)
printf("Heap initialized, %u bytes available\n",
(unsigned int) (size_t) &_heap_size);

/* Initialize the first current task as idle sentinel node.
* This ensures a valid entry point before any real task runs.
*/
idle_task_init();
kcb->task_current = kcb->harts->task_idle;

/* Call the application's main entry point to create initial tasks. */
kcb->preemptive = (bool) app_main();
printf("Scheduler mode: %s\n",
kcb->preemptive ? "Preemptive" : "Cooperative");

/* Verify that the application created at least one task.
* If 'kcb->task_current' is still NULL, it means mo_task_spawn was never
* successfully called.
*/
if (!kcb->task_current)
panic(ERR_NO_TASKS);

/* Save the kernel's context. This is a formality to establish a base
* execution context before launching the first real task.
*/
setjmp(kcb->context);

/* Launch the first task.
* 'kcb->task_current' was set by the first call to mo_task_spawn.
* This function transfers control and does not return.
/* Launch the first task (idle task), then scheduler will select highest
* priority task. This function transfers control and does not return.
*/
tcb_t *first_task = kcb->task_current->data;
if (!first_task)
panic(ERR_NO_TASKS);
tcb_t *idle = kcb->task_current->data;
idle->state = TASK_RUNNING;

hal_dispatch_init(first_task->context);
hal_dispatch_init(idle->context);

/* This line should be unreachable. */
panic(ERR_UNKNOWN);
Expand Down
2 changes: 1 addition & 1 deletion kernel/semaphore.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ void mo_sem_signal(sem_t *s)
if (likely(awakened_task)) {
/* Validate awakened task state consistency */
if (likely(awakened_task->state == TASK_BLOCKED)) {
awakened_task->state = TASK_READY;
sched_wakeup_task(awakened_task);
should_yield = true;
} else {
/* Task state inconsistency - this should not happen */
Expand Down
Loading
Loading