@@ -357,7 +357,15 @@ static void sched_enqueue_task(tcb_t *task)
357
357
/* Ensure task has appropriate time slice for its priority */
358
358
task -> time_slice = get_priority_timeslice (task -> prio_level );
359
359
task -> state = TASK_READY ;
360
- /* Task selection is handled directly through the master task list */
360
+
361
+ /* Push task into corresponding ready queue and setup bitmap */
362
+ CRITICAL_ENTER ();
363
+ if (!kcb -> harts -> ready_queues [task -> prio_level ])
364
+ kcb -> harts -> ready_queues [task -> prio_level ] = list_create ();
365
+
366
+ list_pushback (kcb -> harts -> ready_queues [task -> prio_level ], task );
367
+ bitmap_set (task -> prio_level );
368
+ CRITICAL_LEAVE ();
361
369
}
362
370
363
371
/* Remove task from ready queues - state-based approach for compatibility */
@@ -367,9 +375,20 @@ void sched_dequeue_task(tcb_t *task)
367
375
return ;
368
376
369
377
/* For tasks that need to be removed from ready state (suspended/cancelled),
370
- * we rely on the state change. The scheduler will skip non-ready tasks
371
- * when it encounters them during the round-robin traversal.
378
+ * we rely on the state change. The scheduler will remove it from
379
+ * corresponding priority ready queue and setup bitmap by checking remaining
380
+ * task count in this queue.
381
+ *
382
+ * The state of task will be modified by `mo_task_suspended` or
383
+ * `mo_task_cancel`.
372
384
*/
385
+ CRITICAL_ENTER ();
386
+ list_node_t * node = find_task_node_by_id (task -> id );
387
+ list_remove (kcb -> harts -> ready_queues [task -> prio_level ], node );
388
+
389
+ if (!kcb -> harts -> ready_queues [task -> prio_level ]-> length )
390
+ bitmap_clean (task -> prio_level );
391
+ CRITICAL_LEAVE ();
373
392
}
374
393
375
394
/* Handle time slice expiration for current task */
@@ -430,32 +449,30 @@ uint16_t sched_select_next_task(void)
430
449
431
450
/* Mark current task as ready if it was running */
432
451
if (current_task -> state == TASK_RUNNING )
433
- {
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
- }
452
+ sched_enqueue_task (current_task );
438
453
439
454
/* Round-robin search: find next ready task in the master task list */
440
455
441
456
/* Find highest priority task queue */
442
457
uint32_t bitmap = kcb -> harts -> ready_bitmap ;
443
458
int highest_prio_level = 0 ;
444
- for (;!(bitmap & 1U ); highest_prio_level ++ , bitmap >>= 1 );
459
+ for (; !(bitmap & 1U ); highest_prio_level ++ , bitmap >>= 1 )
460
+ ;
445
461
446
462
/* 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 ;
463
+ list_node_t * node =
464
+ kcb -> harts -> ready_queues [highest_prio_level ]-> head -> next ;
448
465
list_pop (kcb -> harts -> ready_queues [highest_prio_level ]);
449
- ((tcb_t * )node -> data )-> state = TASK_RUNNING ;
466
+ ((tcb_t * ) node -> data )-> state = TASK_RUNNING ;
450
467
kcb -> task_current = node ;
451
468
452
469
/* Check popped queue is empty or not */
453
470
if (kcb -> harts -> ready_queues [highest_prio_level ]-> length == 0 )
454
- kcb -> harts -> ready_bitmap &= ~( 1U << highest_prio_level );
455
-
471
+ bitmap_clean ( highest_prio_level );
472
+
456
473
if (node )
457
- return 1 ;
458
-
474
+ return (( tcb_t * ) node -> data ) -> id ;
475
+
459
476
/* No ready tasks found - this should not happen in normal operation */
460
477
panic (ERR_NO_TASKS );
461
478
return 0 ;
@@ -613,11 +630,6 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
613
630
}
614
631
}
615
632
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
633
622
634
list_node_t * node = list_pushback (kcb -> tasks , tcb );
623
635
if (!node ) {
@@ -631,16 +643,12 @@ int32_t mo_task_spawn(void *task_entry, uint16_t stack_size_req)
631
643
tcb -> id = kcb -> next_tid ++ ;
632
644
kcb -> task_count ++ ; /* Cached count of active tasks for quick access */
633
645
634
- /* If tcb is the first task, turn it into TASK_RUNNING state and does not put into ready queue */
646
+ /* If tcb is the first task, turn it into TASK_RUNNING state and does not
647
+ * put into ready queue */
635
648
if (!kcb -> task_current ) {
636
649
kcb -> task_current = node ;
637
650
tcb -> state = TASK_RUNNING ;
638
651
}
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
- }
644
652
645
653
CRITICAL_LEAVE ();
646
654
@@ -747,7 +755,6 @@ int32_t mo_task_suspend(uint16_t id)
747
755
CRITICAL_LEAVE ();
748
756
return ERR_TASK_CANT_SUSPEND ;
749
757
}
750
-
751
758
task -> state = TASK_SUSPENDED ;
752
759
bool is_current = (kcb -> task_current == node );
753
760
0 commit comments