Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
37 changes: 37 additions & 0 deletions include/lib/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,24 @@ static inline list_node_t *list_pushback(list_t *list, void *data)
return node;
}

/* Pushback list node into list */
static inline void list_pushback_node(list_t *list, list_node_t *target)
{
if (unlikely(!list || !target || target->next))
return;

target->next = list->tail;

/* Insert before tail sentinel */
list_node_t *prev = list->head;
while (prev->next != list->tail)
prev = prev->next;

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

static inline void *list_pop(list_t *list)
{
if (unlikely(list_is_empty(list)))
Expand Down Expand Up @@ -134,6 +152,25 @@ static inline void *list_remove(list_t *list, list_node_t *target)
return data;
}

/* Remove a node from list without freeing */
static inline void list_remove_node(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
35 changes: 33 additions & 2 deletions include/sys/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ typedef struct tcb {

/* Real-time Scheduling Support */
void *rt_prio; /* Opaque pointer for custom real-time scheduler hook */

/* State transition support */
/* Ready queue membership node (only one per task) */
list_node_t rq_node;
} tcb_t;

/* Kernel Control Block (KCB)
Expand All @@ -104,14 +108,24 @@ typedef struct {
/* Timer Management */
list_t *timer_list; /* List of active software timers */
volatile uint32_t ticks; /* Global system tick, incremented by timer */

/* Scheduling attribution */
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 */

/* System idle task */
list_node_t task_idle;
} 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 +301,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->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