15
15
static int32_t noop_rtsched (void );
16
16
void _timer_tick_handler (void );
17
17
18
+ /* hart 0 scheduler */
19
+ static sched_t hart0_sched = {
20
+ .ready_bitmap = 0 ,
21
+ .ready_queues = {NULL },
22
+ .rr_cursors = {NULL },
23
+ .quantum_cycles = {0 },
24
+ .last_selected_prio = 0 ,
25
+ .local_switches = 0 ,
26
+ .current_task = NULL ,
27
+ .hart_id = 0 ,
28
+ };
29
+
18
30
/* Kernel-wide control block (KCB) */
19
31
static kcb_t kernel_state = {
20
32
.tasks = NULL ,
@@ -25,6 +37,7 @@ static kcb_t kernel_state = {
25
37
.task_count = 0 ,
26
38
.ticks = 0 ,
27
39
.preemptive = true, /* Default to preemptive mode */
40
+ .harts = & hart0_sched ,
28
41
};
29
42
kcb_t * kcb = & kernel_state ;
30
43
@@ -344,7 +357,6 @@ static void sched_enqueue_task(tcb_t *task)
344
357
/* Ensure task has appropriate time slice for its priority */
345
358
task -> time_slice = get_priority_timeslice (task -> prio_level );
346
359
task -> state = TASK_READY ;
347
-
348
360
/* Task selection is handled directly through the master task list */
349
361
}
350
362
@@ -418,34 +430,32 @@ uint16_t sched_select_next_task(void)
418
430
419
431
/* Mark current task as ready if it was running */
420
432
if (current_task -> state == TASK_RUNNING )
433
+ {
421
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
+ }
422
438
423
439
/* Round-robin search: find next ready task in the master task list */
424
- list_node_t * start_node = kcb -> task_current ;
425
- list_node_t * node = start_node ;
426
- int iterations = 0 ; /* Safety counter to prevent infinite loops */
427
-
428
- do {
429
- /* Move to next task (circular) */
430
- node = list_cnext (kcb -> tasks , node );
431
- if (!node || !node -> data )
432
- continue ;
433
-
434
- tcb_t * task = node -> data ;
435
-
436
- /* Skip non-ready tasks */
437
- if (task -> state != TASK_READY )
438
- continue ;
439
-
440
- /* Found a ready task */
441
- kcb -> task_current = node ;
442
- task -> state = TASK_RUNNING ;
443
- task -> time_slice = get_priority_timeslice (task -> prio_level );
444
-
445
- return task -> id ;
446
-
447
- } while (node != start_node && ++ iterations < SCHED_IMAX );
448
440
441
+ /* Find highest priority task queue */
442
+ uint32_t bitmap = kcb -> harts -> ready_bitmap ;
443
+ int highest_prio_level = 0 ;
444
+ for (;!(bitmap & 1U ); highest_prio_level ++ , bitmap >>= 1 );
445
+
446
+ /* 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 ;
448
+ list_pop (kcb -> harts -> ready_queues [highest_prio_level ]);
449
+ ((tcb_t * )node -> data )-> state = TASK_RUNNING ;
450
+ kcb -> task_current = node ;
451
+
452
+ /* Check popped queue is empty or not */
453
+ if (kcb -> harts -> ready_queues [highest_prio_level ]-> length == 0 )
454
+ kcb -> harts -> ready_bitmap &= ~(1U << highest_prio_level );
455
+
456
+ if (node )
457
+ return 1 ;
458
+
449
459
/* No ready tasks found - this should not happen in normal operation */
450
460
panic (ERR_NO_TASKS );
451
461
return 0 ;
@@ -603,6 +613,12 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
603
613
}
604
614
}
605
615
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
+ }
621
+
606
622
list_node_t * node = list_pushback (kcb -> tasks , tcb );
607
623
if (!node ) {
608
624
CRITICAL_LEAVE ();
@@ -615,8 +631,16 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
615
631
tcb -> id = kcb -> next_tid ++ ;
616
632
kcb -> task_count ++ ; /* Cached count of active tasks for quick access */
617
633
618
- if (!kcb -> task_current )
634
+ /* If tcb is the first task, turn it into TASK_RUNNING state and does not put into ready queue */
635
+ if (!kcb -> task_current ) {
619
636
kcb -> task_current = node ;
637
+ tcb -> state = TASK_RUNNING ;
638
+ }
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
+ }
620
644
621
645
CRITICAL_LEAVE ();
622
646
@@ -630,8 +654,10 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
630
654
631
655
/* Add to cache and mark ready */
632
656
cache_task (tcb -> id , tcb );
633
- sched_enqueue_task (tcb );
634
657
658
+ /* Active task from TASK_STOPPED state */
659
+ if (tcb -> state == TASK_STOPPED )
660
+ sched_enqueue_task (tcb );
635
661
return tcb -> id ;
636
662
}
637
663
0 commit comments