public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [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