static VALUE rb_cont_call(int argc, VALUE *argv, VALUE contval) { rb_context_t *cont; rb_thread_t *th = GET_THREAD(); GetContPtr(contval, cont); if (cont->saved_thread.self != th->self) { rb_raise(rb_eRuntimeError, "continuation called across threads"); } if (cont->saved_thread.trap_tag != th->trap_tag) { rb_raise(rb_eRuntimeError, "continuation called across trap"); } if (cont->saved_thread.fiber) { rb_context_t *fcont; GetContPtr(cont->saved_thread.fiber, fcont); if (th->fiber != cont->saved_thread.fiber) { rb_raise(rb_eRuntimeError, "continuation called across fiber"); } } cont->argc = argc; cont->value = make_passing_arg(argc, argv); cont_restore_0(cont, &contval); return Qnil; /* unreachable */ }
static inline VALUE fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume) { VALUE value; rb_context_t *cont; rb_thread_t *th = GET_THREAD(); GetContPtr(fib, cont); if (cont->saved_thread.self != th->self) { rb_raise(rb_eFiberError, "fiber called across threads"); } else if (cont->saved_thread.trap_tag != th->trap_tag) { rb_raise(rb_eFiberError, "fiber called across trap"); } else if (!cont->alive) { rb_raise(rb_eFiberError, "dead fiber called"); } if (is_resume) { cont->prev = rb_fiber_current(); } cont->value = make_passing_arg(argc, argv); if ((value = fiber_store(cont)) == Qundef) { cont_restore_0(cont, &value); rb_bug("rb_fiber_resume: unreachable"); } RUBY_VM_CHECK_INTS(); return value; }
static void cont_restore_0(rb_context_t *cont, VALUE *addr_in_prev_frame) { if (cont->machine_stack_src) { #define STACK_PAD_SIZE 1024 VALUE space[STACK_PAD_SIZE]; #if STACK_GROW_DIRECTION < 0 /* downward */ if (addr_in_prev_frame > cont->machine_stack_src) { cont_restore_0(cont, &space[0]); } #elif STACK_GROW_DIRECTION > 0 /* upward */ if (addr_in_prev_frame < cont->machine_stack_src + cont->machine_stack_size) { cont_restore_0(cont, &space[STACK_PAD_SIZE-1]); } #else if (addr_in_prev_frame > &space[0]) { /* Stack grows downward */ if (addr_in_prev_frame > cont->machine_stack_src) { cont_restore_0(cont, &space[0]); } } else { /* Stack grows upward */ if (addr_in_prev_frame < cont->machine_stack_src + cont->machine_stack_size) { cont_restore_0(cont, &space[STACK_PAD_SIZE-1]); } } #endif } #ifdef __ia64 register_stack_extend(cont, (VALUE*)rb_ia64_bsp()); #else cont_restore_1(cont); #endif }