vm.c: integrate task scheduler with vm dispatch loop

modify END_DISPATCH macro to check for context switches after each
bytecode instruction. when switching flag is set or task has stopped,
return from mrb_vm_exec to yield control back to scheduler.

add TASK_STOP macro to mark task completion in OP_STOP instruction.
this allows scheduler to detect when tasks finish execution.

the integration enables cooperative preemption at bytecode granularity
while maintaining compatibility with non-task builds.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2025-10-04 13:22:11 +09:00
parent 1b69b33a4e
commit 9ea37745ac
+23
View File
@@ -1521,7 +1521,14 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci
#define CASE(insn,ops) case insn: { const mrb_code *pc = ci->pc+1; FETCH_ ## ops (); ci->pc = pc; } L_ ## insn ## _BODY:
#define NEXT goto L_END_DISPATCH
#define JUMP NEXT
#ifdef MRB_USE_TASK_SCHEDULER
#define END_DISPATCH L_END_DISPATCH: \
if (mrb->task->switching || mrb->c->status == MRB_TASK_STOPPED) \
return mrb_nil_value(); \
}}
#else
#define END_DISPATCH L_END_DISPATCH:;}}
#endif
#else
@@ -1530,10 +1537,24 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const mrb_callinfo *return_ci
#define NEXT insn=BYTECODE_DECODER(*ci->pc); CODE_FETCH_HOOK(mrb, irep, ci->pc, regs); goto *optable[insn]
#define JUMP NEXT
#ifdef MRB_USE_TASK_SCHEDULER
#define END_DISPATCH \
if (mrb->task->switching || mrb->c->status == MRB_TASK_STOPPED) \
return mrb_nil_value();
#else
#define END_DISPATCH
#endif
#endif
#ifdef MRB_USE_TASK_SCHEDULER
#define TASK_STOP(mrb) \
if (mrb->c->status == MRB_TASK_CREATED) \
mrb->c->status = MRB_TASK_STOPPED;
#else
#define TASK_STOP(mrb)
#endif
/**
* @brief Executes a mruby bytecode sequence (iseq) within the VM.
*
@@ -3342,9 +3363,11 @@ RETRY_TRY_BLOCK:
mrb->jmp = prev_jmp;
if (!mrb_nil_p(v)) {
mrb->exc = mrb_obj_ptr(v);
TASK_STOP(mrb);
return v;
}
mrb->exc = NULL;
TASK_STOP(mrb);
return regs[irep->nlocals];
}
}