summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-08-19 00:37:16 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-08-19 00:37:16 +0000
commit11e7d457d6b86f5ca53440c7caadf679f4abff34 (patch)
treeb328848b2192d29018190e64f0deffd81c794b8b /eval.c
parent4f60a534cd006a72f4b4b0cdf7b1f4cc205a81bd (diff)
* eval.c (rb_thread_save_context, rb_thread_restore_context):
save/restore SEH chain on MS-Windows at thread switch. [ruby-win32:273] * eval.c (win32_get_exception_frame, win32_set_exception_frame): added. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2716 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/eval.c b/eval.c
index ee19b03c2b..7a32be4574 100644
--- a/eval.c
+++ b/eval.c
@@ -7221,6 +7221,53 @@ Init_Proc()
rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1);
}
+/* Windows SEH refers data on the stack. */
+#ifdef _WIN32
+# if !(defined _M_IX86 || defined __i386__)
+# error unsupported processor
+# endif
+static inline DWORD
+win32_get_exception_list()
+{
+ DWORD p;
+# if defined _MSC_VER
+# ifdef _M_IX86
+ __asm mov eax, fs:[0];
+ __asm mov p, eax;
+# endif
+# elif defined __GNUC__
+# ifdef __i386__
+ __asm__("movl %%fs:0,%0" : "=r"(p));
+# endif
+# elif defined __BORLANDC__
+ __emit__(0x64, 0xA1, 0, 0, 0, 0); /* mov eax, fs:[0] */
+ p = _EAX;
+# else
+# error unsupported compiler
+# endif
+ return p;
+}
+
+static inline void
+win32_set_exception_list()
+ DWORD p;
+{
+# if defined _MSC_VER
+# ifdef _M_IX86
+ __asm mov eax, p;
+ __asm mov fs:[0], eax;
+# endif
+# elif defined __GNUC__
+# ifdef __i386__
+ __asm__("movl %0,%%fs:0" :: "r"(p));
+# endif
+# elif defined __BORLANDC__
+ _EAX = p;
+ __emit__(0x64, 0xA3, 0, 0, 0, 0); /* mov fs:[0], eax */
+# endif
+}
+#endif
+
static VALUE rb_eThreadError;
int rb_thread_pending = 0;
@@ -7250,6 +7297,9 @@ enum thread_status {
struct thread {
struct thread *next, *prev;
jmp_buf context;
+#ifdef _WIN32
+ DWORD win32_exception_list;
+#endif
VALUE result;
@@ -7501,6 +7551,9 @@ rb_thread_save_context(th)
th->stk_len = len;
FLUSH_REGISTER_WINDOWS;
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
+#ifdef _WIN32
+ th->win32_exception_list = win32_get_exception_list();
+#endif
th->frame = ruby_frame;
th->scope = ruby_scope;
@@ -7614,6 +7667,9 @@ rb_thread_restore_context(th, exit)
ruby_current_node = th->node;
+#ifdef _WIN32
+ win32_set_exception_list(th->win32_exception_list);
+#endif
tmp = th;
ex = exit;
FLUSH_REGISTER_WINDOWS;