diff --git a/mrbgems/mruby-task/src/task.c b/mrbgems/mruby-task/src/task.c index 9662ffdfc..695f6f81c 100644 --- a/mrbgems/mruby-task/src/task.c +++ b/mrbgems/mruby-task/src/task.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -443,6 +444,8 @@ mrb_tick(mrb_state *mrb) MRB_API mrb_value mrb_task_run(mrb_state *mrb) { + struct mrb_jmpbuf *prev_jmp; + struct mrb_jmpbuf c_jmp; mrb_task *t; if (mrb->task.loop_running) { @@ -450,41 +453,51 @@ mrb_task_run(mrb_state *mrb) } mrb->task.loop_running = TRUE; - while (1) { - t = q_ready_; + prev_jmp = mrb->jmp; + MRB_TRY(&c_jmp) { + mrb->jmp = &c_jmp; - /* No task ready - check if all tasks are done */ - if (!t) { - mrb_task_disable_irq(); - mrb_bool exiting = !q_ready_ && !q_waiting_ && !q_suspended_; - mrb_task_enable_irq(); - if (exiting) { - /* All tasks are dormant - scheduler done */ - break; + while (1) { + t = q_ready_; + + /* No task ready - check if all tasks are done */ + if (!t) { + mrb_task_disable_irq(); + mrb_bool exiting = !q_ready_ && !q_waiting_ && !q_suspended_; + mrb_task_enable_irq(); + if (exiting) { + /* All tasks are dormant - scheduler done */ + break; + } + /* If there are tasks waiting or suspended, idle */ + mrb_hal_task_idle_cpu(mrb); + continue; } - /* If there are tasks waiting or suspended, idle */ - mrb_hal_task_idle_cpu(mrb); - continue; - } - /* Safety check - don't execute terminated tasks */ - if (task_cleanup_if_stopped(mrb, t)) { - continue; - } + /* Safety check - don't execute terminated tasks */ + if (task_cleanup_if_stopped(mrb, t)) { + continue; + } - /* Execute task using core logic */ - execute_task(mrb, t); + /* Execute task using core logic */ + execute_task(mrb, t); - /* Move to end of ready queue if still running (round-robin) */ - if (t->status == MRB_TASK_STATUS_READY) { - task_change_state(mrb, t, MRB_TASK_STATUS_READY); - } + /* Move to end of ready queue if still running (round-robin) */ + if (t->status == MRB_TASK_STATUS_READY) { + task_change_state(mrb, t, MRB_TASK_STATUS_READY); + } - /* Run incremental GC if active */ - if (mrb->gc.state != MRB_GC_STATE_ROOT) { - mrb_incremental_gc(mrb); + /* Run incremental GC if active */ + if (mrb->gc.state != MRB_GC_STATE_ROOT) { + mrb_incremental_gc(mrb); + } } - } + mrb->jmp = prev_jmp; + } MRB_CATCH(&c_jmp) { + mrb->task.loop_running = FALSE; + mrb->jmp = prev_jmp; + MRB_THROW(prev_jmp); + } MRB_END_EXC(&c_jmp); mrb->task.loop_running = FALSE; return mrb_nil_value();