aboutsummaryrefslogtreecommitdiffstats
path: root/cont.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-09-12 20:49:10 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-09-12 20:49:10 +0000
commit89e668f2571612d231084f329d264dbc9c877763 (patch)
treef923db7caf3476b3d907307dc7a4ad6ec31317a7 /cont.c
parent2b26ace900d51129072ee6391037e9951ff2ca48 (diff)
downloadruby-89e668f2571612d231084f329d264dbc9c877763.tar.gz
share VM stack between threads and fibers if identical in size
ec->vm_stack is always allocated with malloc, so stack cache for root fiber (thread stack) and non-root fibers can be shared as long as the size is the same. The purpose of this change is to reduce dependencies on ROOT_FIBER_CONTEXT. [Feature #15095] [Bug #15050] v2: vm.c: fix build with USE_THREAD_DATA_RECYCLE==0 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64703 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'cont.c')
-rw-r--r--cont.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/cont.c b/cont.c
index 7bc1724176..29c18a8eb2 100644
--- a/cont.c
+++ b/cont.c
@@ -1411,13 +1411,20 @@ fiber_init(VALUE fibval, VALUE proc)
rb_context_t *cont = &fib->cont;
rb_execution_context_t *sec = &cont->saved_ec;
rb_thread_t *cth = GET_THREAD();
- size_t fib_stack_size = cth->vm->default_params.fiber_vm_stack_size / sizeof(VALUE);
+ rb_vm_t *vm = cth->vm;
+ size_t fib_stack_bytes = vm->default_params.fiber_vm_stack_size;
+ size_t thr_stack_bytes = vm->default_params.thread_vm_stack_size;
+ VALUE *vm_stack;
/* initialize cont */
cont->saved_vm_stack.ptr = NULL;
- ec_set_vm_stack(sec, NULL, 0);
-
- ec_set_vm_stack(sec, ALLOC_N(VALUE, fib_stack_size), fib_stack_size);
+ if (fib_stack_bytes == thr_stack_bytes) {
+ vm_stack = rb_thread_recycle_stack(fib_stack_bytes / sizeof(VALUE));
+ }
+ else {
+ vm_stack = ruby_xmalloc(fib_stack_bytes);
+ }
+ ec_set_vm_stack(sec, vm_stack, fib_stack_bytes / sizeof(VALUE));
sec->cfp = (void *)(sec->vm_stack + sec->vm_stack_size);
rb_vm_push_frame(sec,
@@ -1758,19 +1765,22 @@ rb_fiber_transfer(VALUE fibval, int argc, const VALUE *argv)
void
rb_fiber_close(rb_fiber_t *fib)
{
- VALUE *vm_stack = fib->cont.saved_ec.vm_stack;
+ rb_execution_context_t *ec = &fib->cont.saved_ec;
+ VALUE *vm_stack = ec->vm_stack;
+ size_t stack_bytes = ec->vm_stack_size * sizeof(VALUE);
+
fiber_status_set(fib, FIBER_TERMINATED);
- if (fib->cont.type == ROOT_FIBER_CONTEXT) {
- rb_thread_recycle_stack_release(vm_stack);
+ if (stack_bytes == rb_ec_vm_ptr(ec)->default_params.thread_vm_stack_size) {
+ rb_thread_recycle_stack_release(vm_stack);
}
else {
- ruby_xfree(vm_stack);
+ ruby_xfree(vm_stack);
}
- ec_set_vm_stack(&fib->cont.saved_ec, NULL, 0);
+ ec_set_vm_stack(ec, NULL, 0);
#if !FIBER_USE_NATIVE
/* should not mark machine stack any more */
- fib->cont.saved_ec.machine.stack_end = NULL;
+ ec->machine.stack_end = NULL;
#endif
}