* [gentoo-commits] proj/ruby-scripts:master commit in: patchsets/patches-ee-1.8.7.2011.03/
@ 2011-05-15 17:52 Hans de Graaff
0 siblings, 0 replies; only message in thread
From: Hans de Graaff @ 2011-05-15 17:52 UTC (permalink / raw
To: gentoo-commits
commit: 6a1d864f6652a0cf7566b8538fa40129299c7be5
Author: Hans de Graaff <hans <AT> degraaff <DOT> org>
AuthorDate: Sun May 15 17:52:01 2011 +0000
Commit: Hans de Graaff <graaff <AT> gentoo <DOT> org>
CommitDate: Sun May 15 17:52:01 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/ruby-scripts.git;a=commit;h=6a1d864f
Update patches for ree18 1.8.7 2011.03.
Drop patches applied upstream.
Update fastthreading patch from the source distribution.
---
.../patches-ee-1.8.7.2011.03/001_memory_leak.patch | 59 +
.../patches-ee-1.8.7.2011.03/002_mkconfig.patch | 16 +
.../003_mkmf-parallel-install.patch | 16 +
.../004_configure-libdir.patch | 13 +
.../005_mkconfig-libdir.patch | 15 +
.../007_no-undefined-ext.patch | 13 +
.../patches-ee-1.8.7.2011.03/008_berkdb-5.0.patch | 13 +
.../999-fast-threading-NOAPPLY.diff | 1440 ++++++++++++++++++++
patchsets/patches-ee-1.8.7.2011.03/series | 7 +
9 files changed, 1592 insertions(+), 0 deletions(-)
diff --git a/patchsets/patches-ee-1.8.7.2011.03/001_memory_leak.patch b/patchsets/patches-ee-1.8.7.2011.03/001_memory_leak.patch
new file mode 100644
index 0000000..25853be
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/001_memory_leak.patch
@@ -0,0 +1,59 @@
+Index: source/ext/dl/handle.c
+===================================================================
+--- source.orig/ext/dl/handle.c
++++ source/ext/dl/handle.c
+@@ -10,9 +10,12 @@ VALUE rb_cDLHandle;
+ void
+ dlhandle_free(struct dl_handle *dlhandle)
+ {
++ if (!dlhandle)
++ return;
+ if (dlhandle->ptr && dlhandle->open && dlhandle->enable_close) {
+ dlclose(dlhandle->ptr);
+ }
++ dlfree(dlhandle);
+ }
+
+ VALUE
+Index: source/ext/dl/ptr.c
+===================================================================
+--- source.orig/ext/dl/ptr.c
++++ source/ext/dl/ptr.c
+@@ -45,6 +45,8 @@ rb_dlmem_aref(void *ptr)
+ void
+ dlptr_free(struct ptr_data *data)
+ {
++ if (!data)
++ return;
+ if (data->ptr) {
+ DEBUG_CODE({
+ printf("dlptr_free(): removing the pointer `0x%x' from the MemorySpace\n",
+@@ -61,6 +63,7 @@ dlptr_free(struct ptr_data *data)
+ if (data->stype) dlfree(data->stype);
+ if (data->ssize) dlfree(data->ssize);
+ if (data->ids) dlfree(data->ids);
++ dlfree(data);
+ }
+
+ void
+Index: source/ext/dl/sym.c
+===================================================================
+--- source.orig/ext/dl/sym.c
++++ source/ext/dl/sym.c
+@@ -57,6 +57,8 @@ char2type(int ch)
+ void
+ dlsym_free(struct sym_data *data)
+ {
++ if(!data)
++ return;
+ if( data->name ){
+ DEBUG_CODE({
+ printf("dlsym_free(): free(data->name:%s)\n",data->name);
+@@ -69,6 +71,7 @@ dlsym_free(struct sym_data *data)
+ });
+ free(data->type);
+ }
++ dlfree(data);
+ }
+
+ VALUE
diff --git a/patchsets/patches-ee-1.8.7.2011.03/002_mkconfig.patch b/patchsets/patches-ee-1.8.7.2011.03/002_mkconfig.patch
new file mode 100644
index 0000000..6574925
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/002_mkconfig.patch
@@ -0,0 +1,16 @@
+Fix for mkconfig to be able to handle empty continued lines.
+Patch from [ruby-core:20420] via bug 234877.
+
+Index: source/mkconfig.rb
+===================================================================
+--- source.orig/mkconfig.rb
++++ source/mkconfig.rb
+@@ -55,7 +55,7 @@ File.foreach "config.status" do |line|
+ continued_name = name
+ next
+ end
+- when /^"(.+)"\s*(\\)?$/
++ when /^"(.*)"\s*(\\)?$/
+ if continued_line
+ continued_line << $1
+ unless $2
diff --git a/patchsets/patches-ee-1.8.7.2011.03/003_mkmf-parallel-install.patch b/patchsets/patches-ee-1.8.7.2011.03/003_mkmf-parallel-install.patch
new file mode 100644
index 0000000..41bf2bc
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/003_mkmf-parallel-install.patch
@@ -0,0 +1,16 @@
+ Patch for bug 239101 by Matsuu Takuto, via Redmine issue 1337 (yes, really).
+ Backported for 1.8.* by Alex Legler.
+
+Index: source/lib/mkmf.rb
+===================================================================
+--- source.orig/lib/mkmf.rb
++++ source/lib/mkmf.rb
+@@ -1523,7 +1523,7 @@ static: $(STATIC_LIB)#{$extout ? " inst
+ dest = "#{dir}/#{f}"
+ mfile.puts dir, "install-so: #{dest}"
+ unless $extout
+- mfile.print "#{dest}: #{f}\n"
++ mfile.print "#{dest}: #{dir} #{f}\n"
+ if (sep = config_string('BUILD_FILE_SEPARATOR'))
+ f.gsub!("/", sep)
+ dir.gsub!("/", sep)
diff --git a/patchsets/patches-ee-1.8.7.2011.03/004_configure-libdir.patch b/patchsets/patches-ee-1.8.7.2011.03/004_configure-libdir.patch
new file mode 100644
index 0000000..b7f17fa
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/004_configure-libdir.patch
@@ -0,0 +1,13 @@
+Index: source/configure.in
+===================================================================
+--- source.orig/configure.in
++++ source/configure.in
+@@ -1730,7 +1730,7 @@ case "$target_os" in
+ rubyw_install_name="$RUBYW_INSTALL_NAME"
+ ;;
+ esac
+-RUBY_LIB_PREFIX=`eval echo \\"${libdir}/ruby\\"`
++RUBY_LIB_PREFIX=`eval echo \\"${libdir}/rubyee\\"`
+
+ AC_ARG_WITH(sitedir,
+ [ --with-sitedir=DIR site libraries in DIR [[LIBDIR/ruby/site_ruby]]],
diff --git a/patchsets/patches-ee-1.8.7.2011.03/005_mkconfig-libdir.patch b/patchsets/patches-ee-1.8.7.2011.03/005_mkconfig-libdir.patch
new file mode 100644
index 0000000..932a4e3
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/005_mkconfig-libdir.patch
@@ -0,0 +1,15 @@
+Evil hack fiddling with the ruby libdir
+
+Index: source/mkconfig.rb
+===================================================================
+--- source.orig/mkconfig.rb
++++ source/mkconfig.rb
+@@ -141,7 +141,7 @@ print(*v_fast)
+ print(*v_others)
+ print <<EOS
+ CONFIG["ruby_version"] = "$(MAJOR).$(MINOR)"
+- CONFIG["rubylibdir"] = "$(libdir)/ruby/$(ruby_version)"
++ CONFIG["rubylibdir"] = "$(libdir)/rubyee/$(ruby_version)"
+ CONFIG["archdir"] = "$(rubylibdir)/$(arch)"
+ CONFIG["sitelibdir"] = "$(sitedir)/$(ruby_version)"
+ CONFIG["sitearchdir"] = "$(sitelibdir)/$(sitearch)"
diff --git a/patchsets/patches-ee-1.8.7.2011.03/007_no-undefined-ext.patch b/patchsets/patches-ee-1.8.7.2011.03/007_no-undefined-ext.patch
new file mode 100644
index 0000000..a122561
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/007_no-undefined-ext.patch
@@ -0,0 +1,13 @@
+Index: source/configure.in
+===================================================================
+--- source.orig/configure.in
++++ source/configure.in
+@@ -1201,7 +1201,7 @@ if test "$with_dln_a_out" != yes; then
+ linux* | gnu* | k*bsd*-gnu | netbsd* | bsdi*)
+ : ${LDSHARED='${CC} -shared'}
+ if test "$rb_cv_binary_elf" = yes; then
+- LDFLAGS="$LDFLAGS -Wl,-export-dynamic"
++ LDFLAGS="$LDFLAGS -Wl,-export-dynamic -Wl,--no-undefined"
+ fi
+ rb_cv_dlopen=yes ;;
+ interix*) : ${LDSHARED="$CC -shared"}
diff --git a/patchsets/patches-ee-1.8.7.2011.03/008_berkdb-5.0.patch b/patchsets/patches-ee-1.8.7.2011.03/008_berkdb-5.0.patch
new file mode 100644
index 0000000..096a1bf
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/008_berkdb-5.0.patch
@@ -0,0 +1,13 @@
+Index: ruby-1.8.7-p249/ext/dbm/extconf.rb
+===================================================================
+--- ruby-1.8.7-p249.orig/ext/dbm/extconf.rb
++++ ruby-1.8.7-p249/ext/dbm/extconf.rb
+@@ -26,7 +26,7 @@ def headers.db_check(db)
+ case db
+ when /^db2?$/
+ db_prefix = "__db_n"
+- hsearch = "-DDB_DBM_HSEARCH "
++ hsearch = "-DDB_DBM_HSEARCH -DHAVE_DBM "
+ when "gdbm"
+ have_gdbm = true
+ when "gdbm_compat"
diff --git a/patchsets/patches-ee-1.8.7.2011.03/999-fast-threading-NOAPPLY.diff b/patchsets/patches-ee-1.8.7.2011.03/999-fast-threading-NOAPPLY.diff
new file mode 100644
index 0000000..06fd0f7
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/999-fast-threading-NOAPPLY.diff
@@ -0,0 +1,1440 @@
+diff --git a/eval.c b/eval.c
+index 8054d2b..b7650b6 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>
+
+ #if defined(HAVE_FCNTL_H) || defined(_WIN32)
+ #include <fcntl.h>
+@@ -1058,7 +1059,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 */
+@@ -1140,6 +1141,20 @@ rb_thread_t rb_main_thread;
+ #define main_thread rb_main_thread
+ #define curr_thread rb_curr_thread
+
++
++#ifndef STACK_FREE_SAFE_DEBUG
++#define STACK_FREE_SAFE_DEBUG 0
++#endif
++
++#if STACK_FREE_SAFE_DEBUG
++#define stack_free_safe(TH,MSG) _stack_free_safe(TH,MSG)
++#else
++#define stack_free_safe(TH,MSG) _stack_free_safe(TH)
++#endif
++
++
++static void stack_free_safe_all_dead_threads();
++
+ static void scope_dup _((struct SCOPE *));
+
+ #define POP_SCOPE() \
+@@ -1280,7 +1295,7 @@ error_print()
+
+ if (NIL_P(ruby_errinfo)) return;
+
+- PUSH_TAG(PROT_NONE);
++ PUSH_TAG(PROT_EMPTY);
+ errat = EXEC_TAG() ? Qnil : get_backtrace(ruby_errinfo);
+ if (EXEC_TAG()) goto error;
+ if (NIL_P(errat)){
+@@ -1436,7 +1451,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;
+@@ -1570,7 +1585,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);
+ }
+@@ -1587,7 +1602,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();
+ }
+@@ -1626,7 +1641,7 @@ ruby_cleanup(exArg)
+ 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();
+@@ -1677,7 +1692,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);
+@@ -1899,7 +1914,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);
+@@ -1921,7 +1936,7 @@ rb_eval_cmd(cmd, arg, level)
+
+ ruby_safe_level = level;
+
+- PUSH_TAG(PROT_NONE);
++ PUSH_TAG(PROT_EMPTY);
+ val = (state = EXEC_TAG()) ? Qnil : eval(ruby_top_self, cmd, Qnil, 0, 0);
+ if (ruby_scope->flags & SCOPE_DONT_RECYCLE)
+ scope_dup(saved_scope);
+@@ -2433,7 +2448,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);
+ }
+@@ -2535,7 +2550,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);
+ }
+@@ -2584,7 +2599,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);
+ }
+@@ -2789,7 +2804,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)");
+@@ -3231,7 +3246,7 @@ eval_node_volatile(rescue, VALUE)
+ int state;
+ VALUE result;
+
+- PUSH_TAG(PROT_NONE);
++ PUSH_TAG(PROT_EMPTY);
+ if ((state = EXEC_TAG()) == 0) {
+ retry_entry:
+ result = rb_eval(self, node->nd_head);
+@@ -3286,7 +3301,7 @@ eval_node_volatile(ensure, VALUE)
+ int state;
+ VALUE result;
+
+- PUSH_TAG(PROT_NONE);
++ PUSH_TAG(PROT_EMPTY);
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_eval(self, node->nd_head);
+ }
+@@ -3453,7 +3468,7 @@ eval_node_volatile(scope, VALUE)
+ 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;
+@@ -4351,7 +4366,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);
+@@ -4758,7 +4773,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",
+@@ -5136,7 +5151,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:
+@@ -5209,7 +5224,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);
+ switch (state = EXEC_TAG()) {
+ case TAG_REDO:
+ state = 0;
+@@ -5614,7 +5629,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;
+@@ -5672,7 +5687,7 @@ rb_protect(proc, data, state)
+ VALUE result;
+ 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);
+@@ -5696,7 +5711,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
+ VALUE result;
+ VALUE retval;
+
+- PUSH_TAG(PROT_NONE);
++ PUSH_TAG(PROT_EMPTY);
+ if ((state = EXEC_TAG()) == 0) {
+ result = (*b_proc)(data1);
+ }
+@@ -5723,7 +5738,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);
+ }
+@@ -6419,7 +6434,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);
+ }
+@@ -6695,7 +6710,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;
+
+@@ -6863,7 +6878,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);
+ }
+@@ -7175,7 +7190,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;
+@@ -7234,7 +7249,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);
+ }
+@@ -7559,7 +7574,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;
+@@ -8268,7 +8283,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);
+@@ -8286,7 +8301,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);
+@@ -9024,7 +9039,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);
+@@ -10469,6 +10484,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;
+
+@@ -10684,33 +10700,33 @@ timeofday()
+ return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
+ }
+
+-extern VALUE *rb_gc_stack_start;
+-#ifdef __ia64
+-extern VALUE *rb_gc_register_stack_start;
+-#endif
+-
+-#define ADJ(addr) \
+- if ((size_t)((void *)addr - stkBase) < stkSize) addr=(void *)addr + stkShift
++#define STACK(addr) (th->stk_pos<(VALUE*)(addr) && (VALUE*)(addr)<th->stk_pos+th->stk_len)
++#define ADJ(addr) (void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr))
+ static void
+ thread_mark(th)
+ rb_thread_t th;
+ {
+ struct FRAME *frame;
+ struct BLOCK *block;
+- void *stkBase;
+- ptrdiff_t stkShift;
+- size_t stkSize;
+-
++
+ rb_gc_mark(th->result);
+ 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);
+@@ -10720,11 +10736,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
+@@ -10734,35 +10750,30 @@ thread_mark(th)
+ }
+ #endif
+ }
+-
+- stkBase = (void *)rb_gc_stack_start;
+- stkSize = th->stk_len * sizeof(VALUE);
+-#if STACK_GROW_DIRECTION == 0
+- if ((VALUE *)&th < rb_gc_stack_start)
+-#endif
+-#if STACK_GROW_DIRECTION <= 0
+- stkBase -= stkSize;
+-#endif
+- stkShift = (void *)th->stk_ptr - stkBase;
+-
+- frame = th->frame;
++
++ if (curr_thread == th)
++ frame = ruby_frame;
++ else
++ frame = th->frame;
++
+ while (frame && frame != top_frame) {
+- ADJ(frame);
+ rb_gc_mark_frame(frame);
+ if (frame->tmp) {
+ struct FRAME *tmp = frame->tmp;
+-
+ while (tmp && tmp != top_frame) {
+- 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) {
+- ADJ(block);
+ rb_gc_mark_frame(&block->frame);
+ block = block->prev;
+ }
+@@ -10826,7 +10837,7 @@ stack_free(th)
+ rb_thread_t th;
+ {
+ if (th->stk_ptr) {
+- free(th->stk_ptr);
++ munmap(th->stk_ptr, th->stk_size);
+ th->stk_ptr = 0;
+ }
+ #ifdef __ia64
+@@ -10878,6 +10889,11 @@ static int th_sig, th_safe;
+ #define RESTORE_SIGNAL 6
+ #define RESTORE_EXIT 7
+
++extern VALUE *rb_gc_stack_start;
++#ifdef __ia64
++extern VALUE *rb_gc_register_stack_start;
++#endif
++
+ static void
+ rb_thread_save_context(th)
+ rb_thread_t th;
+@@ -10887,35 +10903,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;
+@@ -11002,6 +10991,9 @@ rb_thread_restore_context_0(rb_thread_t th, int exit)
+ static int ex;
+ static VALUE tval;
+
++ /* Free any dead thread's stk_ptr. */
++ stack_free_safe_all_dead_threads();
++
+ rb_trap_immediate = 0; /* inhibit interrupts from here */
+ if (ruby_sandbox_restore != NULL) {
+ ruby_sandbox_restore(th);
+@@ -11028,11 +11020,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);
+@@ -11124,8 +11111,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
+@@ -11138,13 +11125,57 @@ rb_thread_ready(th)
+ }
+ }
+
++static
++rb_thread_t dead_thread_needs_stack_free = 0;
++
++static
++int dead_threads_need_stack_free = 0;
++
++static int
++_stack_free_safe (th
++#if STACK_FREE_SAFE_DEBUG
++ , msg
++#endif
++ )
++ rb_thread_t th;
++#if STACK_FREE_SAFE_DEBUG
++ const char *msg;
++#endif
++{
++ if ( th->status == THREAD_KILLED && th->stk_ptr ) {
++ void *sp = (void*) &th;
++#if STACK_FREE_SAFE_DEBUG
++ fprintf(stderr, "\n%s: stack_free_safe(%p): sp (%p): stk [%p, %p): ",
++ msg, th, sp, th->stk_ptr, th->stk_ptr + th->stk_size);
++#endif
++ if ( (void*) th->stk_ptr <= sp && sp < (void*) (th->stk_ptr + th->stk_size) ) {
++#if STACK_FREE_SAFE_DEBUG
++ fprintf(stderr, " cannot call stack_free(), yet. \n");
++ fflush(stderr);
++#endif
++ dead_thread_needs_stack_free = th;
++ ++ dead_threads_need_stack_free;
++ } else {
++#if STACK_FREE_SAFE_DEBUG
++ fprintf(stderr, " calling stack_free(). \n");
++ fflush(stderr);
++#endif
++ if ( dead_thread_needs_stack_free == th )
++ dead_thread_needs_stack_free = 0;
++ stack_free(th);
++ return 1; /* stack freed. */
++ }
++ }
++ return 0; /* stack not freed */
++}
++
+ static void
+ rb_thread_die(th)
+ rb_thread_t th;
+ {
+ th->thgroup = 0;
+ th->status = THREAD_KILLED;
+- stack_free(th);
++ stack_free_safe(th, "rb_thread_die");
+ }
+
+ static void
+@@ -12473,8 +12504,10 @@ rb_thread_group(thread)
+ \
+ th->stk_ptr = 0;\
+ th->stk_len = 0;\
++ th->stk_size = 0;\
+ th->stk_max = 0;\
+ th->wait_for = 0;\
++ th->gc_stack_end = (VALUE *) STACK_GROW_DIRECTION;\
+ IA64_INIT(th->bstr_ptr = 0);\
+ IA64_INIT(th->bstr_len = 0);\
+ IA64_INIT(th->bstr_max = 0);\
+@@ -12520,6 +12553,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);
+@@ -12692,6 +12767,15 @@ 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();
++
+ #if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE)
+ #define START_TIMER() (thread_init ? (void)0 : rb_thread_start_timer())
+ #define STOP_TIMER() (rb_thread_stop_timer())
+@@ -12706,11 +12790,7 @@ rb_thread_start_0(fn, arg, th)
+ 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,
+@@ -12721,16 +12801,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, *new_tag, *prev_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;
+@@ -12738,14 +12843,42 @@ 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;
+ }
+ START_TIMER();
+
++ scope_dup(ruby_scope);
++ prev_tag = NULL;
++ tag = prot_tag;
++ while (tag) {
++ new_tag = alloca(sizeof(struct tag));
++ memcpy(new_tag, tag, sizeof(struct tag));
++
++ if (prev_tag)
++ prev_tag->prev = new_tag;
++ else
++ prot_tag = new_tag;
++
++ prev_tag = new_tag;
++ tag = tag->prev;
++ }
++
+ 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;
+ }
+@@ -13059,6 +13192,40 @@ rb_thread_wait_other_threads()
+ }
+
+ static void
++stack_free_safe_all_dead_threads()
++{
++ if ( dead_threads_need_stack_free ) {
++ rb_thread_t curr, th;
++ int left = dead_threads_need_stack_free;
++
++#if STACK_FREE_SAFE_DEBUG
++ fprintf(stderr, "\nstack_free_safe_all_dead_threads(): %d\n", dead_threads_need_stack_free);
++ fflush(stderr);
++#endif
++
++ /* stack_free_safe() will increment this flag if stack_free_safe(th) cannot call stack_free(). */
++ dead_threads_need_stack_free = 0;
++
++ /*
++ ** Check the last known dead thread that needs stack_free().
++ ** That thread might have been rb_thread_remove()'ed from the thread ring.
++ ** Otherwise, start after current thread's stk_ptr, it should not be freeable anyway.
++ */
++ if ( th = dead_thread_needs_stack_free ) {
++ if ( stack_free_safe(th, "stack_free_safe_all_dead_threads") )
++ if ( -- left <= 0 ) return;
++ }
++
++ curr = curr_thread;
++ FOREACH_THREAD_FROM(curr, th) {
++ if ( stack_free_safe(th, "stack_free_safe_all_dead_threads") )
++ if ( -- left <= 0 ) return;
++ }
++ END_FOREACH_FROM(curr, th);
++ }
++}
++
++static void
+ rb_thread_cleanup()
+ {
+ rb_thread_t curr, th;
+@@ -13082,6 +13249,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;
+
+
+@@ -13932,7 +14136,7 @@ rb_exec_recursive(func, obj, arg)
+ int state;
+
+ hash = recursive_push(hash, objid);
+- PUSH_TAG(PROT_NONE);
++ PUSH_TAG(PROT_EMPTY);
+ result = (state = EXEC_TAG()) ? Qundef : (*func) (obj, arg, Qfalse);
+ POP_TAG();
+ recursive_pop(hash, objid);
+@@ -13957,6 +14161,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);
+@@ -13981,6 +14187,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);
+@@ -14019,7 +14228,7 @@ Init_Thread()
+ #ifdef MBARI_API
+ rb_define_method(rb_cCont, "thread", rb_cont_thread, 0);
+ #endif
+- rb_define_global_function("callcc", rb_callcc, 0);
++ /* rb_define_global_function("callcc", rb_callcc, 0); */
+ rb_global_variable(&cont_protect);
+
+ cThGroup = rb_define_class("ThreadGroup", rb_cObject);
+diff --git a/gc.c b/gc.c
+index 80f2c16..4a83543 100644
+--- a/gc.c
++++ b/gc.c
+@@ -68,7 +68,19 @@ int _setjmp(), _longjmp();
+ #endif
+ #define GC_STACK_MAX (GC_LEVEL_MAX+GC_STACK_PAD)
+
+-static VALUE *stack_limit, *gc_stack_limit;
++/* The address of the end of the main thread's application stack. When the
++ * main thread is active, application code may not cause the stack to grow
++ * past this point. Past this point there's still a small area reserved for
++ * garbage collector operations.
++ */
++static VALUE *stack_limit;
++/*
++ * The address of the end of the current thread's GC stack. When running
++ * the GC, the stack may not grow past this point.
++ * The value of this variable is reset every time garbage_collect() is
++ * called.
++ */
++static VALUE *gc_stack_limit;
+
+ static size_t malloc_increase = 0;
+ static size_t malloc_limit = GC_MALLOC_LIMIT;
+@@ -715,8 +727,6 @@ VALUE *rb_gc_stack_start = 0;
+ VALUE *rb_gc_register_stack_start = 0;
+ #endif
+
+-VALUE *rb_gc_stack_end = (VALUE *)STACK_GROW_DIRECTION;
+-
+
+ #ifdef DJGPP
+ /* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
+@@ -750,12 +760,12 @@ VALUE *__sp(void) {
+ #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(a, b) a
+@@ -778,15 +788,31 @@ ruby_stack_length(base)
+ VALUE **base;
+ {
+ 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 (base) *base = STACK_UPPER(start, STACK_END);
+- return STACK_LENGTH;
++ return STACK_LENGTH(start);
+ }
+
+ int
+ ruby_stack_check()
+ {
+ SET_STACK_END;
+- return __stack_past(stack_limit, STACK_END);
++ if (!rb_main_thread || rb_curr_thread == rb_main_thread) {
++ return __stack_past(stack_limit, STACK_END);
++ } else {
++ /* ruby_stack_check() is only called periodically, but we want to
++ * detect a stack overflow before the thread's guard area is accessed.
++ * So we append a '+ getpagesize()' to the address check.
++ *
++ * TODO: support architectures on which the stack grows upwards.
++ */
++ return __stack_past(rb_curr_thread->guard + getpagesize(), STACK_END);
++ }
+ }
+
+ /*
+@@ -797,22 +823,24 @@ ruby_stack_check()
+ #if STACK_WIPE_METHOD
+ void rb_gc_wipe_stack(void)
+ {
+- VALUE *stack_end = rb_gc_stack_end;
+- VALUE *sp = __sp();
+- rb_gc_stack_end = sp;
++ if (rb_curr_thread) {
++ VALUE *stack_end = rb_curr_thread->gc_stack_end;
++ VALUE *sp = __sp();
++ rb_curr_thread->gc_stack_end = sp;
+ #if STACK_WIPE_METHOD == 1
+ #warning clearing of "ghost references" from the call stack has been disabled
+ #elif STACK_WIPE_METHOD == 2 /* alloca ghost stack before clearing it */
+- if (__stack_past(sp, stack_end)) {
+- size_t bytes = __stack_depth((char *)stack_end, (char *)sp);
+- STACK_UPPER(sp = nativeAllocA(bytes), stack_end = nativeAllocA(bytes));
+- __stack_zero(stack_end, sp);
+- }
++ if (__stack_past(sp, stack_end)) {
++ size_t bytes = __stack_depth((char *)stack_end, (char *)sp);
++ STACK_UPPER(sp = nativeAllocA(bytes), stack_end = nativeAllocA(bytes));
++ __stack_zero(stack_end, sp);
++ }
+ #elif STACK_WIPE_METHOD == 3 /* clear unallocated area past stack pointer */
+- __stack_zero(stack_end, sp); /* will crash if compiler pushes a temp. here */
++ __stack_zero(stack_end, sp); /* will crash if compiler pushes a temp. here */
+ #else
+ #error unsupported method of clearing ghost references from the stack
+ #endif
++ }
+ }
+ #else
+ #warning clearing of "ghost references" from the call stack completely disabled
+@@ -1683,10 +1711,12 @@ garbage_collect_0(VALUE *top_frame)
+ rb_mark_table_prepare();
+ init_mark_stack();
+
+- gc_mark((VALUE)ruby_current_node);
+-
+ /* 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;
+@@ -1696,12 +1726,30 @@ garbage_collect_0(VALUE *top_frame)
+ }
+ }
+ }
+- gc_mark((VALUE)ruby_scope);
+- gc_mark((VALUE)ruby_dyna_vars);
++
++ if (rb_curr_thread == rb_main_thread) {
++ gc_mark((VALUE)ruby_current_node);
++ gc_mark((VALUE)ruby_scope);
++ gc_mark((VALUE)ruby_dyna_vars);
++ } else {
++ gc_mark((VALUE)rb_main_thread->node);
++ gc_mark((VALUE)rb_main_thread->scope);
++ gc_mark((VALUE)rb_main_thread->dyna_vars);
++
++ /* scan the current thread's stack */
++ rb_gc_mark_locations(top_frame, rb_curr_thread->stk_base);
++ }
++
+ if (finalizer_table) {
+ mark_tbl(finalizer_table);
+ }
+
++ /* If this is not the main thread, we need to scan the C stack, so
++ * set top_frame to the end of the C stack.
++ */
++ if (rb_curr_thread != rb_main_thread)
++ top_frame = rb_main_thread->stk_pos;
++
+ #if STACK_GROW_DIRECTION < 0
+ rb_gc_mark_locations(top_frame, rb_gc_stack_start);
+ #elif STACK_GROW_DIRECTION > 0
+@@ -1721,6 +1769,7 @@ garbage_collect_0(VALUE *top_frame)
+ 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 */
+@@ -1767,17 +1816,17 @@ garbage_collect()
+
+ #if STACK_WIPE_SITES & 0x400
+ # ifdef nativeAllocA
+- if (__stack_past (top, stack_limit)) {
+- /* allocate a large frame to ensure app stack cannot grow into GC stack */
++ if ((!rb_main_thread || rb_curr_thread == rb_main_thread) && __stack_past (top, stack_limit)) {
++ /* allocate a large frame to ensure app stack cannot grow into GC stack */
+ (volatile void*) nativeAllocA(__stack_depth((void*)stack_limit,(void*)top));
+- }
++ }
+ garbage_collect_0(top);
+ # else /* no native alloca() available */
+ garbage_collect_0(top);
+- {
++ if (rb_curr_thread) {
+ VALUE *paddedLimit = __stack_grow(gc_stack_limit, GC_STACK_PAD);
+- if (__stack_past(rb_gc_stack_end, paddedLimit))
+- rb_gc_stack_end = paddedLimit;
++ if (__stack_past(rb_curr_thread->gc_stack_end, paddedLimit))
++ rb_curr_thread->gc_stack_end = paddedLimit;
+ }
+ rb_gc_wipe_stack(); /* wipe the whole stack area reserved for this gc */
+ # endif
+@@ -2630,9 +2679,6 @@ Init_GC()
+ {
+ VALUE rb_mObSpace;
+
+-#if !STACK_GROW_DIRECTION
+- rb_gc_stack_end = stack_grow_direction(&rb_mObSpace);
+-#endif
+ rb_mGC = rb_define_module("GC");
+ rb_define_singleton_method(rb_mGC, "start", rb_gc_start, 0);
+ rb_define_singleton_method(rb_mGC, "enable", rb_gc_enable, 0);
+diff --git a/node.h b/node.h
+index c209fa5..1242be5 100644
+--- a/node.h
++++ b/node.h
+@@ -411,8 +411,12 @@ 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;
++ VALUE *gc_stack_end;
+ #ifdef __ia64
+ size_t bstr_len;
+ size_t bstr_max;
+diff --git a/rubysig.h b/rubysig.h
+index fae0869..4a4dadc 100644
+--- a/rubysig.h
++++ b/rubysig.h
+@@ -152,7 +152,6 @@ void rb_trap_restore_mask _((void));
+ RUBY_EXTERN int rb_thread_critical;
+ void rb_thread_schedule _((void));
+
+-RUBY_EXTERN VALUE *rb_gc_stack_end;
+ RUBY_EXTERN int rb_gc_stack_grow_direction; /* -1 for down or 1 for up */
+
+ #if STACK_GROW_DIRECTION > 0
+@@ -268,12 +267,14 @@ RUBY_EXTERN VALUE *__sp(void);
+ #if STACK_WIPE_METHOD == 0
+ #define rb_gc_wipe_stack() ((void)0)
+ #elif STACK_WIPE_METHOD == 4
+-#define rb_gc_wipe_stack() { \
+- VALUE *end = rb_gc_stack_end; \
+- VALUE *sp = __sp(); \
+- rb_gc_stack_end = sp; \
+- __stack_zero(end, sp); \
+-}
++#define rb_gc_wipe_stack() do { \
++ if (rb_curr_thread) { \
++ VALUE *end = rb_curr_thread->gc_stack_end; \
++ VALUE *sp = __sp(); \
++ rb_curr_thread->gc_stack_end = sp; \
++ __stack_zero(end, sp); \
++ } \
++} while (0)
+ #else
+ RUBY_EXTERN void rb_gc_wipe_stack(void);
+ #endif
+@@ -283,7 +284,7 @@ RUBY_EXTERN void rb_gc_wipe_stack(void);
+ */
+ #define rb_gc_update_stack_extent() do { \
+ VALUE *sp = __sp(); \
+- if __stack_past(rb_gc_stack_end, sp) rb_gc_stack_end = sp; \
++ if (rb_curr_thread && __stack_past(rb_curr_thread->gc_stack_end, sp)) rb_curr_thread->gc_stack_end = sp; \
+ } while(0)
+
+
+diff --git a/signal.c b/signal.c
+index 4cf3bec..58798bd 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,36 @@ 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
++
++ 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)
+@@ -633,6 +794,7 @@ sigsegv(sig)
+ rb_bug("Segmentation fault");
+ }
+ #endif
++#endif
+
+ #ifdef SIGPIPE
+ static RETSIGTYPE sigpipe _((int));
+@@ -704,7 +866,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;
+@@ -951,6 +1114,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;
+@@ -959,7 +1136,7 @@ install_sighandler(signum, handler)
+
+ old = ruby_signal(signum, handler);
+ if (old != SIG_DFL) {
+- ruby_signal(signum, old);
++ ruby_signal(signum, old);
+ }
+ }
+
+@@ -1088,6 +1265,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);
diff --git a/patchsets/patches-ee-1.8.7.2011.03/series b/patchsets/patches-ee-1.8.7.2011.03/series
new file mode 100644
index 0000000..3ef404e
--- /dev/null
+++ b/patchsets/patches-ee-1.8.7.2011.03/series
@@ -0,0 +1,7 @@
+001_memory_leak.patch
+002_mkconfig.patch
+003_mkmf-parallel-install.patch
+004_configure-libdir.patch
+005_mkconfig-libdir.patch
+007_no-undefined-ext.patch
+008_berkdb-5.0.patch
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2011-05-15 17:52 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-15 17:52 [gentoo-commits] proj/ruby-scripts:master commit in: patchsets/patches-ee-1.8.7.2011.03/ Hans de Graaff
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox