29 #if !defined(FIBER_USE_NATIVE)
30 # if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
32 # elif defined(__NetBSD__)
38 # define FIBER_USE_NATIVE 0
42 # define FIBER_USE_NATIVE 0
43 # elif defined(__ia64)
46 # define FIBER_USE_NATIVE 0
47 # elif defined(__GNU__)
53 # define FIBER_USE_NATIVE 0
55 # define FIBER_USE_NATIVE 1
57 # elif defined(_WIN32)
58 # if _WIN32_WINNT >= 0x0400
63 # define FIBER_USE_NATIVE 1
67 #if !defined(FIBER_USE_NATIVE)
68 #define FIBER_USE_NATIVE 0
77 #define RB_PAGE_SIZE (pagesize)
78 #define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1))
82 #define CAPTURE_JUST_VALID_VM_STACK 1
96 #ifdef CAPTURE_JUST_VALID_VM_STACK
105 VALUE *register_stack;
106 VALUE *register_stack_src;
107 int register_stack_size;
122 #if FIBER_USE_NATIVE && !defined(_WIN32)
123 #define MAX_MACHINE_STACK_CACHE 10
124 static int machine_stack_cache_index = 0;
125 typedef struct machine_stack_cache_struct {
128 } machine_stack_cache_t;
129 static machine_stack_cache_t machine_stack_cache[MAX_MACHINE_STACK_CACHE];
130 static machine_stack_cache_t terminated_machine_stack;
159 #define GetContPtr(obj, ptr) \
160 TypedData_Get_Struct((obj), rb_context_t, &cont_data_type, (ptr))
162 #define GetFiberPtr(obj, ptr) do {\
163 TypedData_Get_Struct((obj), rb_fiber_t, &fiber_data_type, (ptr)); \
164 if (!(ptr)) rb_raise(rb_eFiberError, "uninitialized fiber"); \
169 #define THREAD_MUST_BE_RUNNING(th) do { \
170 if (!(th)->tag) rb_raise(rb_eThreadError, "not running thread"); \
184 #ifdef CAPTURE_JUST_VALID_VM_STACK
188 rb_gc_mark_localtion(cont->
vm_stack,
211 if (cont->
machine.register_stack) {
213 cont->
machine.register_stack + cont->
machine.register_stack_size);
239 if (fib->fib_handle) {
240 DeleteFiber(fib->fib_handle);
246 if (fib->context.uc_stack.ss_sp) {
248 rb_bug(
"Illegal root fiber parameter");
250 munmap((
void*)fib->context.uc_stack.ss_sp, fib->context.uc_stack.ss_size);
281 size =
sizeof(*cont);
283 #ifdef CAPTURE_JUST_VALID_VM_STACK
288 size += n *
sizeof(*cont->
vm_stack);
295 if (cont->
machine.register_stack) {
296 size += cont->
machine.register_stack_size *
sizeof(*cont->
machine.register_stack);
387 th->
machine.register_stack_end = rb_ia64_bsp();
411 size = cont->
machine.register_stack_size = th->
machine.register_stack_end - th->
machine.register_stack_start;
412 cont->
machine.register_stack_src = th->
machine.register_stack_start;
413 if (cont->
machine.register_stack) {
457 volatile VALUE contval;
462 cont->
self = contval;
472 volatile VALUE contval;
477 contval = cont->
self;
480 #ifdef CAPTURE_JUST_VALID_VM_STACK
511 volatile VALUE value;
535 th->
fiber = sth->fiber;
544 #ifdef CAPTURE_JUST_VALID_VM_STACK
554 th->
stack = sth->stack;
563 th->
state = sth->state;
578 fiber_set_stack_location(
void)
588 fiber_entry(
void *
arg)
590 fiber_set_stack_location();
600 #if defined(MAP_STACK) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
601 #define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_STACK)
603 #define FIBER_STACK_FLAGS (MAP_PRIVATE | MAP_ANON)
607 fiber_machine_stack_alloc(
size_t size)
611 if (machine_stack_cache_index > 0) {
612 if (machine_stack_cache[machine_stack_cache_index - 1].size == (size /
sizeof(
VALUE))) {
613 ptr = machine_stack_cache[machine_stack_cache_index - 1].ptr;
614 machine_stack_cache_index--;
615 machine_stack_cache[machine_stack_cache_index].ptr =
NULL;
616 machine_stack_cache[machine_stack_cache_index].size = 0;
620 rb_bug(
"machine_stack_cache size is not canonicalized");
628 ptr = mmap(
NULL, size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
629 if (ptr == MAP_FAILED) {
635 if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) {
645 fiber_initialize_machine_stack_context(
rb_fiber_t *fib,
size_t size)
650 fib->fib_handle = CreateFiberEx(size - 1, size, 0, fiber_entry,
NULL);
651 if (!fib->fib_handle) {
654 fib->fib_handle = CreateFiberEx(size - 1, size, 0, fiber_entry,
NULL);
655 if (!fib->fib_handle) {
661 ucontext_t *context = &fib->context;
666 ptr = fiber_machine_stack_alloc(size);
667 context->uc_link =
NULL;
668 context->uc_stack.ss_sp = ptr;
669 context->uc_stack.ss_size =
size;
694 rb_bug(
"fiber_setcontext: sth->machine.stack_end has non zero value");
717 rb_bug(
"non_root_fiber->context.uc_stac.ss_sp should not be NULL");
723 SwitchToFiber(newfib->fib_handle);
725 swapcontext(&oldfib->context, &newfib->context);
743 ((_JUMP_BUFFER*)(&cont->
jmpbuf))->Frame =
744 ((_JUMP_BUFFER*)(&
buf))->Frame;
754 if (cont->
machine.register_stack_src) {
766 #define C(a) rse_##a##0, rse_##a##1, rse_##a##2, rse_##a##3, rse_##a##4
767 #define E(a) rse_##a##0= rse_##a##1= rse_##a##2= rse_##a##3= rse_##a##4
768 static volatile int C(a),
C(b),
C(
c),
C(d),
C(e);
769 static volatile int C(f),
C(g),
C(h),
C(i),
C(j);
770 static volatile int C(k),
C(l),
C(m),
C(n),
C(o);
771 static volatile int C(p),
C(q),
C(r),
C(s),
C(t);
775 int rb_dummy_false = 0;
780 if (rb_dummy_false) {
782 E(a) = E(b) = E(
c) = E(d) = E(e) =
783 E(f) = E(g) = E(h) = E(i) = E(j) =
784 E(k) = E(l) = E(m) = E(n) = E(o) =
785 E(p) = E(q) = E(r) = E(s) = E(t) = 0;
786 E(a) = E(b) = E(
c) = E(d) = E(e) =
787 E(f) = E(g) = E(h) = E(i) = E(j) =
788 E(k) = E(l) = E(m) = E(n) = E(o) =
789 E(p) = E(q) = E(r) = E(s) = E(t) = 0;
791 if (curr_bsp < cont->machine.register_stack_src+cont->
machine.register_stack_size) {
792 register_stack_extend(cont, vp, (
VALUE*)rb_ia64_bsp());
805 #define STACK_PAD_SIZE 1
807 #define STACK_PAD_SIZE 1024
811 #if !STACK_GROW_DIRECTION
812 if (addr_in_prev_frame > &space[0]) {
815 #if STACK_GROW_DIRECTION <= 0
817 if (&space[0] > end) {
826 #if !STACK_GROW_DIRECTION
831 #if STACK_GROW_DIRECTION >= 0
842 #if !STACK_GROW_DIRECTION
849 #define cont_restore_0(cont, vp) register_stack_extend((cont), (vp), (VALUE*)rb_ia64_bsp())
979 for (p=current; p; p=p->
next)
982 for (entry=target; entry->
marker; entry++)
987 base_point = cur_size;
989 if (target_size >= base_point &&
997 for (i=0; i < target_size - base_point; i++) {
1003 while (cur_size > base_point) {
1006 current = current->
next;
1013 (*func)(target[i].
data2);
1191 #if VM_DEBUG_BP_CHECK
1192 th->
cfp->bp_check = 0;
1208 #if !FIBER_USE_NATIVE
1240 if (root_fiber == curr) {
1258 #if FIBER_USE_NATIVE && !defined(_WIN32)
1260 terminated_machine_stack.ptr = fib->context.uc_stack.ss_sp;
1261 terminated_machine_stack.size = fib->context.uc_stack.ss_size /
sizeof(
VALUE);
1262 fib->context.uc_stack.ss_sp =
NULL;
1310 rb_bug(
"rb_fiber_start: unreachable");
1320 #if FIBER_USE_NATIVE
1322 fib->fib_handle = ConvertThreadToFiber(0);
1335 if (th->
fiber == 0) {
1359 #if !FIBER_USE_NATIVE
1364 #if FIBER_USE_NATIVE
1365 fiber_setcontext(next_fib, fib);
1367 if (terminated_machine_stack.ptr) {
1368 if (machine_stack_cache_index < MAX_MACHINE_STACK_CACHE) {
1369 machine_stack_cache[machine_stack_cache_index].ptr = terminated_machine_stack.ptr;
1370 machine_stack_cache[machine_stack_cache_index].size = terminated_machine_stack.size;
1371 machine_stack_cache_index++;
1375 munmap((
void*)terminated_machine_stack.ptr, terminated_machine_stack.size *
sizeof(
VALUE));
1378 rb_bug(
"terminated fiber resumed");
1381 terminated_machine_stack.ptr =
NULL;
1382 terminated_machine_stack.size = 0;
1391 #if !FIBER_USE_NATIVE
1409 if (th->
fiber == fibval) {
1424 if (th->
fiber != fibval) {
1436 cont->
value = value;
1437 #if FIBER_USE_NATIVE
1443 fiber_setcontext(fib, oldfib);
1462 #if !FIBER_USE_NATIVE
1465 rb_bug(
"rb_fiber_resume: unreachable");
1654 #if FIBER_USE_NATIVE
1659 GetSystemInfo(&info);
1660 pagesize = info.dwPageSize;
1662 pagesize = sysconf(_SC_PAGESIZE);