@@ -457,16 +457,15 @@ void sched_wakeup_task(tcb_t *task)
457457 *
458458 * Selects the next ready task using circular traversal of the master task list.
459459 *
460- * Complexity: O(n) where n = number of tasks
461- * - Best case: O(1) when next task in sequence is ready
462- * - Worst case: O(n) when only one task is ready and it's the last checked
463- * - Typical case: O(k) where k << n (number of non-ready tasks to skip)
460+ * Complexity: O(1)
461+ * - Always constant-time selection, regardless of total task count.
462+ * - No need to traverse the task list.
464463 *
465464 * Performance characteristics:
466- * - Excellent for small-to-medium task counts (< 50 tasks)
467- * - Simple and reliable implementation
468- * - Good cache locality due to sequential list traversal
469- * - Priority-aware time slice allocation
465+ * - Ideal for systems with frequent context switches or many tasks.
466+ * - Excellent cache locality: only touches nodes in the active ready queue.
467+ * - Priority-aware: highest non-empty ready queue is chosen via bitmap lookup.
468+ * - Each priority level maintains its own rr_cursor to ensure fair rotation.
470469 */
471470uint16_t sched_select_next_task (void )
472471{
@@ -479,53 +478,35 @@ uint16_t sched_select_next_task(void)
479478 if (current_task -> state == TASK_RUNNING )
480479 current_task -> state = TASK_READY ;
481480
482- /* Round-robin search: find next ready task in the master task list */
483- list_node_t * start_node = kcb -> task_current ;
484- list_node_t * node = start_node ;
485- int iterations = 0 ; /* Safety counter to prevent infinite loops */
486-
487- do {
488- /* Move to next task (circular) */
489- node = list_cnext (kcb -> tasks , node );
490- if (!node || !node -> data )
491- continue ;
492-
493- tcb_t * task = node -> data ;
481+ /* Bitmap search, from bit0 (highest priority level) to bit7 (lowest
482+ * priority level) */
483+ uint32_t bitmap = kcb -> ready_bitmap ;
484+ uint8_t top_prio_level = 0 ;
485+ while (top_prio_level < 8 ) {
486+ if (bitmap & 1U )
487+ break ;
488+ bitmap >>= 1 ;
489+ top_prio_level ++ ;
490+ }
494491
495- /* Skip non-ready tasks */
496- if (task -> state != TASK_READY )
497- continue ;
492+ list_node_t * * cursor = & kcb -> rr_cursors [top_prio_level ];
493+ list_t * rq = kcb -> ready_queues [top_prio_level ];
494+ if (unlikely (!rq || !* cursor ))
495+ panic (ERR_NO_TASKS );
498496
499- /* Found a ready task */
500- kcb -> task_current = node ;
501- task -> state = TASK_RUNNING ;
502- task -> time_slice = get_priority_timeslice (task -> prio_level );
497+ /* Update next task with top priority cursor */
498+ kcb -> task_current = * cursor ;
503499
504- return task -> id ;
500+ /* Advance top priority cursor to next task node */
501+ * cursor = list_cnext (rq , * cursor );
505502
506- } while (node != start_node && ++ iterations < SCHED_IMAX );
503+ /* Update new task properties */
504+ tcb_t * new_task = kcb -> task_current -> data ;
505+ new_task -> time_slice = get_priority_timeslice (new_task -> prio_level );
506+ new_task -> state = TASK_RUNNING ;
507507
508- /* No ready tasks found in preemptive mode - all tasks are blocked.
509- * This is normal for periodic RT tasks waiting for their next period.
510- * We CANNOT return a BLOCKED task as that would cause it to run.
511- * Instead, find ANY task (even blocked) as a placeholder, then wait for
512- * interrupt.
513- */
514- if (kcb -> preemptive ) {
515- /* Select any task as placeholder (dispatcher won't actually switch to
516- * it if blocked) */
517- list_node_t * any_node = list_next (kcb -> tasks -> head );
518- while (any_node && any_node != kcb -> tasks -> tail ) {
519- if (any_node -> data ) {
520- kcb -> task_current = any_node ;
521- tcb_t * any_task = any_node -> data ;
522- return any_task -> id ;
523- }
524- any_node = list_next (any_node );
525- }
526- /* No tasks at all - this is a real error */
527- panic (ERR_NO_TASKS );
528- }
508+ if (kcb -> task_current )
509+ return new_task -> id ;
529510
530511 /* In cooperative mode, having no ready tasks is an error */
531512 panic (ERR_NO_TASKS );
0 commit comments