28 #if !defined(FIBER_USE_NATIVE)    29 # if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)    31 #   elif defined(__NetBSD__)    37 #     define FIBER_USE_NATIVE 0    41 #     define FIBER_USE_NATIVE 0    42 #   elif defined(__ia64)    45 #     define FIBER_USE_NATIVE 0    46 #   elif defined(__GNU__)    52 #     define FIBER_USE_NATIVE 0    54 #     define FIBER_USE_NATIVE 1    56 # elif defined(_WIN32)    57 #  define FIBER_USE_NATIVE 1    60 #if !defined(FIBER_USE_NATIVE)    61 #define FIBER_USE_NATIVE 0    70 #define RB_PAGE_SIZE (pagesize)    71 #define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1))    75 #define CAPTURE_JUST_VALID_VM_STACK 1    85 #ifdef CAPTURE_JUST_VALID_VM_STACK   104         VALUE *register_stack;
   105         VALUE *register_stack_src;
   106         int register_stack_size;
   136 #define FIBER_CREATED_P(fib)    ((fib)->status == FIBER_CREATED)   137 #define FIBER_RESUMED_P(fib)    ((fib)->status == FIBER_RESUMED)   138 #define FIBER_SUSPENDED_P(fib)  ((fib)->status == FIBER_SUSPENDED)   139 #define FIBER_TERMINATED_P(fib) ((fib)->status == FIBER_TERMINATED)   140 #define FIBER_RUNNABLE_P(fib)   (FIBER_CREATED_P(fib) || FIBER_SUSPENDED_P(fib))   142 #if FIBER_USE_NATIVE && !defined(_WIN32)   143 #define MAX_MACHINE_STACK_CACHE  10   144 static int machine_stack_cache_index = 0;
   145 typedef struct machine_stack_cache_struct {
   148 } machine_stack_cache_t;
   149 static machine_stack_cache_t machine_stack_cache[MAX_MACHINE_STACK_CACHE];
   150 static machine_stack_cache_t terminated_machine_stack;
   195     if (0) fprintf(stderr, 
"fib: %p, status: %s -> %s\n", fib, fiber_status_name(fib->
status), fiber_status_name(s));
   202 static VALUE rb_cContinuation;
   203 static VALUE rb_cFiber;
   204 static VALUE rb_eFiberError;
   206 #define GetContPtr(obj, ptr)  \   207     TypedData_Get_Struct((obj), rb_context_t, &cont_data_type, (ptr))   209 #define GetFiberPtr(obj, ptr)  do {\   210     TypedData_Get_Struct((obj), rb_fiber_t, &fiber_data_type, (ptr)); \   211     if (!(ptr)) rb_raise(rb_eFiberError, "uninitialized fiber"); \   216 #define THREAD_MUST_BE_RUNNING(th) do { \   217         if (!(th)->ec.tag) rb_raise(rb_eThreadError, "not running thread");     \   238 #ifdef CAPTURE_JUST_VALID_VM_STACK   255             const rb_thread_t *th = rb_thread_ptr(cont_thread_value(cont));
   265     if (cont->
machine.register_stack) {
   267                              cont->
machine.register_stack + cont->
machine.register_stack_size);
   294             if (fib->fib_handle) {
   295                 DeleteFiber(fib->fib_handle);
   299         if (th && th->
ec.
fiber != fib) {
   302                     rb_bug(
"Illegal root fiber parameter");
   304                 munmap((
void*)fib->ss_sp, fib->ss_size);
   329 cont_memsize(
const void *ptr)
   334     size = 
sizeof(*cont);
   336 #ifdef CAPTURE_JUST_VALID_VM_STACK   348     if (cont->
machine.register_stack) {
   349         size += cont->
machine.register_stack_size * 
sizeof(*cont->
machine.register_stack);
   358 #if VM_CHECK_MODE > 0   384 fiber_mark(
void *ptr)
   391     cont_mark(&fib->
cont);
   396 fiber_free(
void *ptr)
   405     cont_free(&fib->
cont);
   410 fiber_memsize(
const void *ptr)
   420     size += cont_memsize(&fib->
cont);
   442     th->machine.register_stack_end = rb_ia64_bsp();
   466     size = cont->
machine.register_stack_size = th->machine.register_stack_end - th->machine.register_stack_start;
   467     cont->
machine.register_stack_src = th->machine.register_stack_start;
   468     if (cont->
machine.register_stack) {
   481     {cont_mark, cont_free, cont_memsize,},
   509     cont_save_thread(cont, th);
   517 cont_new(
VALUE klass)
   520     volatile VALUE contval;
   525     cont->
self = contval;
   531 cont_capture(
volatile int *
volatile stat)
   535     volatile VALUE contval;
   540     cont = cont_new(rb_cContinuation);
   541     contval = cont->
self;
   543 #ifdef CAPTURE_JUST_VALID_VM_STACK   556     cont_save_machine_stack(th, cont);
   617 #ifdef CAPTURE_JUST_VALID_VM_STACK   648 fiber_set_stack_location(
void)
   658 fiber_entry(
void *arg)
   660     fiber_set_stack_location();
   670 #if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)   671 #define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_STACK)   673 #define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON)   677 fiber_machine_stack_alloc(
size_t size)
   681     if (machine_stack_cache_index > 0) {
   682         if (machine_stack_cache[machine_stack_cache_index - 1].size == (size / 
sizeof(
VALUE))) {
   683             ptr = machine_stack_cache[machine_stack_cache_index - 1].ptr;
   684             machine_stack_cache_index--;
   685             machine_stack_cache[machine_stack_cache_index].ptr = 
NULL;
   686             machine_stack_cache[machine_stack_cache_index].size = 0;
   690             rb_bug(
"machine_stack_cache size is not canonicalized");
   698         ptr = mmap(
NULL, size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
   699         if (ptr == MAP_FAILED) {
   705         if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) {
   706             rb_raise(rb_eFiberError, 
"mprotect failed");
   715 fiber_initialize_machine_stack_context(
rb_fiber_t *fib, 
size_t size)
   720 # if defined(_MSC_VER) && _MSC_VER <= 1200   721 #   define CreateFiberEx(cs, stacksize, flags, entry, param) \   722     CreateFiber((stacksize), (entry), (param))   724     fib->fib_handle = CreateFiberEx(size - 1, size, 0, fiber_entry, 
NULL);
   725     if (!fib->fib_handle) {
   728         fib->fib_handle = CreateFiberEx(size - 1, size, 0, fiber_entry, 
NULL);
   729         if (!fib->fib_handle) {
   730             rb_raise(rb_eFiberError, 
"can't create fiber");
   735     ucontext_t *context = &fib->context;
   740     ptr = fiber_machine_stack_alloc(size);
   741     context->uc_link = 
NULL;
   742     context->uc_stack.ss_sp = 
ptr;
   743     context->uc_stack.ss_size = 
size;
   751     sth->machine.register_stack_maxsize = sth->machine.stack_maxsize;
   783     fiber_restore_thread(th, newfib);
   786     if (!newfib->context.uc_stack.ss_sp && th->
root_fiber != newfib) {
   787         rb_bug(
"non_root_fiber->context.uc_stac.ss_sp should not be NULL");
   792     SwitchToFiber(newfib->fib_handle);
   794     swapcontext(&oldfib->context, &newfib->context);
   804     cont_restore_thread(cont);
   812         ((_JUMP_BUFFER*)(&cont->
jmpbuf))->Frame =
   813             ((_JUMP_BUFFER*)(&
buf))->Frame;
   823     if (cont->
machine.register_stack_src) {
   835 #define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4   836 #define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4   837 static volatile int C(a), 
C(b), 
C(c), 
C(d), 
C(e);
   838 static volatile int C(
f), 
C(g), 
C(h), 
C(i), 
C(j);
   839 static volatile int C(k), 
C(l), 
C(m), 
C(n), 
C(o);
   840 static volatile int C(p), 
C(q), 
C(r), 
C(s), 
C(t);
   844 int rb_dummy_false = 0;
   849     if (rb_dummy_false) {
   851         E(a) = E(b) = E(c) = E(d) = E(e) =
   852         E(
f) = E(g) = E(h) = E(i) = E(j) =
   853         E(k) = E(l) = E(m) = E(n) = E(o) =
   854         E(p) = E(q) = E(r) = E(s) = E(t) = 0;
   855         E(a) = E(b) = E(c) = E(d) = E(e) =
   856         E(
f) = E(g) = E(h) = E(i) = E(j) =
   857         E(k) = E(l) = E(m) = E(n) = E(o) =
   858         E(p) = E(q) = E(r) = E(s) = E(t) = 0;
   860     if (curr_bsp < cont->machine.register_stack_src+cont->
machine.register_stack_size) {
   861         register_stack_extend(cont, vp, (
VALUE*)rb_ia64_bsp());
   863     cont_restore_0(cont, vp);
   874 #define STACK_PAD_SIZE 1   876 #define STACK_PAD_SIZE 1024   880 #if !STACK_GROW_DIRECTION   881         if (addr_in_prev_frame > &space[0]) {
   884 #if STACK_GROW_DIRECTION <= 0   886             if (&space[0] > end) {
   891                 cont_restore_0(cont, &space[0]);
   895 #if !STACK_GROW_DIRECTION   900 #if STACK_GROW_DIRECTION >= 0   907                 cont_restore_0(cont, &space[STACK_PAD_SIZE-1]);
   911 #if !STACK_GROW_DIRECTION   915     cont_restore_1(cont);
   918 #define cont_restore_0(cont, vp) register_stack_extend((cont), (vp), (VALUE*)rb_ia64_bsp())  1005 rb_callcc(
VALUE self)
  1007     volatile int called;
  1008     volatile VALUE val = cont_capture(&called);
  1066     for (p=current; p; p=p->
next)
  1069     for (entry=target; entry->
marker; entry++)
  1074     base_point = cur_size;
  1075     while (base_point) {
  1076         if (target_size >= base_point &&
  1084     for (i=0; i < target_size - base_point; i++) {
  1085         if (!lookup_rollback_func(target[i].e_proc)) {
  1090     while (cur_size > base_point) {
  1093         current = current->
next;
  1098         func = (
VALUE (*)(
ANYARGS)) lookup_rollback_func(target[i].e_proc);
  1100             (*func)(target[i].
data2);
  1122 rb_cont_call(
int argc, 
VALUE *argv, 
VALUE contval)
  1128     if (cont_thread_value(cont) != th->
self) {
  1142     cont->
value = make_passing_arg(argc, argv);
  1144     cont_restore_0(cont, &contval);
  1217     {fiber_mark, fiber_free, fiber_memsize,},
  1218     0, 0, RUBY_TYPED_FREE_IMMEDIATELY
  1222 fiber_alloc(
VALUE klass)
  1228 fiber_t_alloc(
VALUE fibval)
  1241     cont_init(&fib->
cont, th);
  1302 #if !FIBER_USE_NATIVE  1311 rb_fiber_init(
VALUE fibval)
  1319     return fiber_init(fiber_alloc(rb_cFiber), 
rb_proc_new(func, obj));
  1322 static void rb_fiber_terminate(
rb_fiber_t *fib);
  1365     rb_fiber_terminate(fib);
  1374     fib = fiber_t_alloc(fiber_alloc(rb_cFiber));
  1376 #if FIBER_USE_NATIVE  1378     fib->fib_handle = ConvertThreadToFiber(0);
  1407         if (root_fiber == fib) {
  1408             rb_raise(rb_eFiberError, 
"can't yield from root fiber");
  1431         cont_save_thread(&fib->
cont, th);
  1435         fib = root_fiber_alloc(th);
  1441 #if FIBER_USE_NATIVE  1449 #if FIBER_USE_NATIVE == 0  1451     cont_save_machine_stack(th, &fib->
cont);
  1456 #if FIBER_USE_NATIVE  1457     fiber_setcontext(next_fib, fib);
  1460     if (terminated_machine_stack.ptr) {
  1461         if (machine_stack_cache_index < MAX_MACHINE_STACK_CACHE) {
  1462             machine_stack_cache[machine_stack_cache_index].ptr = terminated_machine_stack.ptr;
  1463             machine_stack_cache[machine_stack_cache_index].size = terminated_machine_stack.size;
  1464             machine_stack_cache_index++;
  1468                 munmap((
void*)terminated_machine_stack.ptr, terminated_machine_stack.size * 
sizeof(
VALUE));
  1471                 rb_bug(
"terminated fiber resumed");
  1474         terminated_machine_stack.ptr = 
NULL;
  1475         terminated_machine_stack.size = 0;
  1495         cont_restore_0(&next_fib->
cont, &undef);
  1502 fiber_switch(
rb_fiber_t *fib, 
int argc, 
const VALUE *argv, 
int is_resume)
  1512         return make_passing_arg(argc, argv);
  1515     if (cont_thread_value(cont) != th->
self) {
  1516         rb_raise(rb_eFiberError, 
"fiber called across threads");
  1519         rb_raise(rb_eFiberError, 
"fiber called across stack rewinding barrier");
  1522         value = 
rb_exc_new2(rb_eFiberError, 
"dead fiber called");
  1536             cont->
value = value;
  1537 #if FIBER_USE_NATIVE  1540             cont_restore_0(cont, &value);
  1547         fib->
prev = fiber_current();
  1553     cont->
value = make_passing_arg(argc, argv);
  1554     value = fiber_store(fib, th);
  1567     return fiber_switch(fib, argc, argv, 0);
  1577 #if FIBER_USE_NATIVE && !defined(_WIN32)  1579     terminated_machine_stack.ptr = fib->ss_sp;
  1580     terminated_machine_stack.size = fib->ss_size / 
sizeof(
VALUE);
  1582     fib->context.uc_stack.ss_sp = 
NULL;
  1586     fiber_switch(return_fiber(), 1, &value, 0);
  1596         rb_raise(rb_eFiberError, 
"double resume");
  1599         rb_raise(rb_eFiberError, 
"cannot resume transferred Fiber");
  1602     return fiber_switch(fib, argc, argv, 1);
  1608     return fiber_switch(return_fiber(), argc, argv, 0);
  1654 rb_fiber_m_resume(
int argc, 
VALUE *argv, 
VALUE fib)
  1705 rb_fiber_m_transfer(
int argc, 
VALUE *argv, 
VALUE fibval)
  1710     return fiber_switch(fib, argc, argv, 0);
  1724 rb_fiber_s_yield(
int argc, 
VALUE *argv, 
VALUE klass)
  1738 rb_fiber_s_current(
VALUE klass)
  1752 fiber_to_s(
VALUE fibval)
  1756     char status_info[0x10];
  1759     snprintf(status_info, 0x10, 
" (%s)", fiber_status_name(fib->
status));
  1762         strlcat(status_info, 
">", 
sizeof(status_info));
  1787 #if FIBER_USE_NATIVE  1792     GetSystemInfo(&info);
  1793     pagesize = info.dwPageSize;
  1795     pagesize = sysconf(_SC_PAGESIZE);
 
#define RUBY_VM_CHECK_INTS(th)
 
struct rb_ensure_entry entry
 
void rb_bug(const char *fmt,...)
 
#define THREAD_MUST_BE_RUNNING(th)
 
#define GetContPtr(obj, ptr)
 
#define ruby_longjmp(env, val)
 
VALUE rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_info)
 
#define RUBY_TYPED_FREE_IMMEDIATELY
 
#define FIBER_RUNNABLE_P(fib)
 
#define RUBY_VM_SET_INTERRUPT(th)
 
struct rb_trace_arg_struct * trace_arg
 
void rb_undef_alloc_func(VALUE)
 
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj. 
 
#define GetProcPtr(obj, ptr)
 
VALUE local_storage_recursive_hash_for_trace
 
#define FLUSH_REGISTER_WINDOWS
 
void rb_raise(VALUE exc, const char *fmt,...)
 
VALUE rb_fiber_resume(VALUE fibval, int argc, const VALUE *argv)
 
#define TypedData_Wrap_Struct(klass, data_type, sval)
 
void rb_fiber_reset_root_local_storage(VALUE thval)
 
#define GetFiberPtr(obj, ptr)
 
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, VALUE passed_block_handler)
 
#define VM_BLOCK_HANDLER_NONE
 
size_t fiber_machine_stack_size
 
VALUE rb_ary_tmp_new(long capa)
 
rb_ensure_list_t * ensure_list
 
#define STACK_UPPER(x, a, b)
 
void rb_str_set_len(VALUE, long)
 
VALUE rb_fiber_alive_p(VALUE fibval)
 
void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v)
 
#define RUBY_MARK_LEAVE(msg)
 
VALUE rb_fiber_current(void)
 
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
 
void rb_gc_mark(VALUE ptr)
 
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function. 
 
struct cont_saved_vm_stack saved_vm_stack
 
void rb_undef_method(VALUE klass, const char *name)
 
void rb_gc_mark_locations(const VALUE *start, const VALUE *end)
 
struct rb_context_struct rb_context_t
 
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
 
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
 
RUBY_EXTERN VALUE rb_cObject
 
rb_ensure_entry_t * ensure_array
 
size_t st_memsize(const st_table *tab)
 
#define FIBER_SUSPENDED_P(fib)
 
size_t fiber_vm_stack_size
 
VALUE rb_any_to_s(VALUE)
call-seq: obj.to_s -> string 
 
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class. 
 
#define RUBY_MARK_ENTER(msg)
 
VALUE rb_fiber_new(VALUE(*func)(ANYARGS), VALUE obj)
 
#define FIBER_RESUMED_P(fib)
 
void ruby_Init_Fiber_as_Coroutine(void)
 
void rb_fiber_start(void)
 
#define ALLOCA_N(type, n)
 
#define MEMCPY(p1, p2, type, n)
 
VALUE local_storage_recursive_hash
 
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method. 
 
#define RARRAY_CONST_PTR(a)
 
#define REALLOC_N(var, type, n)
 
#define STACK_DIR_UPPER(a, b)
 
VALUE rb_obj_is_proc(VALUE)
 
void rb_vm_stack_to_heap(rb_thread_t *th)
 
RUBY_SYMBOL_EXPORT_BEGIN void ruby_Init_Continuation_body(void)
 
VALUE rb_fiber_yield(int argc, const VALUE *argv)
 
#define RUBY_SYMBOL_EXPORT_END
 
unsigned char buf[MIME_BUF_SIZE]
 
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread. 
 
#define FIBER_TERMINATED_P(fib)
 
struct rb_vm_protect_tag * protect_tag
 
#define STACK_GROW_DIR_DETECTION
 
const VALUE * rb_vm_proc_local_ep(VALUE proc)
 
#define EXEC_EVENT_HOOK(th_, flag_, self_, id_, called_id_, klass_, data_)
 
#define FIBER_CREATED_P(fib)
 
#define RUBY_SYMBOL_EXPORT_BEGIN
 
rb_control_frame_t * rb_vm_push_frame(rb_execution_context_t *sec, const rb_iseq_t *iseq, VALUE type, VALUE self, VALUE specval, VALUE cref_or_me, const VALUE *pc, VALUE *sp, int local_size, int stack_max)
 
#define SET_MACHINE_STACK_END(p)
 
struct rb_ensure_list * next
 
struct rb_execution_context_struct::@143 machine
 
rb_execution_context_t saved_ec
 
enum rb_thread_status status
 
#define RUBY_FREE_UNLESS_NULL(ptr)
 
NOINLINE(static VALUE cont_capture(volatile int *volatile stat))
 
#define VAR_FROM_MEMORY(var)
 
VALUE rb_block_proc(void)
 
#define RUBY_FREE_LEAVE(msg)
 
#define RUBY_FREE_ENTER(msg)
 
#define VAR_INITIALIZED(var)
 
const struct rb_block block
 
RUBY_EXTERN char * strerror(int)
 
VALUE rb_obj_is_fiber(VALUE obj)
 
void rb_execution_context_mark(const rb_execution_context_t *ec)
 
VALUE rb_proc_new(VALUE(*)(ANYARGS), VALUE)
 
VALUE rb_str_cat_cstr(VALUE, const char *)
 
#define VM_UNREACHABLE(func)
 
struct rb_context_struct::@3 machine
 
#define TypedData_Make_Struct(klass, type, data_type, sval)
 
rb_execution_context_t ec
 
RUBY_EXTERN size_t strlcat(char *, const char *, size_t)
 
#define RUBY_EVENT_FIBER_SWITCH
 
void rb_fiber_mark_self(const rb_fiber_t *fib)
 
void ruby_register_rollback_func_for_ensure(VALUE(*ensure_func)(ANYARGS), VALUE(*rollback_func)(ANYARGS))
 
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val)
 
NORETURN(NOINLINE(static void cont_restore_0(rb_context_t *, VALUE *)))
 
struct rb_fiber_struct * prev
 
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
 
struct rb_vm_struct::@140 default_params
 
rb_ensure_list_t * ensure_list
 
VALUE rb_fiber_transfer(VALUE fibval, int argc, const VALUE *argv)