18 #if ((defined(_WIN32) && _WIN32_WINNT >= 0x0400) || (defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT))) && !defined(__NetBSD__) && !defined(sun) && !defined(FIBER_USE_NATIVE)
19 #define FIBER_USE_NATIVE 1
37 #elif !defined(FIBER_USE_NATIVE)
38 #define FIBER_USE_NATIVE 0
47 #define RB_PAGE_SIZE (pagesize)
48 #define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1))
50 #define FIBER_MACHINE_STACK_ALLOCATION_SIZE (0x10000)
53 #define CAPTURE_JUST_VALID_VM_STACK 1
67 #ifdef CAPTURE_JUST_VALID_VM_STACK
74 VALUE *machine_register_stack;
75 VALUE *machine_register_stack_src;
76 int machine_register_stack_size;
89 #if FIBER_USE_NATIVE && !defined(_WIN32)
90 #define MAX_MAHINE_STACK_CACHE 10
91 static int machine_stack_cache_index = 0;
92 typedef struct machine_stack_cache_struct {
95 } machine_stack_cache_t;
96 static machine_stack_cache_t machine_stack_cache[MAX_MAHINE_STACK_CACHE];
97 static machine_stack_cache_t terminated_machine_stack;
120 #define GetContPtr(obj, ptr) \
121 TypedData_Get_Struct((obj), rb_context_t, &cont_data_type, (ptr))
123 #define GetFiberPtr(obj, ptr) do {\
124 TypedData_Get_Struct((obj), rb_fiber_t, &fiber_data_type, (ptr)); \
125 if (!(ptr)) rb_raise(rb_eFiberError, "uninitialized fiber"); \
130 #define THREAD_MUST_BE_RUNNING(th) do { \
131 if (!(th)->tag) rb_raise(rb_eThreadError, "not running thread"); \
145 #ifdef CAPTURE_JUST_VALID_VM_STACK
149 rb_gc_mark_localtion(cont->
vm_stack,
172 if (cont->machine_register_stack) {
174 cont->machine_register_stack + cont->machine_register_stack_size);
199 if (fib->fib_handle) {
200 DeleteFiber(fib->fib_handle);
206 if (fib->context.uc_stack.ss_sp) {
208 rb_bug(
"Illegal root fiber parameter");
210 munmap((
void*)fib->context.uc_stack.ss_sp, fib->context.uc_stack.ss_size);
240 size =
sizeof(*cont);
242 #ifdef CAPTURE_JUST_VALID_VM_STACK
247 size += n *
sizeof(*cont->
vm_stack);
254 if (cont->machine_register_stack) {
255 size += cont->machine_register_stack_size *
sizeof(*cont->machine_register_stack);
345 th->machine_register_stack_end = rb_ia64_bsp();
369 size = cont->machine_register_stack_size = th->machine_register_stack_end - th->machine_register_stack_start;
370 cont->machine_register_stack_src = th->machine_register_stack_start;
371 if (cont->machine_register_stack) {
378 MEMCPY(cont->machine_register_stack, cont->machine_register_stack_src,
VALUE, size);
414 volatile VALUE contval;
419 cont->
self = contval;
429 volatile VALUE contval;
434 contval = cont->
self;
437 #ifdef CAPTURE_JUST_VALID_VM_STACK
452 volatile VALUE value;
476 th->
fiber = sth->fiber;
485 #ifdef CAPTURE_JUST_VALID_VM_STACK
495 th->
stack = sth->stack;
504 th->
state = sth->state;
515 fiber_set_stack_location(
void)
525 fiber_entry(
void *
arg)
527 fiber_set_stack_location();
537 #if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
538 #define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_STACK)
540 #define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON)
544 fiber_machine_stack_alloc(
size_t size)
548 if (machine_stack_cache_index > 0) {
549 if (machine_stack_cache[machine_stack_cache_index - 1].size == (size /
sizeof(
VALUE))) {
550 ptr = machine_stack_cache[machine_stack_cache_index - 1].ptr;
551 machine_stack_cache_index--;
552 machine_stack_cache[machine_stack_cache_index].ptr =
NULL;
553 machine_stack_cache[machine_stack_cache_index].size = 0;
557 rb_bug(
"machine_stack_cache size is not canonicalized");
564 ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
565 if (ptr == MAP_FAILED) {
571 if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) {
581 fiber_initialize_machine_stack_context(
rb_fiber_t *fib,
size_t size)
586 fib->fib_handle = CreateFiberEx(size - 1, size, 0, fiber_entry, NULL);
587 if (!fib->fib_handle) {
590 fib->fib_handle = CreateFiberEx(size - 1, size, 0, fiber_entry, NULL);
591 if (!fib->fib_handle) {
597 ucontext_t *context = &fib->context;
602 ptr = fiber_machine_stack_alloc(size);
603 context->uc_link =
NULL;
604 context->uc_stack.ss_sp = ptr;
605 context->uc_stack.ss_size =
size;
623 fiber_initialize_machine_stack_context(newfib, FIBER_MACHINE_STACK_ALLOCATION_SIZE);
630 rb_bug(
"fiber_setcontext: sth->machine_stack_end has non zero value");
653 rb_bug(
"non_root_fiber->context.uc_stac.ss_sp should not be NULL");
659 SwitchToFiber(newfib->fib_handle);
660 #elif defined(__FreeBSD__)
663 if (setcontext(&newfib->context) < 0) {
664 rb_bug(
"context switch between fiber failed");
672 swapcontext(&oldfib->context, &newfib->context);
690 ((_JUMP_BUFFER*)(&cont->
jmpbuf))->Frame =
691 ((_JUMP_BUFFER*)(&
buf))->Frame;
701 if (cont->machine_register_stack_src) {
702 MEMCPY(cont->machine_register_stack_src, cont->machine_register_stack,
703 VALUE, cont->machine_register_stack_size);
713 #define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
714 #define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
715 static volatile int C(a),
C(b),
C(c),
C(d),
C(e);
716 static volatile int C(f),
C(g),
C(h),
C(
i),
C(j);
717 static volatile int C(k),
C(l),
C(m),
C(n),
C(o);
718 static volatile int C(
p),
C(q),
C(r),
C(s),
C(t);
722 int rb_dummy_false = 0;
727 if (rb_dummy_false) {
729 E(a) = E(b) = E(c) = E(d) = E(e) =
730 E(f) = E(g) = E(h) = E(
i) = E(j) =
731 E(k) = E(l) = E(m) = E(n) = E(o) =
732 E(
p) = E(q) = E(r) = E(s) = E(t) = 0;
733 E(a) = E(b) = E(c) = E(d) = E(e) =
734 E(f) = E(g) = E(h) = E(
i) = E(j) =
735 E(k) = E(l) = E(m) = E(n) = E(o) =
736 E(
p) = E(q) = E(r) = E(s) = E(t) = 0;
738 if (curr_bsp < cont->machine_register_stack_src+cont->machine_register_stack_size) {
739 register_stack_extend(cont, vp, (
VALUE*)rb_ia64_bsp());
752 #define STACK_PAD_SIZE 1
754 #define STACK_PAD_SIZE 1024
758 #if !STACK_GROW_DIRECTION
759 if (addr_in_prev_frame > &space[0]) {
762 #if STACK_GROW_DIRECTION <= 0
764 if (&space[0] > end) {
773 #if !STACK_GROW_DIRECTION
778 #if STACK_GROW_DIRECTION >= 0
789 #if !STACK_GROW_DIRECTION
796 #define cont_restore_0(cont, vp) register_stack_extend((cont), (vp), (VALUE*)rb_ia64_bsp());
1002 #define FIBER_VM_STACK_SIZE (4 * 1024)
1076 #if !FIBER_USE_NATIVE
1127 #if FIBER_USE_NATIVE && !defined(_WIN32)
1129 terminated_machine_stack.ptr = fib->context.uc_stack.ss_sp;
1130 terminated_machine_stack.size = fib->context.uc_stack.ss_size /
sizeof(
VALUE);
1131 fib->context.uc_stack.ss_sp =
NULL;
1179 rb_bug(
"rb_fiber_start: unreachable");
1189 #if FIBER_USE_NATIVE
1191 fib->fib_handle = ConvertThreadToFiber(0);
1204 if (th->
fiber == 0) {
1228 #if !FIBER_USE_NATIVE
1234 fiber_setcontext(next_fib, fib);
1236 if (terminated_machine_stack.ptr) {
1237 if (machine_stack_cache_index < MAX_MAHINE_STACK_CACHE) {
1238 machine_stack_cache[machine_stack_cache_index].ptr = terminated_machine_stack.ptr;
1239 machine_stack_cache[machine_stack_cache_index].size = terminated_machine_stack.size;
1240 machine_stack_cache_index++;
1244 munmap((
void*)terminated_machine_stack.ptr, terminated_machine_stack.size *
sizeof(
VALUE));
1247 rb_bug(
"terminated fiber resumed");
1250 terminated_machine_stack.ptr =
NULL;
1251 terminated_machine_stack.size = 0;
1260 #if !FIBER_USE_NATIVE
1286 if (th->
fiber != fibval) {
1298 cont->
value = value;
1299 #if FIBER_USE_NATIVE
1305 fiber_setcontext(fib, oldfib);
1320 #if !FIBER_USE_NATIVE
1323 rb_bug(
"rb_fiber_resume: unreachable");
1479 #if FIBER_USE_NATIVE
1484 GetSystemInfo(&info);
1485 pagesize = info.dwPageSize;
1487 pagesize = sysconf(_SC_PAGESIZE);
1500 #if defined __GNUC__ && __GNUC__ >= 4
1501 #pragma GCC visibility push(default)
1523 #if defined __GNUC__ && __GNUC__ >= 4
1524 #pragma GCC visibility pop