@@ -471,16 +471,15 @@ void _sched_block_enqueue(tcb_t *blocked_task)
471471 *
472472 * Selects the next ready task using circular traversal of the master task list.
473473 *
474- * Complexity: O(n) where n = number of tasks
475- * - Best case: O(1) when next task in sequence is ready
476- * - Worst case: O(n) when only one task is ready and it's the last checked
477- * - Typical case: O(k) where k << n (number of non-ready tasks to skip)
474+ * Complexity: O(1)
475+ * - Always constant-time selection, regardless of total task count.
476+ * - No need to traverse the task list.
478477 *
479478 * Performance characteristics:
480- * - Excellent for small-to-medium task counts (< 50 tasks)
481- * - Simple and reliable implementation
482- * - Good cache locality due to sequential list traversal
483- * - Priority-aware time slice allocation
479+ * - Ideal for systems with frequent context switches or many tasks.
480+ * - Excellent cache locality: only touches nodes in the active ready queue.
481+ * - Priority-aware: highest non-empty ready queue is chosen via bitmap lookup.
482+ * - Each priority level maintains its own rr_cursor to ensure fair rotation.
484483 */
485484uint16_t sched_select_next_task (void )
486485{
@@ -493,53 +492,35 @@ uint16_t sched_select_next_task(void)
493492 if (current_task -> state == TASK_RUNNING )
494493 current_task -> state = TASK_READY ;
495494
496- /* Round-robin search: find next ready task in the master task list */
497- list_node_t * start_node = kcb -> task_current ;
498- list_node_t * node = start_node ;
499- int iterations = 0 ; /* Safety counter to prevent infinite loops */
500-
501- do {
502- /* Move to next task (circular) */
503- node = list_cnext (kcb -> tasks , node );
504- if (!node || !node -> data )
505- continue ;
506-
507- tcb_t * task = node -> data ;
495+ /* Bitmap search, from bit0 (highest priority level) to bit7 (lowest
496+ * priority level) */
497+ uint32_t bitmap = kcb -> ready_bitmap ;
498+ uint8_t top_prio_level = 0 ;
499+ while (top_prio_level < 8 ) {
500+ if (bitmap & 1U )
501+ break ;
502+ bitmap >>= 1 ;
503+ top_prio_level ++ ;
504+ }
508505
509- /* Skip non-ready tasks */
510- if (task -> state != TASK_READY )
511- continue ;
506+ list_node_t * * cursor = & kcb -> rr_cursors [top_prio_level ];
507+ list_t * rq = kcb -> ready_queues [top_prio_level ];
508+ if (unlikely (!rq || !* cursor ))
509+ panic (ERR_NO_TASKS );
512510
513- /* Found a ready task */
514- kcb -> task_current = node ;
515- task -> state = TASK_RUNNING ;
516- task -> time_slice = get_priority_timeslice (task -> prio_level );
511+ /* Update next task with top priority cursor */
512+ kcb -> task_current = * cursor ;
517513
518- return task -> id ;
514+ /* Advance top priority cursor to next task node */
515+ * cursor = list_cnext (rq , * cursor );
519516
520- } while (node != start_node && ++ iterations < SCHED_IMAX );
517+ /* Update new task properties */
518+ tcb_t * new_task = kcb -> task_current -> data ;
519+ new_task -> time_slice = get_priority_timeslice (new_task -> prio_level );
520+ new_task -> state = TASK_RUNNING ;
521521
522- /* No ready tasks found in preemptive mode - all tasks are blocked.
523- * This is normal for periodic RT tasks waiting for their next period.
524- * We CANNOT return a BLOCKED task as that would cause it to run.
525- * Instead, find ANY task (even blocked) as a placeholder, then wait for
526- * interrupt.
527- */
528- if (kcb -> preemptive ) {
529- /* Select any task as placeholder (dispatcher won't actually switch to
530- * it if blocked) */
531- list_node_t * any_node = list_next (kcb -> tasks -> head );
532- while (any_node && any_node != kcb -> tasks -> tail ) {
533- if (any_node -> data ) {
534- kcb -> task_current = any_node ;
535- tcb_t * any_task = any_node -> data ;
536- return any_task -> id ;
537- }
538- any_node = list_next (any_node );
539- }
540- /* No tasks at all - this is a real error */
541- panic (ERR_NO_TASKS );
542- }
522+ if (kcb -> task_current )
523+ return new_task -> id ;
543524
544525 /* In cooperative mode, having no ready tasks is an error */
545526 panic (ERR_NO_TASKS );
0 commit comments