Skip to content

Commit a2ebd5e

Browse files
committed
Enable enqueue/dequeue from ready queues
`sched_enqueue_task`/`sched_dequeue_task` also put/remove task from corresponding prior queue and check the length of queue after put/remove task to setup bitmap. bitmap marco used here for simple operation purpose, it can be modified for the further development. The enqueue and dequeue process in `mo_task_spawn`/`sched_select_next_task` are all replaced by `sched_enqueue_task` and `sched_dequeue_task`.
1 parent 901ecbf commit a2ebd5e

File tree

2 files changed

+41
-28
lines changed

2 files changed

+41
-28
lines changed

include/sys/task.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ enum task_states {
5959
#define TASK_TIMESLICE_LOW 10 /* Low priority: longer slice */
6060
#define TASK_TIMESLICE_IDLE 15 /* Idle tasks: longest slice */
6161

62+
/* Bitmap operations */
63+
#define bitmap_check(prio) (kcb->harts->ready_bitmap & 1U << prio)
64+
#define bitmap_set(prio) (kcb->harts->ready_bitmap |= 1U << prio)
65+
#define bitmap_clean(prio) (kcb->harts->ready_bitmap &= ~(1U << prio))
66+
67+
6268
/* Task Control Block (TCB)
6369
*
6470
* Contains all essential information about a single task, including saved
@@ -86,7 +92,7 @@ typedef struct tcb {
8692

8793
/* Scheduler attribution */
8894
typedef struct sched {
89-
volatile uint32_t ready_bitmap; /* 8-bit priority bitmap */
95+
uint32_t ready_bitmap; /* 8-bit priority bitmap */
9096
list_t
9197
*ready_queues[TASK_PRIORITY_LEVELS]; /* Separate queue per priority */
9298
uint16_t queue_counts[TASK_PRIORITY_LEVELS]; /* O(1) size tracking */

kernel/task.c

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,15 @@ static void sched_enqueue_task(tcb_t *task)
357357
/* Ensure task has appropriate time slice for its priority */
358358
task->time_slice = get_priority_timeslice(task->prio_level);
359359
task->state = TASK_READY;
360-
/* Task selection is handled directly through the master task list */
360+
361+
/* Push task into corresponding ready queue and setup bitmap */
362+
CRITICAL_ENTER();
363+
if (!kcb->harts->ready_queues[task->prio_level])
364+
kcb->harts->ready_queues[task->prio_level] = list_create();
365+
366+
list_pushback(kcb->harts->ready_queues[task->prio_level], task);
367+
bitmap_set(task->prio_level);
368+
CRITICAL_LEAVE();
361369
}
362370

363371
/* Remove task from ready queues - state-based approach for compatibility */
@@ -367,9 +375,20 @@ void sched_dequeue_task(tcb_t *task)
367375
return;
368376

369377
/* For tasks that need to be removed from ready state (suspended/cancelled),
370-
* we rely on the state change. The scheduler will skip non-ready tasks
371-
* when it encounters them during the round-robin traversal.
378+
* we rely on the state change. The scheduler will remove it from
379+
* corresponding priority ready queue and setup bitmap by checking remaining
380+
* task count in this queue.
381+
*
382+
* The state of task will be modified by `mo_task_suspended` or
383+
* `mo_task_cancel`.
372384
*/
385+
CRITICAL_ENTER();
386+
list_node_t *node = find_task_node_by_id(task->id);
387+
list_remove(kcb->harts->ready_queues[task->prio_level], node);
388+
389+
if (!kcb->harts->ready_queues[task->prio_level]->length)
390+
bitmap_clean(task->prio_level);
391+
CRITICAL_LEAVE();
373392
}
374393

375394
/* Handle time slice expiration for current task */
@@ -430,32 +449,30 @@ uint16_t sched_select_next_task(void)
430449

431450
/* Mark current task as ready if it was running */
432451
if (current_task->state == TASK_RUNNING)
433-
{
434-
current_task->state = TASK_READY;
435-
list_pushback(kcb->harts->ready_queues[current_task->prio_level], current_task);
436-
kcb->harts->ready_bitmap |= (1U << current_task->prio_level);
437-
}
452+
sched_enqueue_task(current_task);
438453

439454
/* Round-robin search: find next ready task in the master task list */
440455

441456
/* Find highest priority task queue */
442457
uint32_t bitmap = kcb->harts->ready_bitmap;
443458
int highest_prio_level = 0;
444-
for (;!(bitmap & 1U); highest_prio_level++, bitmap >>= 1);
459+
for (; !(bitmap & 1U); highest_prio_level++, bitmap >>= 1)
460+
;
445461

446462
/* Pop out from corresponding queue and mark it as TASK_RUNNING */
447-
list_node_t *node = kcb->harts->ready_queues[highest_prio_level]->head->next;
463+
list_node_t *node =
464+
kcb->harts->ready_queues[highest_prio_level]->head->next;
448465
list_pop(kcb->harts->ready_queues[highest_prio_level]);
449-
((tcb_t *)node->data)->state = TASK_RUNNING;
466+
((tcb_t *) node->data)->state = TASK_RUNNING;
450467
kcb->task_current = node;
451468

452469
/* Check popped queue is empty or not */
453470
if (kcb->harts->ready_queues[highest_prio_level]->length == 0)
454-
kcb->harts->ready_bitmap &= ~(1U << highest_prio_level);
455-
471+
bitmap_clean(highest_prio_level);
472+
456473
if (node)
457-
return 1;
458-
474+
return ((tcb_t *) node->data)->id;
475+
459476
/* No ready tasks found - this should not happen in normal operation */
460477
panic(ERR_NO_TASKS);
461478
return 0;
@@ -613,11 +630,6 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
613630
}
614631
}
615632

616-
/* Create corresponding ready queue */
617-
if (!kcb->harts->ready_queues[tcb->prio_level]) {
618-
kcb->harts->ready_queues[tcb->prio_level] = list_create();
619-
kcb->tasks = list_create();
620-
}
621633

622634
list_node_t *node = list_pushback(kcb->tasks, tcb);
623635
if (!node) {
@@ -631,16 +643,12 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
631643
tcb->id = kcb->next_tid++;
632644
kcb->task_count++; /* Cached count of active tasks for quick access */
633645

634-
/* If tcb is the first task, turn it into TASK_RUNNING state and does not put into ready queue */
646+
/* If tcb is the first task, turn it into TASK_RUNNING state and does not
647+
* put into ready queue */
635648
if (!kcb->task_current) {
636649
kcb->task_current = node;
637650
tcb->state = TASK_RUNNING;
638651
}
639-
else {
640-
/* Setup bitmap and put into corresponding ready queue */
641-
kcb->harts->ready_bitmap |= (1U << tcb->prio_level);
642-
list_pushback(kcb->harts->ready_queues[tcb->prio_level], tcb);
643-
}
644652

645653
CRITICAL_LEAVE();
646654

@@ -747,7 +755,6 @@ int32_t mo_task_suspend(uint16_t id)
747755
CRITICAL_LEAVE();
748756
return ERR_TASK_CANT_SUSPEND;
749757
}
750-
751758
task->state = TASK_SUSPENDED;
752759
bool is_current = (kcb->task_current == node);
753760

0 commit comments

Comments
 (0)