@@ -525,20 +525,20 @@ static inline tcb_t *sched_switch_to_idle(void)
525525 return idle ;
526526}
527527
528- /* Efficient Round-Robin Task Selection with O(n ) Complexity
528+ /* Efficient Round-Robin Task Selection (Cursor-Based, O(1 ) Complexity)
529529 *
530- * Selects the next ready task using circular traversal of the master task list.
530+ * Selects the next ready task by advancing the per-priority round-robin
531+ * cursor (rr_cursor) circularly using list API list_cnext().
531532 *
532- * Complexity: O(n) where n = number of tasks
533- * - Best case: O(1) when next task in sequence is ready
534- * - Worst case: O(n) when only one task is ready and it's the last checked
535- * - Typical case: O(k) where k << n (number of non-ready tasks to skip)
533+ * Complexity: O(1)
534+ * - Always constant-time selection, regardless of total task count.
535+ * - No need to traverse the task list.
536536 *
537537 * Performance characteristics:
538- * - Excellent for small-to-medium task counts (< 50 tasks)
539- * - Simple and reliable implementation
540- * - Good cache locality due to sequential list traversal
541- * - Priority-aware time slice allocation
538+ * - Ideal for systems with frequent context switches or many tasks.
539+ * - Excellent cache locality: only touches nodes in the active ready queue.
540+ * - Priority-aware: highest non-empty ready queue is chosen via bitmap lookup.
541+ * - Each priority level maintains its own rr_cursor to ensure fair rotation.
542542 */
543543uint16_t sched_select_next_task (void )
544544{
@@ -551,53 +551,36 @@ uint16_t sched_select_next_task(void)
551551 if (current_task -> state == TASK_RUNNING )
552552 current_task -> state = TASK_READY ;
553553
554- /* Round-robin search: find next ready task in the master task list */
555- list_node_t * start_node = kcb -> task_current ;
556- list_node_t * node = start_node ;
557- int iterations = 0 ; /* Safety counter to prevent infinite loops */
554+ /* Check out bitmap */
555+ uint32_t bitmap = kcb -> ready_bitmap ;
558556
559- do {
560- /* Move to next task (circular) */
561- node = list_cnext ( kcb -> tasks , node );
562- if (! node || ! node -> data )
563- continue ;
557+ /* If no available ready queue found in bitmap - all tasks blocked, the
558+ * scheduler will switch to system idle task and wait for next timer
559+ * interrupt*/
560+ if (unlikely (! bitmap ) )
561+ return sched_switch_to_idle () -> id ;
564562
565- tcb_t * task = node -> data ;
563+ /* Find top priority ready queue */
564+ uint8_t top_prio_level = find_highest_ready_priority (bitmap );
566565
567- /* Skip non-ready tasks */
568- if (task -> state != TASK_READY )
569- continue ;
566+ list_node_t * * cursor = & kcb -> rr_cursors [top_prio_level ];
567+ list_t * rq = kcb -> ready_queues [top_prio_level ];
568+ if (unlikely (!rq || !* cursor ))
569+ panic (ERR_NO_TASKS );
570570
571- /* Found a ready task */
572- kcb -> task_current = node ;
573- task -> state = TASK_RUNNING ;
574- task -> time_slice = get_priority_timeslice (task -> prio_level );
571+ /* Update next task with top priority cursor */
572+ kcb -> task_current = * cursor ;
575573
576- return task -> id ;
574+ /* Advance top priority cursor to next task node */
575+ * cursor = list_cnext (rq , * cursor );
577576
578- } while (node != start_node && ++ iterations < SCHED_IMAX );
577+ /* Update new task properties */
578+ tcb_t * new_task = kcb -> task_current -> data ;
579+ new_task -> time_slice = get_priority_timeslice (new_task -> prio_level );
580+ new_task -> state = TASK_RUNNING ;
579581
580- /* No ready tasks found in preemptive mode - all tasks are blocked.
581- * This is normal for periodic RT tasks waiting for their next period.
582- * We CANNOT return a BLOCKED task as that would cause it to run.
583- * Instead, find ANY task (even blocked) as a placeholder, then wait for
584- * interrupt.
585- */
586- if (kcb -> preemptive ) {
587- /* Select any task as placeholder (dispatcher won't actually switch to
588- * it if blocked) */
589- list_node_t * any_node = list_next (kcb -> tasks -> head );
590- while (any_node && any_node != kcb -> tasks -> tail ) {
591- if (any_node -> data ) {
592- kcb -> task_current = any_node ;
593- tcb_t * any_task = any_node -> data ;
594- return any_task -> id ;
595- }
596- any_node = list_next (any_node );
597- }
598- /* No tasks at all - this is a real error */
599- panic (ERR_NO_TASKS );
600- }
582+ if (kcb -> task_current )
583+ return new_task -> id ;
601584
602585 /* In cooperative mode, having no ready tasks is an error */
603586 panic (ERR_NO_TASKS );
0 commit comments