@@ -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,39 @@ 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 ;
495+ /* Bitmap search, from bit0 (highest priority level) to bit7 (lowest
496+ * priority level) */
497+ uint8_t bitmap = kcb -> ready_bitmap ;
498+ if ( unlikely ( bitmap == 0 ))
499+ panic ( ERR_NO_TASKS );
500+
501+ uint8_t top_prio_level = 0 ;
502+ while ( top_prio_level < TASK_PRIORITY_LEVELS ) {
503+ if (bitmap & 1U )
504+ break ;
506505
507- tcb_t * task = node -> data ;
506+ bitmap >>= 1 ;
507+ top_prio_level ++ ;
508+ }
508509
509- /* Skip non-ready tasks */
510- if (task -> state != TASK_READY )
511- continue ;
510+ list_node_t * * cursor = & kcb -> rr_cursors [top_prio_level ];
511+ list_t * rq = kcb -> ready_queues [top_prio_level ];
512+ if (unlikely (!rq || !* cursor ))
513+ panic (ERR_NO_TASKS );
512514
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 );
515+ /* Update next task with top priority cursor */
516+ kcb -> task_current = * cursor ;
517517
518- return task -> id ;
518+ /* Advance top priority cursor to next task node */
519+ * cursor = list_cnext (rq , * cursor );
519520
520- } while (node != start_node && ++ iterations < SCHED_IMAX );
521+ /* Update new task properties */
522+ tcb_t * new_task = kcb -> task_current -> data ;
523+ new_task -> time_slice = get_priority_timeslice (new_task -> prio_level );
524+ new_task -> state = TASK_RUNNING ;
521525
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- }
526+ if (kcb -> task_current )
527+ return new_task -> id ;
543528
544529 /* In cooperative mode, having no ready tasks is an error */
545530 panic (ERR_NO_TASKS );
0 commit comments