diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-12-19 22:29:18 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-12-19 22:29:18 +0000 |
commit | 87e1616048edca270c86ab7e5d8b8599e1df79de (patch) | |
tree | 97ab05b808201a66b21d7cacbc5702769507abcf /vm.c | |
parent | 5d92f6ec05be5df5f89f81fb926ad08faf22ee03 (diff) | |
download | ruby-87e1616048edca270c86ab7e5d8b8599e1df79de.tar.gz |
* vm.c: support variable VM/Machine stack sizes.
Specified by the following environment variaables:
- RUBY_THREAD_VM_STACK_SIZE: vm stack size used at thread creation.
default: 128KB (32bit CPU) or 256KB (64bit CPU).
- RUBY_THREAD_MACHINE_STACK_SIZE: machine stack size used at thread
creation. default: 512KB or 1024KB.
- RUBY_FIBER_VM_STACK_SIZE: vm stack size used at fiber creation.
default: 64KB or 128KB.
- RUBY_FIBER_MACHINE_STACK_SIZE: machine stack size used at fiber
creation. default: 256KB or 256KB.
This values are specified at launched timing. You can not change
these values at running time.
Environ variables are only *hints* because:
- They are aligned to 4KB.
- They have minimum values (depend on OSs).
- Machine stack settings are ignored by some OSs.
Default values especially fiber stack sizes are increased.
This change affect Fiber's behavior:
(1) You can run more complex program on a Fiber.
(2) You can not make many (thousands) Fibers because of
lack of address space (on 32bit CPU).
If (2) bothers you,
(a) Use 64bit CPU with big memory, or
(b) Specify RUBY_FIBER_(VM|MACHINE)_STACK_SIZE correctly.
You need to choose correct stack size carefully. These values
are completely rely on systems (OS/compiler and so on).
* vm_core.h (rb_vm_t::default_params): add to record above settings.
* vm.c (RubyVM::DEFAULT_PARAMS): add new constant to see
above setting.
* thread_pthread.c: support RUBY_THREAD_MACHINE_STACK_SIZE.
* cont.c: support RUBY_FIBER_(VM|MACHINE)_STACK_SIZE.
* test/ruby/test_fiber.rb: add tests for above.
* test/ruby/test_thread.rb: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38478 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 97 |
1 files changed, 93 insertions, 4 deletions
@@ -1613,6 +1613,82 @@ static const rb_data_type_t vm_data_type = { {rb_vm_mark, vm_free, vm_memsize,}, }; + +static VALUE +vm_default_params(void) +{ + rb_vm_t *vm = GET_VM(); + VALUE result = rb_hash_new(); +#define SET(name) rb_hash_aset(result, ID2SYM(rb_intern(#name)), SIZET2NUM(vm->default_params.name)); + SET(thread_vm_stack_size); + SET(thread_machine_stack_size); + SET(fiber_vm_stack_size); + SET(fiber_machine_stack_size); +#undef SET + rb_obj_freeze(result); + return result; +} + +static size_t +get_param(const char *name, size_t default_value, size_t min_value) +{ + const char *envval; + size_t result = default_value; + if ((envval = getenv(name)) != 0) { + long val = atol(envval); + if (val < (long)min_value) { + val = (long)min_value; + } + result = (size_t)(((val -1 + RUBY_VM_SIZE_ALIGN) / RUBY_VM_SIZE_ALIGN) * RUBY_VM_SIZE_ALIGN); + } + if (0) fprintf(stderr, "%s: %d\n", name, result); /* debug print */ + + return result; +} + +static void +check_machine_stack_size(size_t *sizep) +{ + size_t size = *sizep; +#ifdef __SYMBIAN32__ + *sizep = 64 * 1024; /* 64KB: Let's be slightly more frugal on mobile platform */ +#endif + +#ifdef PTHREAD_STACK_MIN + if (size < PTHREAD_STACK_MIN) { + *sizep = PTHREAD_STACK_MIN * 2; + } +#endif +} + +static void +vm_default_params_setup(rb_vm_t *vm) +{ + vm->default_params.thread_vm_stack_size = + get_param("RUBY_THREAD_VM_STACK_SIZE", + RUBY_VM_THREAD_VM_STACK_SIZE, + RUBY_VM_THREAD_VM_STACK_SIZE_MIN); + + vm->default_params.thread_machine_stack_size = + get_param("RUBY_THREAD_MACHINE_STACK_SIZE", + RUBY_VM_THREAD_MACHINE_STACK_SIZE, + RUBY_VM_THREAD_MACHINE_STACK_SIZE_MIN); + + vm->default_params.fiber_vm_stack_size = + get_param("RUBY_FIBER_VM_STACK_SIZE", + RUBY_VM_FIBER_VM_STACK_SIZE, + RUBY_VM_FIBER_VM_STACK_SIZE_MIN); + + vm->default_params.fiber_machine_stack_size = + get_param("RUBY_FIBER_MACHINE_STACK_SIZE", + RUBY_VM_FIBER_MACHINE_STACK_SIZE, + RUBY_VM_FIBER_MACHINE_STACK_SIZE_MIN); + + /* environment dependent check */ + check_machine_stack_size(&vm->default_params.thread_machine_stack_size); + check_machine_stack_size(&vm->default_params.fiber_machine_stack_size); +} + static void vm_init2(rb_vm_t *vm) { @@ -1620,6 +1696,8 @@ vm_init2(rb_vm_t *vm) vm->src_encoding_index = -1; vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */ vm->at_exit.basic.klass = 0; + + vm_default_params_setup(vm); } /* Thread */ @@ -1635,6 +1713,7 @@ static VALUE * thread_recycle_stack(size_t size) { if (thread_recycle_stack_count) { + /* TODO: check stack size if stack sizes are variable */ return thread_recycle_stack_slot[--thread_recycle_stack_count]; } else { @@ -1839,7 +1918,10 @@ th_init(rb_thread_t *th, VALUE self) /* altstack of main thread is reallocated in another place */ th->altstack = malloc(rb_sigaltstack_size()); #endif - th->stack_size = RUBY_VM_THREAD_STACK_SIZE; + /* th->stack_size is word number. + * th->vm->default_params.thread_vm_stack_size is byte size. + */ + th->stack_size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE); th->stack = thread_recycle_stack(th->stack_size); th->cfp = (void *)(th->stack + th->stack_size); @@ -1864,9 +1946,9 @@ ruby_thread_init(VALUE self) rb_vm_t *vm = GET_THREAD()->vm; GetThreadPtr(self, th); + th->vm = vm; th_init(th, self); rb_iv_set(self, "locals", rb_hash_new()); - th->vm = vm; th->top_wrapper = 0; th->top_self = rb_vm_top_self(); @@ -2189,6 +2271,14 @@ Init_VM(void) /* ::RubyVM::INSTRUCTION_NAMES */ rb_define_const(rb_cRubyVM, "INSTRUCTION_NAMES", rb_insns_name_array()); + /* ::RubyVM::DEFAULT_PARAMS + * This constant variable shows VM's default parameters. + * Note that changing these values does not affect VM exection. + * Specification is not stable and you should not depend on this value. + * Of course, this constant is MRI specific. + */ + rb_define_const(rb_cRubyVM, "DEFAULT_PARAMS", vm_default_params()); + /* debug functions ::RubyVM::SDR(), ::RubyVM::NSDR() */ #if VMDEBUG rb_define_singleton_method(rb_cRubyVM, "SDR", sdr, 0); @@ -2266,7 +2356,6 @@ Init_BareVM(void) exit(EXIT_FAILURE); } MEMZERO(th, rb_thread_t, 1); - rb_thread_set_current_raw(th); vm_init2(vm); @@ -2276,8 +2365,8 @@ Init_BareVM(void) ruby_current_vm = vm; Init_native_thread(); - th_init(th, 0); th->vm = vm; + th_init(th, 0); ruby_thread_init_stack(th); } |