Exemplo n.º 1
0
static void
fiber_set_stack_location(void)
{
    rb_thread_t *th = GET_THREAD();
    VALUE *ptr;

    SET_MACHINE_STACK_END(&ptr);
    th->machine_stack_start = (void*)(((VALUE)ptr & RB_PAGE_MASK) + STACK_UPPER((void *)&ptr, 0, RB_PAGE_SIZE));
}
Exemplo n.º 2
0
static void
cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
{
    size_t size;
    rb_thread_t *sth = &cont->saved_thread;

    SET_MACHINE_STACK_END(&th->machine_stack_end);
#ifdef __ia64
    th->machine_register_stack_end = rb_ia64_bsp();
#endif

    if (th->machine_stack_start > th->machine_stack_end) {
	size = cont->machine_stack_size = th->machine_stack_start - th->machine_stack_end;
	cont->machine_stack_src = th->machine_stack_end;
    }
    else {
	size = cont->machine_stack_size = th->machine_stack_end - th->machine_stack_start;
	cont->machine_stack_src = th->machine_stack_start;
    }

    if (cont->machine_stack) {
	REALLOC_N(cont->machine_stack, VALUE, size);
    }
    else {
	cont->machine_stack = ALLOC_N(VALUE, size);
    }

    FLUSH_REGISTER_WINDOWS;
    MEMCPY(cont->machine_stack, cont->machine_stack_src, VALUE, size);

#ifdef __ia64
    rb_ia64_flushrs();
    size = cont->machine_register_stack_size = th->machine_register_stack_end - th->machine_register_stack_start;
    cont->machine_register_stack_src = th->machine_register_stack_start;
    if (cont->machine_register_stack) {
	REALLOC_N(cont->machine_register_stack, VALUE, size);
    }
    else {
	cont->machine_register_stack = ALLOC_N(VALUE, size);
    }

    MEMCPY(cont->machine_register_stack, cont->machine_register_stack_src, VALUE, size);
#endif

    sth->machine_stack_start = sth->machine_stack_end = 0;
#ifdef __ia64
    sth->machine_register_stack_start = sth->machine_register_stack_end = 0;
#endif
}
Exemplo n.º 3
0
static void
fiber_setcontext(rb_fiber_t *newfib, rb_fiber_t *oldfib)
{
    rb_thread_t *th = GET_THREAD(), *sth = &newfib->cont.saved_thread;

    if (newfib->status != RUNNING) {
	fiber_initialize_machine_stack_context(newfib, FIBER_MACHINE_STACK_ALLOCATION_SIZE);
    }

    /* restore thread context */
    cont_restore_thread(&newfib->cont);
    th->machine_stack_maxsize = sth->machine_stack_maxsize;
    if (sth->machine_stack_end && (newfib != oldfib)) {
	rb_bug("fiber_setcontext: sth->machine_stack_end has non zero value");
    }

    /* save  oldfib's machine stack */
    if (oldfib->status != TERMINATED) {
	STACK_GROW_DIR_DETECTION;
	SET_MACHINE_STACK_END(&th->machine_stack_end);
	if (STACK_DIR_UPPER(0, 1)) {
	    oldfib->cont.machine_stack_size = th->machine_stack_start - th->machine_stack_end;
	    oldfib->cont.machine_stack = th->machine_stack_end;
	}
	else {
	    oldfib->cont.machine_stack_size = th->machine_stack_end - th->machine_stack_start;
	    oldfib->cont.machine_stack = th->machine_stack_start;
	}
    }
    /* exchange machine_stack_start between oldfib and newfib */
    oldfib->cont.saved_thread.machine_stack_start = th->machine_stack_start;
    th->machine_stack_start = sth->machine_stack_start;
    /* oldfib->machine_stack_end should be NULL */
    oldfib->cont.saved_thread.machine_stack_end = 0;
#ifndef _WIN32
    if (!newfib->context.uc_stack.ss_sp && th->root_fiber != newfib->cont.self) {
	rb_bug("non_root_fiber->context.uc_stac.ss_sp should not be NULL");
    }
#endif

    /* swap machine context */
#ifdef _WIN32
    SwitchToFiber(newfib->fib_handle);
#else
    swapcontext(&oldfib->context, &newfib->context);
#endif
}