From 435cd02200c6973e2be431a7182f9bbc08837a7b Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Fri, 2 Oct 2009 12:00:01 -0500 Subject: [PATCH] keep a map of thread ids to vm pointers. use this to look up the correct VM to handle mach exceptions on os x --- vm/factor.cpp | 22 +++++++++++++++------- vm/mach_signal.cpp | 26 ++++++++++++++++---------- vm/os-unix.hpp | 2 +- vm/os-windows-nt.hpp | 1 + vm/vm.hpp | 2 ++ 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/vm/factor.cpp b/vm/factor.cpp index bf826bbbfa..6243da7572 100755 --- a/vm/factor.cpp +++ b/vm/factor.cpp @@ -4,6 +4,7 @@ namespace factor { factor_vm *vm; +unordered_map thread_vms; void init_globals() { @@ -46,7 +47,7 @@ void factor_vm::default_parameters(vm_parameters *p) #else if (this == vm) p->console = true; - else + else p->console = false; #endif @@ -221,23 +222,30 @@ struct startargs { vm_char **argv; }; -// arg must be new'ed because we're going to delete it! -void* start_standalone_factor_thread(void *arg) +factor_vm * new_factor_vm() { factor_vm *newvm = new factor_vm; register_vm_with_thread(newvm); + thread_vms[thread_id()] = newvm; + + return newvm; +} + +// arg must be new'ed because we're going to delete it! +void* start_standalone_factor_thread(void *arg) +{ + factor_vm *newvm = new_factor_vm(); startargs *args = (startargs*) arg; - int argc = args->argc; vm_char **argv = args->argv; - delete args; + int argc = args->argc; vm_char **argv = args->argv; + delete args; newvm->start_standalone_factor(argc, argv); return 0; } VM_C_API void start_standalone_factor(int argc, vm_char **argv) { - factor_vm *newvm = new factor_vm; + factor_vm *newvm = new_factor_vm(); vm = newvm; - register_vm_with_thread(newvm); return newvm->start_standalone_factor(argc,argv); } diff --git a/vm/mach_signal.cpp b/vm/mach_signal.cpp index 7793caa3be..2d76b12c38 100644 --- a/vm/mach_signal.cpp +++ b/vm/mach_signal.cpp @@ -33,7 +33,7 @@ void factor_vm::call_fault_handler( exception_data_type_t code, MACH_EXC_STATE_TYPE *exc_state, MACH_THREAD_STATE_TYPE *thread_state, - MACH_FLOAT_STATE_TYPE *float_state) + MACH_FLOAT_STATE_TYPE *float_state) { /* There is a race condition here, but in practice an exception delivered during stack frame setup/teardown or while transitioning @@ -68,17 +68,23 @@ void factor_vm::call_fault_handler( } } -static void call_fault_handler(exception_type_t exception, +static void call_fault_handler( + mach_port_t thread, + exception_type_t exception, exception_data_type_t code, MACH_EXC_STATE_TYPE *exc_state, MACH_THREAD_STATE_TYPE *thread_state, MACH_FLOAT_STATE_TYPE *float_state) { - SIGNAL_VM_PTR()->call_fault_handler(exception,code,exc_state,thread_state,float_state); + THREADHANDLE thread_id = pthread_from_mach_thread_np(thread); + assert(thread_id); + unordered_map::const_iterator vm = thread_vms.find(thread_id); + if (vm != thread_vms.end()) + vm->second->call_fault_handler(exception,code,exc_state,thread_state,float_state); } /* Handle an exception by invoking the user's fault handler and/or forwarding -the duty to the previously installed handlers. */ +the duty to the previously installed handlers. */ extern "C" kern_return_t catch_exception_raise (mach_port_t exception_port, @@ -95,7 +101,7 @@ catch_exception_raise (mach_port_t exception_port, /* Get fault information and the faulting thread's register contents.. - See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html. */ + See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html. */ exc_state_count = MACH_EXC_STATE_COUNT; if (thread_get_state (thread, MACH_EXC_STATE_FLAVOR, (natural_t *)&exc_state, &exc_state_count) @@ -116,7 +122,7 @@ catch_exception_raise (mach_port_t exception_port, return KERN_FAILURE; } - float_state_count = MACH_FLOAT_STATE_COUNT; + float_state_count = MACH_FLOAT_STATE_COUNT; if (thread_get_state (thread, MACH_FLOAT_STATE_FLAVOR, (natural_t *)&float_state, &float_state_count) != KERN_SUCCESS) @@ -128,11 +134,11 @@ catch_exception_raise (mach_port_t exception_port, /* Modify registers so to have the thread resume executing the fault handler */ - call_fault_handler(exception,code[0],&exc_state,&thread_state,&float_state); + call_fault_handler(thread,exception,code[0],&exc_state,&thread_state,&float_state); /* Set the faulting thread's register contents.. - See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html. */ + See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_set_state.html. */ if (thread_set_state (thread, MACH_FLOAT_STATE_FLAVOR, (natural_t *)&float_state, float_state_count) != KERN_SUCCESS) @@ -167,7 +173,7 @@ mach_exception_thread (void *arg) char data[1024]; } msg; - /* Buffer for a reply message. */ + /* Buffer for a reply message. */ struct { mach_msg_header_t head; @@ -230,7 +236,7 @@ void mach_initialize () for a particular thread. This has the effect that when our exception port gets the message, the thread specific exception port has already been asked, and we don't need to bother about it. - See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html. */ + See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html. */ if (task_set_exception_ports (self, mask, our_exception_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) != KERN_SUCCESS) diff --git a/vm/os-unix.hpp b/vm/os-unix.hpp index 6ef539ab8b..dc8acc445e 100644 --- a/vm/os-unix.hpp +++ b/vm/os-unix.hpp @@ -45,7 +45,7 @@ typedef char symbol_char; typedef pthread_t THREADHANDLE; THREADHANDLE start_thread(void *(*start_routine)(void *),void *args); -pthread_t thread_id(); +inline static THREADHANDLE thread_id() { return pthread_self(); } void unix_init_signals(); void signal_handler(int signal, siginfo_t* siginfo, void* uap); diff --git a/vm/os-windows-nt.hpp b/vm/os-windows-nt.hpp index b02006f9d2..1b12b47c40 100755 --- a/vm/os-windows-nt.hpp +++ b/vm/os-windows-nt.hpp @@ -29,6 +29,7 @@ FACTOR_STDCALL LONG exception_handler(PEXCEPTION_POINTERS pe); typedef HANDLE THREADHANDLE; THREADHANDLE start_thread(void *(*start_routine)(void *),void *args); +inline static THREADHANDLE thread_id() { return GetCurrentThread(); } void init_platform_globals(); struct factor_vm; diff --git a/vm/vm.hpp b/vm/vm.hpp index 97d873db93..8f2b96944f 100644 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -796,4 +796,6 @@ struct factor_vm #define SIGNAL_VM_PTR() tls_vm() #endif +extern unordered_map thread_vms; + }