Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ on:
push:
branches:
- main
- o1-sched-lauch
pull_request:
branches:
- main
- main

# Cancel in-progress runs for the same PR/branch
concurrency:
Expand Down
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
20 changes: 18 additions & 2 deletions include/sys/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ typedef struct tcb {

/* Stack Protection */
uint32_t canary; /* Random stack canary for overflow detection */

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

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

/* Scheduling attributions */
uint8_t ready_bitmap; /* 8-bit priority bitmap */
list_t
*ready_queues[TASK_PRIORITY_LEVELS]; /* Separate queue per priority */
list_node_t *rr_cursors[TASK_PRIORITY_LEVELS]; /* Round-robin position */
} 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 @@ -288,6 +296,14 @@ uint64_t mo_uptime(void);
*/
void _sched_block(queue_t *wait_q);

/* Dequeue path for task with TASK_BLOCKED state. It must be called before task
* state set as TASK_BLOCKED. Currently, this API is used in mutex lock case.*/
void _sched_block_dequeue(tcb_t *blocked_task);

/* Enqueue path for the task with TASK_BLOCKED state. This API is the mainly
* enqueuing path for semaphore and mutex operations. */
void _sched_block_enqueue(tcb_t *blocked_task);

/* Application Entry Point */

/* The main entry point for the user application.
Expand Down
19 changes: 11 additions & 8 deletions kernel/mutex.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ static void mutex_block_atomic(list_t *waiters)
/* Add to waiters list */
if (unlikely(!list_pushback(waiters, self)))
panic(ERR_SEM_OPERATION);

/* Block and yield atomically */
self->state = TASK_BLOCKED;

/* Explicit remove list node from the ready queue */
_sched_block_dequeue(self);
_yield(); /* This releases NOSCHED when we context switch */
}

Expand Down Expand Up @@ -241,7 +244,7 @@ int32_t mo_mutex_timedlock(mutex_t *m, uint32_t ticks)
if (self->state == TASK_BLOCKED) {
/* We woke up due to timeout, not mutex unlock */
if (remove_self_from_waiters(m->waiters)) {
self->state = TASK_READY;
_sched_block_enqueue(self);
result = ERR_TIMEOUT;
} else {
/* Race condition: we were both timed out and unlocked */
Expand Down Expand Up @@ -283,7 +286,7 @@ int32_t mo_mutex_unlock(mutex_t *m)
/* Validate task state before waking */
if (likely(next_owner->state == TASK_BLOCKED)) {
m->owner_tid = next_owner->id;
next_owner->state = TASK_READY;
_sched_block_enqueue(next_owner);
/* Clear any pending timeout since we're granting ownership */
next_owner->delay = 0;
} else {
Expand Down Expand Up @@ -396,7 +399,7 @@ int32_t mo_cond_wait(cond_t *c, mutex_t *m)
/* Failed to unlock - remove from wait list and restore state */
NOSCHED_ENTER();
remove_self_from_waiters(c->waiters);
self->state = TASK_READY;
_sched_block_enqueue(self);
NOSCHED_LEAVE();
return unlock_result;
}
Expand Down Expand Up @@ -439,7 +442,7 @@ int32_t mo_cond_timedwait(cond_t *c, mutex_t *m, uint32_t ticks)
/* Failed to unlock - cleanup and restore */
NOSCHED_ENTER();
remove_self_from_waiters(c->waiters);
self->state = TASK_READY;
_sched_block_enqueue(self);
self->delay = 0;
NOSCHED_LEAVE();
return unlock_result;
Expand All @@ -455,7 +458,7 @@ int32_t mo_cond_timedwait(cond_t *c, mutex_t *m, uint32_t ticks)
if (self->state == TASK_BLOCKED) {
/* Timeout occurred - remove from wait list */
remove_self_from_waiters(c->waiters);
self->state = TASK_READY;
_sched_block_enqueue(self);
self->delay = 0;
wait_status = ERR_TIMEOUT;
} else {
Expand Down Expand Up @@ -484,7 +487,7 @@ int32_t mo_cond_signal(cond_t *c)
if (likely(waiter)) {
/* Validate task state before waking */
if (likely(waiter->state == TASK_BLOCKED)) {
waiter->state = TASK_READY;
_sched_block_enqueue(waiter);
/* Clear any pending timeout since we're signaling */
waiter->delay = 0;
} else {
Expand All @@ -511,7 +514,7 @@ int32_t mo_cond_broadcast(cond_t *c)
if (likely(waiter)) {
/* Validate task state before waking */
if (likely(waiter->state == TASK_BLOCKED)) {
waiter->state = TASK_READY;
_sched_block_enqueue(waiter);
/* Clear any pending timeout since we're broadcasting */
waiter->delay = 0;
} else {
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_block_enqueue(awakened_task);
should_yield = true;
} else {
/* Task state inconsistency - this should not happen */
Expand Down
Loading
Loading