mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Make FIBER_USE_NATIVE the default and reformat code.
This commit is contained in:
parent
97808e29cd
commit
1b82c877df
1 changed files with 250 additions and 516 deletions
292
cont.c
292
cont.c
|
@ -15,81 +15,18 @@
|
||||||
#include "eval_intern.h"
|
#include "eval_intern.h"
|
||||||
#include "mjit.h"
|
#include "mjit.h"
|
||||||
|
|
||||||
/* FIBER_USE_NATIVE enables Fiber performance improvement using system
|
|
||||||
* dependent method such as make/setcontext on POSIX system or
|
|
||||||
* CreateFiber() API on Windows.
|
|
||||||
* This hack make Fiber context switch faster (x2 or more).
|
|
||||||
* However, it decrease maximum number of Fiber. For example, on the
|
|
||||||
* 32bit POSIX OS, ten or twenty thousands Fiber can be created.
|
|
||||||
*
|
|
||||||
* Details is reported in the paper "A Fast Fiber Implementation for Ruby 1.9"
|
|
||||||
* in Proc. of 51th Programming Symposium, pp.21--28 (2010) (in Japanese).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Enable FIBER_USE_COROUTINE to make fiber yield/resume much faster by using native assembly implementations.
|
|
||||||
|
|
||||||
rvm install ruby-head-ioquatix-native-fiber --url https://github.com/ioquatix/ruby --branch native-fiber
|
|
||||||
|
|
||||||
# Without libcoro
|
|
||||||
koyoko% ./build/bin/ruby ./fiber_benchmark.rb 10000 1000
|
|
||||||
setup time for 10000 fibers: 0.099961
|
|
||||||
execution time for 1000 messages: 19.505909
|
|
||||||
|
|
||||||
# With libcoro
|
|
||||||
koyoko% ./build/bin/ruby ./fiber_benchmark.rb 10000 1000
|
|
||||||
setup time for 10000 fibers: 0.099268
|
|
||||||
execution time for 1000 messages: 8.491746
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef FIBER_USE_COROUTINE
|
#ifdef FIBER_USE_COROUTINE
|
||||||
#include FIBER_USE_COROUTINE
|
#include FIBER_USE_COROUTINE
|
||||||
#define FIBER_USE_NATIVE 1
|
|
||||||
#else
|
|
||||||
#pragma message "Native coroutine not available!"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(FIBER_USE_NATIVE)
|
|
||||||
# if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
|
|
||||||
# if 0
|
|
||||||
# elif defined(__NetBSD__)
|
|
||||||
/* On our experience, NetBSD doesn't support using setcontext() and pthread
|
|
||||||
* simultaneously. This is because pthread_self(), TLS and other information
|
|
||||||
* are represented by stack pointer (higher bits of stack pointer).
|
|
||||||
* TODO: check such constraint on configure.
|
|
||||||
*/
|
|
||||||
# define FIBER_USE_NATIVE 0
|
|
||||||
# elif defined(__sun)
|
|
||||||
/* On Solaris because resuming any Fiber caused SEGV, for some reason.
|
|
||||||
*/
|
|
||||||
# define FIBER_USE_NATIVE 0
|
|
||||||
# elif defined(__GNU__)
|
|
||||||
/* GNU/Hurd doesn't fully support getcontext, setcontext, makecontext
|
|
||||||
* and swapcontext functions. Disabling their usage till support is
|
|
||||||
* implemented. More info at
|
|
||||||
* http://darnassus.sceen.net/~hurd-web/open_issues/glibc/#getcontext
|
|
||||||
*/
|
|
||||||
# define FIBER_USE_NATIVE 0
|
|
||||||
# else
|
|
||||||
# define FIBER_USE_NATIVE 1
|
|
||||||
# endif
|
|
||||||
# elif defined(_WIN32)
|
|
||||||
# define FIBER_USE_NATIVE 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#if !defined(FIBER_USE_NATIVE)
|
|
||||||
#define FIBER_USE_NATIVE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RB_PAGE_SIZE (pagesize)
|
#define RB_PAGE_SIZE (pagesize)
|
||||||
#define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1))
|
#define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1))
|
||||||
static long pagesize;
|
static long pagesize;
|
||||||
#endif /*FIBER_USE_NATIVE*/
|
|
||||||
|
|
||||||
#define CAPTURE_JUST_VALID_VM_STACK 1
|
#define CAPTURE_JUST_VALID_VM_STACK 1
|
||||||
|
|
||||||
|
@ -153,25 +90,6 @@ enum fiber_status {
|
||||||
#define FIBER_TERMINATED_P(fiber) ((fiber)->status == FIBER_TERMINATED)
|
#define FIBER_TERMINATED_P(fiber) ((fiber)->status == FIBER_TERMINATED)
|
||||||
#define FIBER_RUNNABLE_P(fiber) (FIBER_CREATED_P(fiber) || FIBER_SUSPENDED_P(fiber))
|
#define FIBER_RUNNABLE_P(fiber) (FIBER_CREATED_P(fiber) || FIBER_SUSPENDED_P(fiber))
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE && !defined(FIBER_USE_COROUTINE) && !defined(_WIN32)
|
|
||||||
static inline int
|
|
||||||
fiber_context_create(ucontext_t *context, void (*func)(), void *arg, void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
if (getcontext(context) < 0) return -1;
|
|
||||||
/*
|
|
||||||
* getcontext() may fail by some reasons:
|
|
||||||
* 1. SELinux policy banned one of "rt_sigprocmask",
|
|
||||||
* "sigprocmask" or "swapcontext";
|
|
||||||
* 2. libseccomp (aka. syscall filter) banned one of them.
|
|
||||||
*/
|
|
||||||
context->uc_link = NULL;
|
|
||||||
context->uc_stack.ss_sp = ptr;
|
|
||||||
context->uc_stack.ss_size = size;
|
|
||||||
makecontext(context, func, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct rb_fiber_struct {
|
struct rb_fiber_struct {
|
||||||
rb_context_t cont;
|
rb_context_t cont;
|
||||||
VALUE first_proc;
|
VALUE first_proc;
|
||||||
|
@ -183,28 +101,11 @@ struct rb_fiber_struct {
|
||||||
*/
|
*/
|
||||||
unsigned int transferred : 1;
|
unsigned int transferred : 1;
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
#define FIBER_ALLOCATE_STACK
|
|
||||||
struct coroutine_context context;
|
struct coroutine_context context;
|
||||||
void *ss_sp;
|
void *ss_sp;
|
||||||
size_t ss_size;
|
size_t ss_size;
|
||||||
#elif defined(_WIN32)
|
|
||||||
void *fiber_handle;
|
|
||||||
#else
|
|
||||||
#define FIBER_ALLOCATE_STACK
|
|
||||||
ucontext_t context;
|
|
||||||
/* Because context.uc_stack.ss_sp and context.uc_stack.ss_size
|
|
||||||
* are not necessarily valid after makecontext() or swapcontext(),
|
|
||||||
* they are saved in these variables for later use.
|
|
||||||
*/
|
|
||||||
void *ss_sp;
|
|
||||||
size_t ss_size;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef FIBER_ALLOCATE_STACK
|
|
||||||
#define MAX_MACHINE_STACK_CACHE 10
|
#define MAX_MACHINE_STACK_CACHE 10
|
||||||
static int machine_stack_cache_index = 0;
|
static int machine_stack_cache_index = 0;
|
||||||
typedef struct machine_stack_cache_struct {
|
typedef struct machine_stack_cache_struct {
|
||||||
|
@ -213,7 +114,6 @@ typedef struct machine_stack_cache_struct {
|
||||||
} machine_stack_cache_t;
|
} machine_stack_cache_t;
|
||||||
static machine_stack_cache_t machine_stack_cache[MAX_MACHINE_STACK_CACHE];
|
static machine_stack_cache_t machine_stack_cache[MAX_MACHINE_STACK_CACHE];
|
||||||
static machine_stack_cache_t terminated_machine_stack;
|
static machine_stack_cache_t terminated_machine_stack;
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
fiber_status_name(enum fiber_status s)
|
fiber_status_name(enum fiber_status s)
|
||||||
|
@ -392,16 +292,11 @@ cont_free(void *ptr)
|
||||||
ruby_xfree(cont->saved_ec.vm_stack);
|
ruby_xfree(cont->saved_ec.vm_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
if (cont->type == CONTINUATION_CONTEXT) {
|
if (cont->type == CONTINUATION_CONTEXT) {
|
||||||
/* cont */
|
|
||||||
ruby_xfree(cont->ensure_array);
|
ruby_xfree(cont->ensure_array);
|
||||||
RUBY_FREE_UNLESS_NULL(cont->machine.stack);
|
RUBY_FREE_UNLESS_NULL(cont->machine.stack);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
/* fiber */
|
|
||||||
rb_fiber_t *fiber = (rb_fiber_t*)cont;
|
rb_fiber_t *fiber = (rb_fiber_t*)cont;
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
coroutine_destroy(&fiber->context);
|
coroutine_destroy(&fiber->context);
|
||||||
if (fiber->ss_sp != NULL) {
|
if (fiber->ss_sp != NULL) {
|
||||||
if (fiber_is_root_p(fiber)) {
|
if (fiber_is_root_p(fiber)) {
|
||||||
|
@ -414,24 +309,8 @@ cont_free(void *ptr)
|
||||||
#endif
|
#endif
|
||||||
fiber->ss_sp = NULL;
|
fiber->ss_sp = NULL;
|
||||||
}
|
}
|
||||||
#elif defined(_WIN32)
|
|
||||||
if (!fiber_is_root_p(fiber)) {
|
|
||||||
/* don't delete root fiber handle */
|
|
||||||
if (fiber->fiber_handle) {
|
|
||||||
DeleteFiber(fiber->fiber_handle);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else /* not WIN32 */
|
|
||||||
/* fiber->ss_sp == NULL is possible for root fiber */
|
|
||||||
if (fiber->ss_sp != NULL) {
|
|
||||||
munmap((void*)fiber->ss_sp, fiber->ss_size);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#else /* not FIBER_USE_NATIVE */
|
|
||||||
ruby_xfree(cont->ensure_array);
|
|
||||||
RUBY_FREE_UNLESS_NULL(cont->machine.stack);
|
|
||||||
#endif
|
|
||||||
RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr);
|
RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr);
|
||||||
|
|
||||||
if (mjit_enabled && cont->mjit_cont != NULL) {
|
if (mjit_enabled && cont->mjit_cont != NULL) {
|
||||||
|
@ -507,16 +386,6 @@ fiber_mark(void *ptr)
|
||||||
fiber_verify(fiber);
|
fiber_verify(fiber);
|
||||||
rb_gc_mark_no_pin(fiber->first_proc);
|
rb_gc_mark_no_pin(fiber->first_proc);
|
||||||
if (fiber->prev) rb_fiber_mark_self(fiber->prev);
|
if (fiber->prev) rb_fiber_mark_self(fiber->prev);
|
||||||
|
|
||||||
#if !FIBER_USE_NATIVE
|
|
||||||
if (fiber->status == FIBER_TERMINATED) {
|
|
||||||
/* FIBER_TERMINATED fiber should not mark machine stack */
|
|
||||||
if (fiber->cont.saved_ec.machine.stack_end != NULL) {
|
|
||||||
fiber->cont.saved_ec.machine.stack_end = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cont_mark(&fiber->cont);
|
cont_mark(&fiber->cont);
|
||||||
RUBY_MARK_LEAVE("cont");
|
RUBY_MARK_LEAVE("cont");
|
||||||
}
|
}
|
||||||
|
@ -798,42 +667,12 @@ cont_restore_thread(rb_context_t *cont)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
static COROUTINE
|
static COROUTINE
|
||||||
fiber_entry(struct coroutine_context * from, struct coroutine_context * to)
|
fiber_entry(struct coroutine_context * from, struct coroutine_context * to)
|
||||||
{
|
{
|
||||||
rb_fiber_start();
|
rb_fiber_start();
|
||||||
}
|
}
|
||||||
#elif defined(_WIN32)
|
|
||||||
static void
|
|
||||||
fiber_set_stack_location(void)
|
|
||||||
{
|
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
VALUE *ptr;
|
|
||||||
|
|
||||||
SET_MACHINE_STACK_END(&ptr);
|
|
||||||
th->ec->machine.stack_start = (void*)(((VALUE)ptr & RB_PAGE_MASK) + STACK_UPPER((void *)&ptr, 0, RB_PAGE_SIZE));
|
|
||||||
}
|
|
||||||
|
|
||||||
NORETURN(static VOID CALLBACK fiber_entry(void *arg));
|
|
||||||
static VOID CALLBACK
|
|
||||||
fiber_entry(void *arg)
|
|
||||||
{
|
|
||||||
fiber_set_stack_location();
|
|
||||||
rb_fiber_start();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
NORETURN(static void fiber_entry(void *arg));
|
|
||||||
static void
|
|
||||||
fiber_entry(void *arg)
|
|
||||||
{
|
|
||||||
rb_fiber_start();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FIBER_ALLOCATE_STACK
|
|
||||||
/*
|
/*
|
||||||
* FreeBSD require a first (i.e. addr) argument of mmap(2) is not NULL
|
* FreeBSD require a first (i.e. addr) argument of mmap(2) is not NULL
|
||||||
* if MAP_STACK is passed.
|
* if MAP_STACK is passed.
|
||||||
|
@ -898,15 +737,12 @@ fiber_machine_stack_alloc(size_t size)
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
static void
|
static void
|
||||||
fiber_initialize_machine_stack_context(rb_fiber_t *fiber, size_t size)
|
fiber_initialize_machine_stack_context(rb_fiber_t *fiber, size_t size)
|
||||||
{
|
{
|
||||||
rb_execution_context_t *sec = &fiber->cont.saved_ec;
|
rb_execution_context_t *sec = &fiber->cont.saved_ec;
|
||||||
|
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
char *ptr;
|
char *ptr;
|
||||||
STACK_GROW_DIR_DETECTION;
|
STACK_GROW_DIR_DETECTION;
|
||||||
|
|
||||||
|
@ -916,34 +752,6 @@ fiber_initialize_machine_stack_context(rb_fiber_t *fiber, size_t size)
|
||||||
coroutine_initialize(&fiber->context, fiber_entry, ptr, size);
|
coroutine_initialize(&fiber->context, fiber_entry, ptr, size);
|
||||||
sec->machine.stack_start = (VALUE*)(ptr + STACK_DIR_UPPER(0, size));
|
sec->machine.stack_start = (VALUE*)(ptr + STACK_DIR_UPPER(0, size));
|
||||||
sec->machine.stack_maxsize = size - RB_PAGE_SIZE;
|
sec->machine.stack_maxsize = size - RB_PAGE_SIZE;
|
||||||
#elif defined(_WIN32)
|
|
||||||
# if defined(_MSC_VER) && _MSC_VER <= 1200
|
|
||||||
# define CreateFiberEx(cs, stacksize, flags, entry, param) \
|
|
||||||
CreateFiber((stacksize), (entry), (param))
|
|
||||||
# endif
|
|
||||||
fiber->fiber_handle = CreateFiberEx(size - 1, size, 0, fiber_entry, NULL);
|
|
||||||
if (!fiber->fiber_handle) {
|
|
||||||
/* try to release unnecessary fibers & retry to create */
|
|
||||||
rb_gc();
|
|
||||||
fiber->fiber_handle = CreateFiberEx(size - 1, size, 0, fiber_entry, NULL);
|
|
||||||
if (!fiber->fiber_handle) {
|
|
||||||
rb_raise(rb_eFiberError, "can't create fiber");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sec->machine.stack_maxsize = size;
|
|
||||||
#else /* not WIN32 */
|
|
||||||
char *ptr;
|
|
||||||
STACK_GROW_DIR_DETECTION;
|
|
||||||
|
|
||||||
ptr = fiber_machine_stack_alloc(size);
|
|
||||||
fiber->ss_sp = ptr;
|
|
||||||
fiber->ss_size = size;
|
|
||||||
if (fiber_context_create(&fiber->context, fiber_entry, NULL, fiber->ss_sp, fiber->ss_size)) {
|
|
||||||
rb_raise(rb_eFiberError, "can't get context for creating fiber: %s", ERRNOMSG);
|
|
||||||
}
|
|
||||||
sec->machine.stack_start = (VALUE*)(ptr + STACK_DIR_UPPER(0, size));
|
|
||||||
sec->machine.stack_maxsize = size - RB_PAGE_SIZE;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE(static void fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber));
|
NOINLINE(static void fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber));
|
||||||
|
@ -977,18 +785,8 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber)
|
||||||
fiber_restore_thread(th, new_fiber);
|
fiber_restore_thread(th, new_fiber);
|
||||||
|
|
||||||
/* swap machine context */
|
/* swap machine context */
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
coroutine_transfer(&old_fiber->context, &new_fiber->context);
|
coroutine_transfer(&old_fiber->context, &new_fiber->context);
|
||||||
#elif defined(_WIN32)
|
|
||||||
SwitchToFiber(new_fiber->fiber_handle);
|
|
||||||
#else
|
|
||||||
if (!new_fiber->context.uc_stack.ss_sp && th->root_fiber != new_fiber) {
|
|
||||||
rb_bug("non_root_fiber->context.uc_stac.ss_sp should not be NULL");
|
|
||||||
}
|
}
|
||||||
swapcontext(&old_fiber->context, &new_fiber->context);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif /* FIBER_USE_NATIVE */
|
|
||||||
|
|
||||||
NOINLINE(NORETURN(static void cont_restore_1(rb_context_t *)));
|
NOINLINE(NORETURN(static void cont_restore_1(rb_context_t *)));
|
||||||
|
|
||||||
|
@ -1420,20 +1218,21 @@ fiber_init(VALUE fiber_value, VALUE proc)
|
||||||
rb_execution_context_t *sec = &cont->saved_ec;
|
rb_execution_context_t *sec = &cont->saved_ec;
|
||||||
rb_thread_t *cth = GET_THREAD();
|
rb_thread_t *cth = GET_THREAD();
|
||||||
rb_vm_t *vm = cth->vm;
|
rb_vm_t *vm = cth->vm;
|
||||||
size_t fiber_stack_bytes = vm->default_params.fiber_vm_stack_size;
|
size_t fiber_vm_stack_size = vm->default_params.fiber_vm_stack_size;
|
||||||
size_t thr_stack_bytes = vm->default_params.thread_vm_stack_size;
|
size_t thread_vm_stack_size = vm->default_params.thread_vm_stack_size;
|
||||||
VALUE *vm_stack;
|
VALUE *vm_stack;
|
||||||
|
|
||||||
/* initialize cont */
|
/* initialize cont */
|
||||||
cont->saved_vm_stack.ptr = NULL;
|
cont->saved_vm_stack.ptr = NULL;
|
||||||
if (fiber_stack_bytes == thr_stack_bytes) {
|
if (fiber_vm_stack_size == thread_vm_stack_size) {
|
||||||
vm_stack = rb_thread_recycle_stack(fiber_stack_bytes / sizeof(VALUE));
|
vm_stack = rb_thread_recycle_stack(fiber_vm_stack_size / sizeof(VALUE));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vm_stack = ruby_xmalloc(fiber_stack_bytes);
|
vm_stack = ruby_xmalloc(fiber_vm_stack_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
cont->free_vm_stack = 1;
|
cont->free_vm_stack = 1;
|
||||||
rb_ec_initialize_vm_stack(sec, vm_stack, fiber_stack_bytes / sizeof(VALUE));
|
rb_ec_initialize_vm_stack(sec, vm_stack, fiber_vm_stack_size / sizeof(VALUE));
|
||||||
|
|
||||||
sec->tag = NULL;
|
sec->tag = NULL;
|
||||||
sec->local_storage = NULL;
|
sec->local_storage = NULL;
|
||||||
|
@ -1442,10 +1241,6 @@ fiber_init(VALUE fiber_value, VALUE proc)
|
||||||
|
|
||||||
fiber->first_proc = proc;
|
fiber->first_proc = proc;
|
||||||
|
|
||||||
#if !FIBER_USE_NATIVE
|
|
||||||
MEMCPY(&cont->jmpbuf, &cth->root_jmpbuf, rb_jmpbuf_t, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return fiber_value;
|
return fiber_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1527,21 +1322,7 @@ root_fiber_alloc(rb_thread_t *th)
|
||||||
DATA_PTR(fiber_value) = fiber;
|
DATA_PTR(fiber_value) = fiber;
|
||||||
fiber->cont.self = fiber_value;
|
fiber->cont.self = fiber_value;
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
coroutine_initialize_main(&fiber->context);
|
coroutine_initialize_main(&fiber->context);
|
||||||
#elif defined(_WIN32)
|
|
||||||
/* setup fiber_handle for root Fiber */
|
|
||||||
if (fiber->fiber_handle == 0) {
|
|
||||||
if ((fiber->fiber_handle = ConvertThreadToFiber(0)) == 0) {
|
|
||||||
rb_bug("root_fiber_alloc: ConvertThreadToFiber() failed - %s\n", rb_w32_strerror(-1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rb_bug("root_fiber_alloc: fiber_handle is not NULL.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return fiber;
|
return fiber;
|
||||||
}
|
}
|
||||||
|
@ -1571,8 +1352,6 @@ rb_threadptr_root_fiber_release(rb_thread_t *th)
|
||||||
else {
|
else {
|
||||||
VM_ASSERT(th->ec->fiber_ptr->cont.type == FIBER_CONTEXT);
|
VM_ASSERT(th->ec->fiber_ptr->cont.type == FIBER_CONTEXT);
|
||||||
VM_ASSERT(th->ec->fiber_ptr->cont.self == 0);
|
VM_ASSERT(th->ec->fiber_ptr->cont.self == 0);
|
||||||
|
|
||||||
// th->ec->fiber_ptr->cont.saved_ec.vm_stack = NULL;
|
|
||||||
fiber_free(th->ec->fiber_ptr);
|
fiber_free(th->ec->fiber_ptr);
|
||||||
|
|
||||||
if (th->ec == ruby_current_execution_context_ptr) {
|
if (th->ec == ruby_current_execution_context_ptr) {
|
||||||
|
@ -1648,25 +1427,16 @@ fiber_store(rb_fiber_t *next_fiber, rb_thread_t *th)
|
||||||
VM_ASSERT(FIBER_RESUMED_P(fiber) || FIBER_TERMINATED_P(fiber));
|
VM_ASSERT(FIBER_RESUMED_P(fiber) || FIBER_TERMINATED_P(fiber));
|
||||||
VM_ASSERT(FIBER_RUNNABLE_P(next_fiber));
|
VM_ASSERT(FIBER_RUNNABLE_P(next_fiber));
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
if (FIBER_CREATED_P(next_fiber)) {
|
if (FIBER_CREATED_P(next_fiber)) {
|
||||||
fiber_initialize_machine_stack_context(next_fiber, th->vm->default_params.fiber_machine_stack_size);
|
fiber_initialize_machine_stack_context(next_fiber, th->vm->default_params.fiber_machine_stack_size);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (FIBER_RESUMED_P(fiber)) fiber_status_set(fiber, FIBER_SUSPENDED);
|
if (FIBER_RESUMED_P(fiber)) fiber_status_set(fiber, FIBER_SUSPENDED);
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE == 0
|
|
||||||
/* should (re-)allocate stack are before fiber->status change to pass fiber_verify() */
|
|
||||||
cont_save_machine_stack(th, &fiber->cont);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fiber_status_set(next_fiber, FIBER_RESUMED);
|
fiber_status_set(next_fiber, FIBER_RESUMED);
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
fiber_setcontext(next_fiber, fiber);
|
fiber_setcontext(next_fiber, fiber);
|
||||||
/* restored */
|
|
||||||
#ifdef MAX_MACHINE_STACK_CACHE
|
|
||||||
if (terminated_machine_stack.ptr) {
|
if (terminated_machine_stack.ptr) {
|
||||||
if (machine_stack_cache_index < MAX_MACHINE_STACK_CACHE) {
|
if (machine_stack_cache_index < MAX_MACHINE_STACK_CACHE) {
|
||||||
machine_stack_cache[machine_stack_cache_index++] = terminated_machine_stack;
|
machine_stack_cache[machine_stack_cache_index++] = terminated_machine_stack;
|
||||||
|
@ -1686,30 +1456,11 @@ fiber_store(rb_fiber_t *next_fiber, rb_thread_t *th)
|
||||||
terminated_machine_stack.ptr = NULL;
|
terminated_machine_stack.ptr = NULL;
|
||||||
terminated_machine_stack.size = 0;
|
terminated_machine_stack.size = 0;
|
||||||
}
|
}
|
||||||
#endif /* MAX_MACHINE_STACK_CACHE */
|
|
||||||
fiber = th->ec->fiber_ptr;
|
|
||||||
if (fiber->cont.argc == -1) rb_exc_raise(fiber->cont.value);
|
|
||||||
return fiber->cont.value;
|
|
||||||
|
|
||||||
#else /* FIBER_USE_NATIVE */
|
|
||||||
fiber->cont.saved_ec.machine.stack_end = NULL;
|
|
||||||
if (ruby_setjmp(fiber->cont.jmpbuf)) {
|
|
||||||
/* restored */
|
|
||||||
fiber = th->ec->fiber_ptr;
|
fiber = th->ec->fiber_ptr;
|
||||||
if (fiber->cont.argc == -1) rb_exc_raise(fiber->cont.value);
|
if (fiber->cont.argc == -1) rb_exc_raise(fiber->cont.value);
|
||||||
if (next_fiber->cont.value == Qundef) {
|
|
||||||
cont_restore_0(&next_fiber->cont, &next_fiber->cont.value);
|
|
||||||
VM_UNREACHABLE(fiber_store);
|
|
||||||
}
|
|
||||||
return fiber->cont.value;
|
return fiber->cont.value;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
VALUE undef = Qundef;
|
|
||||||
cont_restore_0(&next_fiber->cont, &undef);
|
|
||||||
VM_UNREACHABLE(fiber_store);
|
|
||||||
}
|
|
||||||
#endif /* FIBER_USE_NATIVE */
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume)
|
fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume)
|
||||||
|
@ -1750,11 +1501,9 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume)
|
||||||
cont = &th->root_fiber->cont;
|
cont = &th->root_fiber->cont;
|
||||||
cont->argc = -1;
|
cont->argc = -1;
|
||||||
cont->value = value;
|
cont->value = value;
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
fiber_setcontext(th->root_fiber, th->ec->fiber_ptr);
|
fiber_setcontext(th->root_fiber, th->ec->fiber_ptr);
|
||||||
#else
|
|
||||||
cont_restore_0(cont, &value);
|
|
||||||
#endif
|
|
||||||
VM_UNREACHABLE(fiber_switch);
|
VM_UNREACHABLE(fiber_switch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1799,11 +1548,6 @@ rb_fiber_close(rb_fiber_t *fiber)
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_ec_clear_vm_stack(ec);
|
rb_ec_clear_vm_stack(ec);
|
||||||
|
|
||||||
#if !FIBER_USE_NATIVE
|
|
||||||
/* should not mark machine stack any more */
|
|
||||||
ec->machine.stack_end = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1815,22 +1559,14 @@ rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt)
|
||||||
VM_ASSERT(FIBER_RESUMED_P(fiber));
|
VM_ASSERT(FIBER_RESUMED_P(fiber));
|
||||||
rb_fiber_close(fiber);
|
rb_fiber_close(fiber);
|
||||||
|
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
#if defined(FIBER_USE_COROUTINE)
|
|
||||||
coroutine_destroy(&fiber->context);
|
coroutine_destroy(&fiber->context);
|
||||||
#elif !defined(_WIN32)
|
|
||||||
fiber->context.uc_stack.ss_sp = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MAX_MACHINE_STACK_CACHE
|
|
||||||
/* Ruby must not switch to other thread until storing terminated_machine_stack */
|
/* Ruby must not switch to other thread until storing terminated_machine_stack */
|
||||||
terminated_machine_stack.ptr = fiber->ss_sp;
|
terminated_machine_stack.ptr = fiber->ss_sp;
|
||||||
terminated_machine_stack.size = fiber->ss_size / sizeof(VALUE);
|
terminated_machine_stack.size = fiber->ss_size / sizeof(VALUE);
|
||||||
fiber->ss_sp = NULL;
|
fiber->ss_sp = NULL;
|
||||||
fiber->cont.machine.stack = NULL;
|
fiber->cont.machine.stack = NULL;
|
||||||
fiber->cont.machine.stack_size = 0;
|
fiber->cont.machine.stack_size = 0;
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret_fiber = return_fiber();
|
ret_fiber = return_fiber();
|
||||||
if (need_interrupt) RUBY_VM_SET_INTERRUPT(&ret_fiber->cont.saved_ec);
|
if (need_interrupt) RUBY_VM_SET_INTERRUPT(&ret_fiber->cont.saved_ec);
|
||||||
|
@ -2072,7 +1808,6 @@ rb_fiber_atfork(rb_thread_t *th)
|
||||||
void
|
void
|
||||||
Init_Cont(void)
|
Init_Cont(void)
|
||||||
{
|
{
|
||||||
#if FIBER_USE_NATIVE
|
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -2083,7 +1818,6 @@ Init_Cont(void)
|
||||||
pagesize = sysconf(_SC_PAGESIZE);
|
pagesize = sysconf(_SC_PAGESIZE);
|
||||||
#endif
|
#endif
|
||||||
SET_MACHINE_STACK_END(&th->ec->machine.stack_end);
|
SET_MACHINE_STACK_END(&th->ec->machine.stack_end);
|
||||||
#endif
|
|
||||||
|
|
||||||
rb_cFiber = rb_define_class("Fiber", rb_cObject);
|
rb_cFiber = rb_define_class("Fiber", rb_cObject);
|
||||||
rb_define_alloc_func(rb_cFiber, fiber_alloc);
|
rb_define_alloc_func(rb_cFiber, fiber_alloc);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue