summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--eval.c57
-rw-r--r--gc.c8
3 files changed, 52 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 20f652a1bd..3be579a487 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Thu Jun 9 19:55:41 2005 Tanaka Akira <akr@m17n.org>
+
+ * eval.c (ruby_longjmp): new macro to call longjmp, setcontext, etc.
+ (ruby_setjmp): new macro to call setjmp, getcontext, etc.
+ (ruby_setjmp): call setjmp before getcontext to avoid IA64 register
+ stack problem.
+ [ruby-talk:144939]
+
+ * gc.c (Init_stack): remove IA64_MAGIC_STACK_LIMIT.
+
Wed Jun 8 11:11:34 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
* bignum.c (get2comp): calculate proper 2's complement for
diff --git a/eval.c b/eval.c
index f2715d400c..da8094faeb 100644
--- a/eval.c
+++ b/eval.c
@@ -32,9 +32,8 @@
#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
#include <ucontext.h>
#define USE_CONTEXT
-#else
-#include <setjmp.h>
#endif
+#include <setjmp.h>
#include "st.h"
#include "dln.h"
@@ -98,8 +97,6 @@ typedef struct {
volatile int status;
} rb_jmpbuf_t[1];
-#undef longjmp
-#undef setjmp
NORETURN(static void rb_jump_context(rb_jmpbuf_t, int));
static inline void
rb_jump_context(env, val)
@@ -110,15 +107,45 @@ rb_jump_context(env, val)
setcontext(&env->context);
abort(); /* ensure noreturn */
}
-#define longjmp(env, val) rb_jump_context(env, val)
-#define setjmp(j) ((j)->status = 0, getcontext(&(j)->context), (j)->status)
+/*
+ * DUMMY_SETJMP is a magic for getcontext, gcc and IA64 register stack
+ * combination problem.
+ *
+ * Assume following code sequence.
+ *
+ * 1. set a register in the register stack such as r32.
+ * 2. call getcontext.
+ * 3. use the register.
+ * 4. update the register for other use.
+ * 5. call setcontext directly or indirectly.
+ *
+ * This code should be run as 1->2->3->4->5->3->4.
+ * But after second getcontext return (second 3),
+ * the register is broken (updated).
+ * It's because getcontext/setcontext doesn't preserve the content of the
+ * register stack.
+ *
+ * setjmp also doesn't preserve the content of the register stack.
+ * But it has not the problem because gcc knows setjmp may return twice.
+ * gcc detects setjmp and generates setjmp safe code.
+ *
+ * So setjmp call before getcontext call fix the problem.
+ * It is not required that setjmp is called at run time, since the problem is
+ * register usage.
+ */
+static jmp_buf dummy_setjmp_jmp_buf;
+int dummy_setjmp_false = 0;
+#define DUMMY_SETJMP (dummy_setjmp_false ? setjmp(dummy_setjmp_jmp_buf) : 0)
+#define ruby_longjmp(env, val) rb_jump_context(env, val)
+#define ruby_setjmp(j) ((j)->status = 0, DUMMY_SETJMP, getcontext(&(j)->context), (j)->status)
#else
typedef jmp_buf rb_jmpbuf_t;
-#ifndef setjmp
-#ifdef HAVE__SETJMP
-#define setjmp(env) _setjmp(env)
-#define longjmp(env,val) _longjmp(env,val)
-#endif
+#if !defined(setjmp) && defined(HAVE__SETJMP)
+#define ruby_setjmp(env) _setjmp(env)
+#define ruby_longjmp(env,val) _longjmp(env,val)
+#else
+#define ruby_setjmp(env) setjmp(env)
+#define ruby_longjmp(env,val) longjmp(env,val)
#endif
#endif
@@ -927,12 +954,12 @@ static struct tag *prot_tag;
#define PROT_LAMBDA INT2FIX(2) /* 5 */
#define PROT_YIELD INT2FIX(3) /* 7 */
-#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, setjmp(prot_tag->buf))
+#define EXEC_TAG() (FLUSH_REGISTER_WINDOWS, ruby_setjmp(prot_tag->buf))
#define JUMP_TAG(st) do { \
ruby_frame = prot_tag->frame; \
ruby_iter = prot_tag->iter; \
- longjmp(prot_tag->buf,(st)); \
+ ruby_longjmp(prot_tag->buf,(st)); \
} while (0)
#define POP_TAG() \
@@ -10006,7 +10033,7 @@ rb_thread_switch(n)
#define THREAD_SAVE_CONTEXT(th) \
(rb_thread_save_context(th),\
- rb_thread_switch((FLUSH_REGISTER_WINDOWS, setjmp((th)->context))))
+ rb_thread_switch((FLUSH_REGISTER_WINDOWS, ruby_setjmp((th)->context))))
NORETURN(static void rb_thread_restore_context _((rb_thread_t,int)));
@@ -10087,7 +10114,7 @@ rb_thread_restore_context(th, exit)
rb_backref_set(tmp->last_match);
tmp->last_match = tval;
- longjmp(tmp->context, ex);
+ ruby_longjmp(tmp->context, ex);
}
static void
diff --git a/gc.c b/gc.c
index 9e6a8f3d85..fdcff70d39 100644
--- a/gc.c
+++ b/gc.c
@@ -1483,14 +1483,6 @@ Init_stack(addr)
STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
}
}
-#if defined(__ia64__) && (!defined(__GNUC__) || __GNUC__ < 2 || defined(__OPTIMIZE__))
- /* ruby crashes on IA64 if compiled with optimizer on */
- /* when if STACK_LEVEL_MAX is greater than this magic number */
- /* I know this is a kludge. I suspect optimizer bug */
-#define IA64_MAGIC_STACK_LIMIT 49152
- if (STACK_LEVEL_MAX > IA64_MAGIC_STACK_LIMIT)
- STACK_LEVEL_MAX = IA64_MAGIC_STACK_LIMIT;
-#endif
#endif
}