Fix mrb_task_run to prevent returning unexpectedly

Old code:

```c
t = q_ready_;

/* No task ready - check if all tasks are done */
if (!t) {
  /* If there are tasks waiting or suspended, idle */
  if (q_waiting_ || q_suspended_) {
    mrb_hal_task_idle_cpu(mrb);
    continue;
```

IRQ possibly happens between `t = q_ready_;` and `if (q_waiting_ || q_suspended_) {` and, for example, a waiting task may move to the ready queue.
As a result, the infinite loop in mrb_task_run unexpectedly breaks in spite of not all the task is dormant.
This patch fixes the issue above by setting the `exitting` condition with a critical section.
This commit is contained in:
HASUMI Hitoshi
2026-02-13 13:34:54 +09:00
parent 8c99e3dd29
commit cfcd86fd9b
+9 -6
View File
@@ -459,13 +459,16 @@ mrb_task_run(mrb_state *mrb)
/* No task ready - check if all tasks are done */
if (!t) {
/* If there are tasks waiting or suspended, idle */
if (q_waiting_ || q_suspended_) {
mrb_hal_task_idle_cpu(mrb);
continue;
mrb_task_disable_irq();
mrb_bool exitting = !q_ready_ && !q_waiting_ && !q_suspended_;
mrb_task_enable_irq();
if (exitting) {
/* All tasks are dormant - scheduler done */
break;
}
/* All tasks are dormant - scheduler done */
break;
/* If there are tasks waiting or suspended, idle */
mrb_hal_task_idle_cpu(mrb);
continue;
}
/* Safety check - don't execute terminated tasks */