1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2005-06-09 11:18:31 +00:00
parent 20e269da04
commit 27c228d681
3 changed files with 53 additions and 24 deletions

View file

@ -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.
Thu Jun 9 18:24:16 2005 Tanaka Akira <akr@m17n.org>
* configure.in, eval.c, gc.c: use libunwind only on HP-UX.

59
eval.c
View file

@ -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
@ -934,12 +961,12 @@ static struct tag *prot_tag;
#define PROT_YIELD INT2FIX(3) /* 7 */
#define PROT_TOP INT2FIX(4) /* 9 */
#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() \
@ -10360,7 +10387,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)));
NOINLINE(static void stack_extend _((rb_thread_t, int)));
@ -10451,7 +10478,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
@ -11918,7 +11945,7 @@ rb_thread_start_0(fn, arg, th)
th->anchor = ip;
thread_insert(th);
curr_thread = th;
longjmp((prot_tag = ip->tag)->buf, TAG_THREAD);
ruby_longjmp((prot_tag = ip->tag)->buf, TAG_THREAD);
}
if (ruby_block) { /* should nail down higher blocks */

8
gc.c
View file

@ -1469,14 +1469,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
}