예제 #1
0
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 */
}
예제 #2
0
파일: cont.c 프로젝트: genki/ruby
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;
}
예제 #3
0
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
}