1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135 |
- diff --git a/eval.c b/eval.c
- index b705302..909cd3d 100644
- --- a/eval.c
- +++ b/eval.c
- @@ -73,6 +73,7 @@ char *strrchr _((const char*,const char));
- #endif
-
- #include <time.h>
- +#include <sys/mman.h>
-
- #ifdef __BEOS__
- #include <net/socket.h>
- @@ -1022,7 +1023,7 @@ static struct tag *prot_tag;
- _tag.blkid = 0; \
- prot_tag = &_tag
-
- -#define PROT_NONE Qfalse /* 0 */
- +#define PROT_EMPTY Qfalse /* 0 */
- #define PROT_THREAD Qtrue /* 2 */
- #define PROT_FUNC INT2FIX(0) /* 1 */
- #define PROT_LOOP INT2FIX(1) /* 3 */
- @@ -1234,7 +1235,7 @@ error_print()
-
- if (NIL_P(ruby_errinfo)) return;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if (EXEC_TAG() == 0) {
- errat = get_backtrace(ruby_errinfo);
- }
- @@ -1395,7 +1396,7 @@ ruby_init()
- /* default visibility is private at toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- rb_call_inits();
- ruby_class = rb_cObject;
- @@ -1529,7 +1530,7 @@ ruby_options(argc, argv)
- int state;
-
- Init_stack((void*)&state);
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- ruby_process_options(argc, argv);
- }
- @@ -1546,7 +1547,7 @@ void rb_exec_end_proc _((void));
- static void
- ruby_finalize_0()
- {
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if (EXEC_TAG() == 0) {
- rb_trap_exit();
- }
- @@ -1584,7 +1585,7 @@ ruby_cleanup(ex)
- Init_stack((void *)&state);
- ruby_finalize_0();
- errs[0] = ruby_errinfo;
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- PUSH_ITER(ITER_NOT);
- if ((state = EXEC_TAG()) == 0) {
- rb_thread_cleanup();
- @@ -1635,7 +1636,7 @@ ruby_exec_internal()
- {
- int state;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- PUSH_ITER(ITER_NOT);
- /* default visibility is private at toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
- @@ -1857,7 +1858,7 @@ rb_eval_cmd(cmd, arg, level)
- }
- if (TYPE(cmd) != T_STRING) {
- PUSH_ITER(ITER_NOT);
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- ruby_safe_level = level;
- if ((state = EXEC_TAG()) == 0) {
- val = rb_funcall2(cmd, rb_intern("call"), RARRAY(arg)->len, RARRAY(arg)->ptr);
- @@ -1879,7 +1880,7 @@ rb_eval_cmd(cmd, arg, level)
-
- ruby_safe_level = level;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- val = eval(ruby_top_self, cmd, Qnil, 0, 0);
- }
- @@ -2386,7 +2387,7 @@ is_defined(self, node, buf)
- val = self;
- if (node->nd_recv == (NODE *)1) goto check_bound;
- case NODE_CALL:
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- val = rb_eval(self, node->nd_recv);
- }
- @@ -2488,7 +2489,7 @@ is_defined(self, node, buf)
- break;
-
- case NODE_COLON2:
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- val = rb_eval(self, node->nd_head);
- }
- @@ -2537,7 +2538,7 @@ is_defined(self, node, buf)
- goto again;
-
- default:
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- rb_eval(self, node);
- }
- @@ -2741,7 +2742,7 @@ call_trace_func(event, node, self, id, klass)
- klass = rb_iv_get(klass, "__attached__");
- }
- }
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- raised = rb_thread_reset_raised(th);
- if ((state = EXEC_TAG()) == 0) {
- srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
- @@ -3304,7 +3305,7 @@ rb_eval(self, n)
- volatile VALUE e_info = ruby_errinfo;
- volatile int rescuing = 0;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- retry_entry:
- result = rb_eval(self, node->nd_head);
- @@ -3353,7 +3354,7 @@ rb_eval(self, n)
- break;
-
- case NODE_ENSURE:
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_head);
- }
- @@ -3571,7 +3572,7 @@ rb_eval(self, n)
- ruby_frame = &frame;
-
- PUSH_SCOPE();
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if (node->nd_rval) {
- saved_cref = ruby_cref;
- ruby_cref = (NODE*)node->nd_rval;
- @@ -4197,7 +4198,7 @@ module_setup(module, n)
- }
-
- PUSH_CREF(module);
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- EXEC_EVENT_HOOK(RUBY_EVENT_CLASS, n, ruby_cbase,
- ruby_frame->last_func, ruby_frame->last_class);
- @@ -4604,7 +4605,7 @@ rb_longjmp(tag, mesg)
- VALUE e = ruby_errinfo;
- int status;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((status = EXEC_TAG()) == 0) {
- StringValue(e);
- warn_printf("Exception `%s' at %s:%d - %s\n",
- @@ -4978,7 +4979,7 @@ rb_yield_0(val, self, klass, flags, avalue)
- var = block->var;
-
- if (var) {
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- NODE *bvar = NULL;
- block_var:
- @@ -5051,7 +5052,7 @@ rb_yield_0(val, self, klass, flags, avalue)
- ruby_current_node = node;
-
- PUSH_ITER(block->iter);
- - PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
- + PUSH_TAG(lambda ? PROT_EMPTY : PROT_YIELD);
- if ((state = EXEC_TAG()) == 0) {
- redo:
- if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
- @@ -5464,7 +5465,7 @@ rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
- VALUE eclass;
- va_list args;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- switch (state = EXEC_TAG()) {
- case TAG_RETRY:
- if (!handle) break;
- @@ -5522,7 +5523,7 @@ rb_protect(proc, data, state)
- VALUE result = Qnil; /* OK */
- int status;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- cont_protect = (VALUE)rb_node_newnode(NODE_MEMO, cont_protect, 0, 0);
- if ((status = EXEC_TAG()) == 0) {
- result = (*proc)(data);
- @@ -5550,7 +5551,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
- volatile VALUE result = Qnil;
- VALUE retval;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- result = (*b_proc)(data1);
- }
- @@ -5577,7 +5578,7 @@ rb_with_disable_interrupt(proc, data)
- int thr_critical = rb_thread_critical;
-
- rb_thread_critical = Qtrue;
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((status = EXEC_TAG()) == 0) {
- result = (*proc)(data);
- }
- @@ -6264,7 +6265,7 @@ rb_funcall_rescue(recv, mid, n, va_alist)
-
- va_init_list(ar, n);
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((status = EXEC_TAG()) == 0) {
- result = vafuncall(recv, mid, n, &ar);
- }
- @@ -6539,7 +6540,7 @@ eval(self, src, scope, file, line)
- if (TYPE(ruby_class) == T_ICLASS) {
- ruby_class = RBASIC(ruby_class)->klass;
- }
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- NODE *node;
-
- @@ -6698,7 +6699,7 @@ exec_under(func, under, cbase, args)
-
- mode = scope_vmode;
- SCOPE_SET(SCOPE_PUBLIC);
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- val = (*func)(args);
- }
- @@ -7009,7 +7010,7 @@ rb_load(fname, wrap)
- PUSH_SCOPE();
- /* default visibility is private at loading toplevel */
- SCOPE_SET(SCOPE_PRIVATE);
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- state = EXEC_TAG();
- last_func = ruby_frame->last_func;
- last_node = ruby_current_node;
- @@ -7068,7 +7069,7 @@ rb_load_protect(fname, wrap, state)
- {
- int status;
-
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((status = EXEC_TAG()) == 0) {
- rb_load(fname, wrap);
- }
- @@ -7389,7 +7390,7 @@ rb_require_safe(fname, safe)
- saved.node = ruby_current_node;
- saved.func = ruby_frame->last_func;
- saved.safe = ruby_safe_level;
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- VALUE feature, path;
- long handle;
- @@ -8097,7 +8098,7 @@ rb_exec_end_proc()
- tmp_end_procs = link = ephemeral_end_procs;
- ephemeral_end_procs = 0;
- while (link) {
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((status = EXEC_TAG()) == 0) {
- ruby_safe_level = link->safe;
- (*link->func)(link->data);
- @@ -8115,7 +8116,7 @@ rb_exec_end_proc()
- tmp_end_procs = link = end_procs;
- end_procs = 0;
- while (link) {
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((status = EXEC_TAG()) == 0) {
- ruby_safe_level = link->safe;
- (*link->func)(link->data);
- @@ -8852,7 +8853,7 @@ proc_invoke(proc, args, self, klass)
- ruby_block = &_block;
- PUSH_ITER(ITER_CUR);
- ruby_frame->iter = ITER_CUR;
- - PUSH_TAG(pcall ? PROT_LAMBDA : PROT_NONE);
- + PUSH_TAG(pcall ? PROT_LAMBDA : PROT_EMPTY);
- state = EXEC_TAG();
- if (state == 0) {
- proc_set_safe_level(proc);
- @@ -10179,6 +10180,7 @@ win32_set_exception_list(p)
- int rb_thread_pending = 0;
-
- VALUE rb_cThread;
- +static unsigned int rb_thread_stack_size;
-
- extern VALUE rb_last_status;
-
- @@ -10406,12 +10408,20 @@ thread_mark(th)
- rb_gc_mark(th->thread);
- if (th->join) rb_gc_mark(th->join->thread);
-
- - rb_gc_mark(th->klass);
- - rb_gc_mark(th->wrapper);
- - rb_gc_mark((VALUE)th->cref);
- + if (curr_thread == th) {
- + rb_gc_mark(ruby_class);
- + rb_gc_mark(ruby_wrapper);
- + rb_gc_mark((VALUE)ruby_cref);
- + rb_gc_mark((VALUE)ruby_scope);
- + rb_gc_mark((VALUE)ruby_dyna_vars);
- + } else {
- + rb_gc_mark(th->klass);
- + rb_gc_mark(th->wrapper);
- + rb_gc_mark((VALUE)th->cref);
- + rb_gc_mark((VALUE)th->scope);
- + rb_gc_mark((VALUE)th->dyna_vars);
- + }
-
- - rb_gc_mark((VALUE)th->scope);
- - rb_gc_mark((VALUE)th->dyna_vars);
- rb_gc_mark(th->errinfo);
- rb_gc_mark(th->last_status);
- rb_gc_mark(th->last_line);
- @@ -10421,11 +10431,11 @@ thread_mark(th)
- rb_gc_mark_maybe(th->sandbox);
-
- /* mark data in copied stack */
- - if (th == curr_thread) return;
- + if (th == main_thread) return;
- if (th->status == THREAD_KILLED) return;
- if (th->stk_len == 0) return; /* stack not active, no need to mark. */
- - if (th->stk_ptr) {
- - rb_gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
- + if (th->stk_ptr && th != curr_thread) {
- + rb_gc_mark_locations(th->stk_pos, th->stk_base);
- #if defined(THINK_C) || defined(__human68k__)
- rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
- #endif
- @@ -10435,24 +10445,30 @@ thread_mark(th)
- }
- #endif
- }
- - frame = th->frame;
- +
- + if (curr_thread == th)
- + frame = ruby_frame;
- + else
- + frame = th->frame;
- +
- while (frame && frame != top_frame) {
- - frame = ADJ(frame);
- rb_gc_mark_frame(frame);
- if (frame->tmp) {
- struct FRAME *tmp = frame->tmp;
- -
- while (tmp && tmp != top_frame) {
- - tmp = ADJ(tmp);
- rb_gc_mark_frame(tmp);
- tmp = tmp->prev;
- }
- }
- frame = frame->prev;
- }
- - block = th->block;
- +
- + if (curr_thread == th)
- + block = ruby_block;
- + else
- + block = th->block;
- +
- while (block) {
- - block = ADJ(block);
- rb_gc_mark_frame(&block->frame);
- block = block->prev;
- }
- @@ -10515,7 +10531,7 @@ static inline void
- stack_free(th)
- rb_thread_t th;
- {
- - if (th->stk_ptr) free(th->stk_ptr);
- + if (th->stk_ptr) munmap(th->stk_ptr, th->stk_size);
- th->stk_ptr = 0;
- #ifdef __ia64
- if (th->bstr_ptr) free(th->bstr_ptr);
- @@ -10576,35 +10592,8 @@ rb_thread_save_context(th)
- static VALUE tval;
-
- len = ruby_stack_length(&pos);
- - th->stk_len = 0;
- - th->stk_pos = pos;
- - if (len > th->stk_max) {
- - VALUE *ptr = realloc(th->stk_ptr, sizeof(VALUE) * len);
- - if (!ptr) rb_memerror();
- - th->stk_ptr = ptr;
- - th->stk_max = len;
- - }
- th->stk_len = len;
- - FLUSH_REGISTER_WINDOWS;
- - MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
- -#ifdef __ia64
- - th->bstr_pos = rb_gc_register_stack_start;
- - len = (VALUE*)rb_ia64_bsp() - th->bstr_pos;
- - th->bstr_len = 0;
- - if (len > th->bstr_max) {
- - VALUE *ptr = realloc(th->bstr_ptr, sizeof(VALUE) * len);
- - if (!ptr) rb_memerror();
- - th->bstr_ptr = ptr;
- - th->bstr_max = len;
- - }
- - th->bstr_len = len;
- - rb_ia64_flushrs();
- - MEMCPY(th->bstr_ptr, th->bstr_pos, VALUE, th->bstr_len);
- -#endif
- -#ifdef SAVE_WIN32_EXCEPTION_LIST
- - th->win32_exception_list = win32_get_exception_list();
- -#endif
- -
- + th->stk_pos = pos;
- th->frame = ruby_frame;
- th->scope = ruby_scope;
- ruby_scope->flags |= SCOPE_DONT_RECYCLE;
- @@ -10714,11 +10703,6 @@ rb_thread_restore_context_0(rb_thread_t th, int exit)
- #endif
- tmp = th;
- ex = exit;
- - FLUSH_REGISTER_WINDOWS;
- - MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
- -#ifdef __ia64
- - MEMCPY(tmp->bstr_pos, tmp->bstr_ptr, VALUE, tmp->bstr_len);
- -#endif
-
- tval = rb_lastline_get();
- rb_lastline_set(tmp->last_line);
- @@ -10809,8 +10793,8 @@ rb_thread_restore_context(th, exit)
- rb_thread_t th;
- int exit;
- {
- - if (!th->stk_ptr) rb_bug("unsaved context");
- - stack_extend(th, exit);
- + if (!th->stk_ptr && th != main_thread) rb_bug("unsaved context");
- + rb_thread_restore_context_0(th, exit);
- }
-
- static void
- @@ -10829,7 +10813,6 @@ rb_thread_die(th)
- {
- th->thgroup = 0;
- th->status = THREAD_KILLED;
- - stack_free(th);
- }
-
- static void
- @@ -12096,6 +12079,7 @@ rb_thread_group(thread)
- \
- th->stk_ptr = 0;\
- th->stk_len = 0;\
- + th->stk_size = 0;\
- th->stk_max = 0;\
- th->wait_for = 0;\
- IA64_INIT(th->bstr_ptr = 0);\
- @@ -12143,6 +12127,48 @@ rb_thread_alloc(klass)
- THREAD_ALLOC(th);
- th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th);
-
- + /* if main_thread != NULL, then this is NOT the main thread, so
- + * we create a heap-stack
- + */
- + if (main_thread) {
- + /* Allocate stack, don't forget to add 1 extra word because of the MATH below */
- + unsigned int pagesize = getpagesize();
- + unsigned int total_size = rb_thread_stack_size + pagesize + sizeof(int);
- + void *stack_area = NULL;
- +
- + stack_area = mmap(NULL, total_size, PROT_READ | PROT_WRITE | PROT_EXEC,
- + MAP_PRIVATE | MAP_ANON, -1, 0);
- +
- + if (stack_area == MAP_FAILED) {
- + fprintf(stderr, "Thread stack allocation failed!\n");
- + rb_memerror();
- + }
- +
- + th->stk_ptr = th->stk_pos = stack_area;
- + th->stk_size = total_size;
- +
- + if (mprotect(th->stk_ptr, pagesize, PROT_NONE) == -1) {
- + fprintf(stderr, "Failed to create thread guard region: %s\n", strerror(errno));
- + rb_memerror();
- + }
- +
- + th->guard = th->stk_ptr + (pagesize/sizeof(VALUE *));
- +
- + /* point stk_base at the top of the stack */
- + /* ASSUMPTIONS:
- + * 1.) The address returned by malloc is "suitably aligned" for anything on this system
- + * 2.) Adding a value that is "aligned" for this platform should not unalign the address
- + * returned from malloc.
- + * 3.) Don't push anything on to the stack, otherwise it'll get unaligned.
- + * 4.) x86_64 ABI says aligned AFTER arguments have been pushed. You *must* then do a call[lq]
- + * or push[lq] something else on to the stack if you inted to do a ret.
- + */
- + th->stk_base = th->stk_ptr + ((total_size - sizeof(int))/sizeof(VALUE *));
- + th->stk_len = rb_thread_stack_size;
- + } else {
- + th->stk_ptr = th->stk_pos = rb_gc_stack_start;
- + }
- +
- for (vars = th->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- @@ -12246,17 +12272,22 @@ rb_thread_stop_timer()
- int rb_thread_tick = THREAD_TICK;
- #endif
-
- +struct thread_start_args {
- + VALUE (*fn)();
- + void *arg;
- + rb_thread_t th;
- +} new_th;
- +
- +static VALUE
- +rb_thread_start_2();
- +
- static VALUE
- rb_thread_start_0(fn, arg, th)
- VALUE (*fn)();
- void *arg;
- rb_thread_t th;
- {
- - volatile rb_thread_t th_save = th;
- volatile VALUE thread = th->thread;
- - struct BLOCK *volatile saved_block = 0;
- - enum rb_thread_status status;
- - int state;
-
- if (OBJ_FROZEN(curr_thread->thgroup)) {
- rb_raise(rb_eThreadError,
- @@ -12284,16 +12315,41 @@ rb_thread_start_0(fn, arg, th)
- return thread;
- }
-
- - if (ruby_block) { /* should nail down higher blocks */
- - struct BLOCK dummy;
- + new_th.fn = fn;
- + new_th.arg = arg;
- + new_th.th = th;
- +
- +#if defined(__i386__)
- + __asm__ __volatile__ ("movl %0, %%esp\n\t"
- + "calll *%1\n"
- + :: "r" (th->stk_base),
- + "r" (rb_thread_start_2));
- +#elif defined(__x86_64__)
- + __asm__ __volatile__ ("movq %0, %%rsp\n\t"
- + "callq *%1\n"
- + :: "r" (th->stk_base),
- + "r" (rb_thread_start_2));
- +#else
- + #error unsupported architecture!
- +#endif
- + /* NOTREACHED */
- + return 0;
- +}
-
- - dummy.prev = ruby_block;
- - blk_copy_prev(&dummy);
- - saved_block = ruby_block = dummy.prev;
- - }
- - scope_dup(ruby_scope);
- +static VALUE
- +rb_thread_start_2()
- +{
- + volatile rb_thread_t th = new_th.th;
- + volatile rb_thread_t th_save = th;
- + volatile VALUE thread = th->thread;
- + struct BLOCK *volatile saved_block = 0;
- + enum rb_thread_status status;
- + int state;
- + struct tag *tag;
- + struct RVarmap *vars;
- + struct FRAME dummy_frame;
-
- - if (!th->next) {
- + if (!th->next) {
- /* merge in thread list */
- th->prev = curr_thread;
- curr_thread->next->prev = th;
- @@ -12301,13 +12357,27 @@ rb_thread_start_0(fn, arg, th)
- curr_thread->next = th;
- th->priority = curr_thread->priority;
- th->thgroup = curr_thread->thgroup;
- + }
- + curr_thread = th;
- +
- + dummy_frame = *ruby_frame;
- + dummy_frame.prev = top_frame;
- + ruby_frame = &dummy_frame;
- +
- + if (ruby_block) { /* should nail down higher blocks */
- + struct BLOCK dummy;
- +
- + dummy.prev = ruby_block;
- + blk_copy_prev(&dummy);
- + saved_block = ruby_block = dummy.prev;
- }
-
- + scope_dup(ruby_scope);
- +
- PUSH_TAG(PROT_THREAD);
- if ((state = EXEC_TAG()) == 0) {
- if (THREAD_SAVE_CONTEXT(th) == 0) {
- - curr_thread = th;
- - th->result = (*fn)(arg, th);
- + th->result = (*new_th.fn)(new_th.arg, th);
- }
- th = th_save;
- }
- @@ -12644,6 +12714,43 @@ rb_thread_cleanup()
- END_FOREACH_FROM(curr, th);
- }
-
- +/*
- + * call-seq:
- + * Thread.stack_size => fixnum
- + *
- + * Returns the thread stack size in bytes
- + */
- +static VALUE
- +rb_thread_stacksize_get()
- +{
- + return INT2FIX(rb_thread_stack_size);
- +}
- +
- +/*
- + * call-seq:
- + * Thread.stack_size= fixnum => Qnil
- + *
- + * Sets the global thread stacksize and returns Qnil.
- + */
- +static VALUE
- +rb_thread_stacksize_set(obj, val)
- + VALUE obj;
- + VALUE val;
- +{
- +
- + unsigned int size = FIX2UINT(val);
- +
- + /* 16byte alignment works for both x86 and x86_64 */
- + if (size & (~0xf)) {
- + size += 0x10;
- + size = size & (~0xf);
- + }
- +
- + rb_thread_stack_size = size;
- +
- + return Qnil;
- +}
- +
- int rb_thread_critical;
-
-
- @@ -13473,7 +13580,7 @@ rb_exec_recursive(func, obj, arg)
- int state;
-
- hash = recursive_push(hash, objid);
- - PUSH_TAG(PROT_NONE);
- + PUSH_TAG(PROT_EMPTY);
- if ((state = EXEC_TAG()) == 0) {
- result = (*func) (obj, arg, Qfalse);
- }
- @@ -13500,6 +13607,8 @@ Init_Thread()
- {
- VALUE cThGroup;
-
- + rb_thread_stack_size = (1024 * 1024);
- +
- recursive_key = rb_intern("__recursive_key__");
- rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
- rb_cThread = rb_define_class("Thread", rb_cObject);
- @@ -13524,6 +13633,9 @@ Init_Thread()
- rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
- rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
-
- + rb_define_singleton_method(rb_cThread, "stack_size", rb_thread_stacksize_get, 0);
- + rb_define_singleton_method(rb_cThread, "stack_size=", rb_thread_stacksize_set, 1);
- +
- rb_define_method(rb_cThread, "run", rb_thread_run, 0);
- rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
- rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
- diff --git a/gc.c b/gc.c
- index a564f0b..d6d654d 100644
- --- a/gc.c
- +++ b/gc.c
- @@ -506,12 +506,12 @@ stack_end_address(VALUE **stack_end_p)
- # define STACK_END (stack_end)
- #endif
- #if STACK_GROW_DIRECTION < 0
- -# define STACK_LENGTH (rb_gc_stack_start - STACK_END)
- +# define STACK_LENGTH(start) ((start) - STACK_END)
- #elif STACK_GROW_DIRECTION > 0
- -# define STACK_LENGTH (STACK_END - rb_gc_stack_start + 1)
- +# define STACK_LENGTH(start) (STACK_END - (start) + 1)
- #else
- -# define STACK_LENGTH ((STACK_END < rb_gc_stack_start) ? rb_gc_stack_start - STACK_END\
- - : STACK_END - rb_gc_stack_start + 1)
- +# define STACK_LENGTH(start) ((STACK_END < (start)) ? (start) - STACK_END\
- + : STACK_END - (start) + 1)
- #endif
- #if STACK_GROW_DIRECTION > 0
- # define STACK_UPPER(x, a, b) a
- @@ -534,27 +534,36 @@ stack_grow_direction(addr)
-
- #define GC_WATER_MARK 512
-
- -#define CHECK_STACK(ret) do {\
- +#define CHECK_STACK(ret, start) do {\
- SET_STACK_END;\
- - (ret) = (STACK_LENGTH > STACK_LEVEL_MAX + GC_WATER_MARK);\
- + (ret) = (STACK_LENGTH(start) > STACK_LEVEL_MAX + GC_WATER_MARK);\
- } while (0)
-
- size_t
- ruby_stack_length(p)
- VALUE **p;
- {
- - SET_STACK_END;
- - if (p) *p = STACK_UPPER(STACK_END, rb_gc_stack_start, STACK_END);
- - return STACK_LENGTH;
- + SET_STACK_END;
- + VALUE *start;
- + if (rb_curr_thread == rb_main_thread) {
- + start = rb_gc_stack_start;
- + } else {
- + start = rb_curr_thread->stk_base;
- + }
- + if (p) *p = STACK_UPPER(STACK_END, start, STACK_END);
- + return STACK_LENGTH(start);
- }
-
- int
- ruby_stack_check()
- {
- - int ret;
- -
- - CHECK_STACK(ret);
- - return ret;
- + int ret;
- + if (rb_curr_thread == rb_main_thread) {
- + CHECK_STACK(ret, rb_gc_stack_start);
- + } else {
- + CHECK_STACK(ret, rb_curr_thread->stk_base);
- + }
- + return ret;
- }
-
- #define MARK_STACK_MAX 1024
- @@ -1441,10 +1450,13 @@ garbage_collect()
-
- init_mark_stack();
-
- - gc_mark((VALUE)ruby_current_node, 0);
- -
- /* mark frame stack */
- - for (frame = ruby_frame; frame; frame = frame->prev) {
- + if (rb_curr_thread == rb_main_thread)
- + frame = ruby_frame;
- + else
- + frame = rb_main_thread->frame;
- +
- + for (; frame; frame = frame->prev) {
- rb_gc_mark_frame(frame);
- if (frame->tmp) {
- struct FRAME *tmp = frame->tmp;
- @@ -1454,16 +1466,35 @@ garbage_collect()
- }
- }
- }
- - gc_mark((VALUE)ruby_scope, 0);
- - gc_mark((VALUE)ruby_dyna_vars, 0);
- +
- + if (rb_curr_thread == rb_main_thread) {
- + gc_mark((VALUE)ruby_current_node, 0);
- + gc_mark((VALUE)ruby_scope, 0);
- + gc_mark((VALUE)ruby_dyna_vars, 0);
- + } else {
- + gc_mark((VALUE)rb_main_thread->node, 0);
- + gc_mark((VALUE)rb_main_thread->scope, 0);
- + gc_mark((VALUE)rb_main_thread->dyna_vars, 0);
- +
- + /* scan the current thread's stack */
- + rb_gc_mark_locations((VALUE*)STACK_END, rb_curr_thread->stk_base);
- + }
- +
- if (finalizer_table) {
- - mark_tbl(finalizer_table, 0);
- + mark_tbl(finalizer_table, 0);
- }
-
- FLUSH_REGISTER_WINDOWS;
- /* This assumes that all registers are saved into the jmp_buf (and stack) */
- rb_setjmp(save_regs_gc_mark);
- mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
- +
- + /* If this is not the main thread, we need to scan the C stack, so
- + * set STACK_END to the end of the C stack.
- + */
- + if (rb_curr_thread != rb_main_thread)
- + STACK_END = rb_main_thread->stk_pos;
- +
- #if STACK_GROW_DIRECTION < 0
- rb_gc_mark_locations((VALUE*)STACK_END, rb_gc_stack_start);
- #elif STACK_GROW_DIRECTION > 0
- @@ -1483,6 +1514,7 @@ garbage_collect()
- rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
- (VALUE*)((char*)rb_gc_stack_start + 2));
- #endif
- +
- rb_gc_mark_threads();
-
- /* mark protected global variables */
- diff --git a/lib/logger.rb b/lib/logger.rb
- index 15d95fc..5a6d467 100644
- --- a/lib/logger.rb
- +++ b/lib/logger.rb
- @@ -170,7 +170,7 @@ require 'monitor'
-
- class Logger
- VERSION = "1.2.6"
- - id, name, rev = %w$Id$
- + id, name, rev = %w$Id logger.rb 1234$
- ProgName = "#{name.chomp(",v")}/#{rev}"
-
- class Error < RuntimeError; end
- diff --git a/node.h b/node.h
- index c209fa5..740e66a 100644
- --- a/node.h
- +++ b/node.h
- @@ -411,8 +411,11 @@ struct rb_thread {
-
- size_t stk_len;
- size_t stk_max;
- + size_t stk_size;
- VALUE *stk_ptr;
- VALUE *stk_pos;
- + VALUE *stk_base;
- + VALUE *guard;
- #ifdef __ia64
- size_t bstr_len;
- size_t bstr_max;
- diff --git a/signal.c b/signal.c
- index fb21fd3..acac6a7 100644
- --- a/signal.c
- +++ b/signal.c
- @@ -14,6 +14,7 @@
-
- #include "ruby.h"
- #include "rubysig.h"
- +#include "node.h"
- #include <signal.h>
- #include <stdio.h>
-
- @@ -428,15 +429,22 @@ typedef RETSIGTYPE (*sighandler_t)_((int));
- static sighandler_t
- ruby_signal(signum, handler)
- int signum;
- - sighandler_t handler;
- + void *handler;
- {
- struct sigaction sigact, old;
-
- rb_trap_accept_nativethreads[signum] = 0;
-
- - sigact.sa_handler = handler;
- + if (signum == SIGSEGV || signum == SIGBUS) {
- + sigact.sa_sigaction = handler;
- + sigact.sa_flags = (SA_ONSTACK | SA_RESETHAND | SA_SIGINFO);
- + } else {
- + sigact.sa_handler = handler;
- + sigact.sa_flags = 0;
- + }
- +
- sigemptyset(&sigact.sa_mask);
- - sigact.sa_flags = 0;
- +
- # ifdef SA_NOCLDWAIT
- if (signum == SIGCHLD && handler == SIG_IGN)
- sigact.sa_flags |= SA_NOCLDWAIT;
- @@ -599,7 +607,132 @@ sighandler(sig)
- }
- }
-
- +#include <stdio.h>
- +#ifdef HAVE_STDARG_PROTOTYPES
- +#include <stdarg.h>
- +#define va_init_list(a,b) va_start(a,b)
- +#else
- +#include <varargs.h>
- +#define va_init_list(a,b) va_start(a)
- +#endif
- +
- +void
- +#ifdef HAVE_STDARG_PROTOTYPES
- +sig_printf(const char *fmt, ...)
- +#else
- + sig_printf(fmt, va_alist)
- + const char *fmt;
- + va_dcl
- +#endif
- +{
- + char buf[BUFSIZ];
- + va_list args;
- + FILE *out = stderr;
- +
- + va_init_list(args, fmt);
- + vfprintf(out, fmt, args);
- + va_end(args);
- + fprintf(out, "\n");
- +}
- +
- +static void
- +dump_machine_state(uc)
- + ucontext_t *uc;
- +{
- + const char *dump64 =
- + " ----------------- Register state dump ----------------------\n"
- + "rax = 0x%.16x rbx = 0x%.16x rcx = 0x%.16x rdx = 0x%.16x\n"
- + "rdi = 0x%.16x rsi = 0x%.16x rbp = 0x%.16x rsp = 0x%.16x\n"
- + "r8 = 0x%.16x r9 = 0x%.16x r10 = 0x%.16x r11 = 0x%.16x\n"
- + "r12 = 0x%.16x r13 = 0x%.16x r14 = 0x%.16x r15 = 0x%.16x\n"
- + "rip = 0x%.16x rflags = 0x%.16x cs = 0x%.16x fs = 0x%.16x\n"
- + "gs = 0x%.16x";
- +
- + const char *dump32 =
- + " ----------------- Register state dump -------------------\n"
- + "eax = 0x%.8x ebx = 0x%.8x ecx = 0x%.8x edx = 0x%.8x\n"
- + "edi = 0x%.8x esi = 0x%.8x ebp = 0x%.8x esp = 0x%.8x\n"
- + "ss = 0x%.8x eflags = 0x%.8x eip = 0x%.8x cs = 0x%.8x\n"
- + "ds = 0x%.8x es = 0x%.8x fs = 0x%.8x gs = 0x%.8x\n";
- +
- +#if defined(__LP64__) && defined(__APPLE__)
- + sig_printf(dump64, uc->uc_mcontext->__ss.__rax, uc->uc_mcontext->__ss.__rbx,
- + uc->uc_mcontext->__ss.__rcx, uc->uc_mcontext->__ss.__rdx, uc->uc_mcontext->__ss.__rdi,
- + uc->uc_mcontext->__ss.__rsi, uc->uc_mcontext->__ss.__rbp, uc->uc_mcontext->__ss.__rsp,
- + uc->uc_mcontext->__ss.__r8, uc->uc_mcontext->__ss.__r9, uc->uc_mcontext->__ss.__r10,
- + uc->uc_mcontext->__ss.__r11, uc->uc_mcontext->__ss.__r12, uc->uc_mcontext->__ss.__r13,
- + uc->uc_mcontext->__ss.__r14, uc->uc_mcontext->__ss.__r15, uc->uc_mcontext->__ss.__rip,
- + uc->uc_mcontext->__ss.__rflags, uc->uc_mcontext->__ss.__cs, uc->uc_mcontext->__ss.__fs,
- + uc->uc_mcontext->__ss.__gs);
- +#elif !defined(__LP64__) && defined(__APPLE__)
- + sig_printf(dump32, uc->uc_mcontext->__ss.__eax, uc->uc_mcontext->__ss.__ebx,
- + uc->uc_mcontext->__ss.__ecx, uc->uc_mcontext->__ss.__edx,
- + uc->uc_mcontext->__ss.__edi, uc->uc_mcontext->__ss.__esi,
- + uc->uc_mcontext->__ss.__ebp, uc->uc_mcontext->__ss.__esp,
- + uc->uc_mcontext->__ss.__ss, uc->uc_mcontext->__ss.__eflags,
- + uc->uc_mcontext->__ss.__eip, uc->uc_mcontext->__ss.__cs,
- + uc->uc_mcontext->__ss.__ds, uc->uc_mcontext->__ss.__es,
- + uc->uc_mcontext->__ss.__fs, uc->uc_mcontext->__ss.__gs);
- +#elif defined(__i386__)
- + sig_printf(dump32, uc->uc_mcontext.gregs[REG_EAX], uc->uc_mcontext.gregs[REG_EBX],
- + uc->uc_mcontext.gregs[REG_ECX], uc->uc_mcontext.gregs[REG_EDX],
- + uc->uc_mcontext.gregs[REG_EDI], uc->uc_mcontext.gregs[REG_ESI],
- + uc->uc_mcontext.gregs[REG_EBP], uc->uc_mcontext.gregs[REG_ESP],
- + uc->uc_mcontext.gregs[REG_SS], uc->uc_mcontext.gregs[REG_EFL],
- + uc->uc_mcontext.gregs[REG_EIP], uc->uc_mcontext.gregs[REG_EIP],
- + uc->uc_mcontext.gregs[REG_DS], uc->uc_mcontext.gregs[REG_ES],
- + uc->uc_mcontext.gregs[REG_FS], uc->uc_mcontext.gregs[REG_FS]);
- +#elif defined(__x86_64__)
- + sig_printf(dump64, uc->uc_mcontext.gregs[REG_RAX], uc->uc_mcontext.gregs[REG_RBX],
- + uc->uc_mcontext.gregs[REG_RCX], uc->uc_mcontext.gregs[REG_RDX],
- + uc->uc_mcontext.gregs[REG_RDI], uc->uc_mcontext.gregs[REG_RSI],
- + uc->uc_mcontext.gregs[REG_RBP], uc->uc_mcontext.gregs[REG_RSP],
- + uc->uc_mcontext.gregs[REG_R8], uc->uc_mcontext.gregs[REG_R9],
- + uc->uc_mcontext.gregs[REG_R10], uc->uc_mcontext.gregs[REG_R11],
- + uc->uc_mcontext.gregs[REG_R12], uc->uc_mcontext.gregs[REG_R13],
- + uc->uc_mcontext.gregs[REG_R14], uc->uc_mcontext.gregs[REG_R15],
- + uc->uc_mcontext.gregs[REG_RIP], uc->uc_mcontext.gregs[REG_EFL],
- + uc->uc_mcontext.gregs[REG_CSGSFS]);
- +#else
- +#endif
- +}
- +
- +static int
- +check_guard(caddr_t fault_addr, rb_thread_t th) {
- + if(fault_addr <= (caddr_t)rb_curr_thread->guard &&
- + fault_addr >= (caddr_t)rb_curr_thread->stk_ptr) {
- + return 1;
- + }
- + return 0;
- +}
- +
- #ifdef SIGBUS
- +#ifdef POSIX_SIGNAL
- +static void sigbus _((int, siginfo_t*, void*));
- +static void
- +sigbus(sig, ip, context)
- + int sig;
- + siginfo_t *ip;
- + void *context;
- +{
- +#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
- + if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
- + sigsend_to_ruby_thread(sig);
- + return;
- + }
- +#endif
- +
- + dump_machine_state(context);
- + if (check_guard((caddr_t)ip->si_addr, rb_curr_thread)) {
- + /* we hit the guard page, print out a warning to help app developers */
- + rb_bug("Thread stack overflow! Try increasing it!");
- + } else {
- + rb_bug("Bus Error");
- + }
- +}
- +
- +#else /* !defined(POSIX_SIGNAL) */
- +
- static RETSIGTYPE sigbus _((int));
- static RETSIGTYPE
- sigbus(sig)
- @@ -615,8 +748,38 @@ sigbus(sig)
- rb_bug("Bus Error");
- }
- #endif
- +#endif
- +
-
- #ifdef SIGSEGV
- +#ifdef POSIX_SIGNAL
- +static void sigsegv _((int, siginfo_t*, void*));
- +static void
- +sigsegv(sig, ip, context)
- + int sig;
- + siginfo_t *ip;
- + void *context;
- +{
- +#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
- + if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig]) {
- + sigsend_to_ruby_thread(sig);
- + return;
- + }
- +#endif
- +
- + extern int ruby_gc_stress;
- + ruby_gc_stress = 0;
- + dump_machine_state(context);
- + if (check_guard((caddr_t)ip->si_addr, rb_curr_thread)) {
- + /* we hit the guard page, print out a warning to help app developers */
- + rb_bug("Thread stack overflow! Try increasing it!");
- + } else {
- + rb_bug("Segmentation fault");
- + }
- +}
- +
- +#else /* !defined(POSIX_SIGNAL) */
- +
- static RETSIGTYPE sigsegv _((int));
- static RETSIGTYPE
- sigsegv(sig)
- @@ -634,6 +797,7 @@ sigsegv(sig)
- rb_bug("Segmentation fault");
- }
- #endif
- +#endif
-
- #ifdef SIGPIPE
- static RETSIGTYPE sigpipe _((int));
- @@ -705,7 +869,8 @@ static VALUE
- trap(arg)
- struct trap_arg *arg;
- {
- - sighandler_t func, oldfunc;
- + sighandler_t oldfunc;
- + void *func;
- VALUE command, oldcmd;
- int sig = -1;
- const char *s;
- @@ -952,6 +1117,20 @@ sig_list()
- }
-
- static void
- +create_sigstack()
- +{
- + stack_t ss;
- + ss.ss_size = SIGSTKSZ;
- + ss.ss_sp = malloc(ss.ss_size);
- + ss.ss_flags = 0;
- + if (sigaltstack(&ss, NULL) < 0) {
- + free(ss.ss_sp);
- + fprintf(stderr, "Couldn't create signal stack! Error %d: %s\n", errno, strerror(errno));
- + exit(1);
- + }
- +}
- +
- +static void
- install_sighandler(signum, handler)
- int signum;
- sighandler_t handler;
- @@ -960,7 +1139,7 @@ install_sighandler(signum, handler)
-
- old = ruby_signal(signum, handler);
- if (old != SIG_DFL) {
- - ruby_signal(signum, old);
- + ruby_signal(signum, old);
- }
- }
-
- @@ -1089,6 +1268,8 @@ Init_signal()
- rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
- rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
-
- + create_sigstack();
- +
- install_sighandler(SIGINT, sighandler);
- #ifdef SIGHUP
- install_sighandler(SIGHUP, sighandler);
|