keep a map of thread ids to vm pointers. use this to look up the correct VM to handle mach exceptions on os x

db4
Joe Groff 2009-10-02 12:00:01 -05:00
parent f867a776d9
commit 435cd02200
5 changed files with 35 additions and 18 deletions

View File

@ -4,6 +4,7 @@ namespace factor
{ {
factor_vm *vm; factor_vm *vm;
unordered_map<THREADHANDLE, factor_vm*> thread_vms;
void init_globals() void init_globals()
{ {
@ -221,23 +222,30 @@ struct startargs {
vm_char **argv; vm_char **argv;
}; };
// arg must be new'ed because we're going to delete it! factor_vm * new_factor_vm()
void* start_standalone_factor_thread(void *arg)
{ {
factor_vm *newvm = new factor_vm; factor_vm *newvm = new factor_vm;
register_vm_with_thread(newvm); 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; startargs *args = (startargs*) arg;
int argc = args->argc; vm_char **argv = args->argv; int argc = args->argc; vm_char **argv = args->argv;
delete args; delete args;
newvm->start_standalone_factor(argc, argv); newvm->start_standalone_factor(argc, argv);
return 0; return 0;
} }
VM_C_API void start_standalone_factor(int argc, vm_char **argv) 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; vm = newvm;
register_vm_with_thread(newvm);
return newvm->start_standalone_factor(argc,argv); return newvm->start_standalone_factor(argc,argv);
} }

View File

@ -33,7 +33,7 @@ void factor_vm::call_fault_handler(
exception_data_type_t code, exception_data_type_t code,
MACH_EXC_STATE_TYPE *exc_state, MACH_EXC_STATE_TYPE *exc_state,
MACH_THREAD_STATE_TYPE *thread_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 /* There is a race condition here, but in practice an exception
delivered during stack frame setup/teardown or while transitioning 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, exception_data_type_t code,
MACH_EXC_STATE_TYPE *exc_state, MACH_EXC_STATE_TYPE *exc_state,
MACH_THREAD_STATE_TYPE *thread_state, MACH_THREAD_STATE_TYPE *thread_state,
MACH_FLOAT_STATE_TYPE *float_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<THREADHANDLE, factor_vm*>::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 /* 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" extern "C"
kern_return_t kern_return_t
catch_exception_raise (mach_port_t exception_port, 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.. /* 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; exc_state_count = MACH_EXC_STATE_COUNT;
if (thread_get_state (thread, MACH_EXC_STATE_FLAVOR, if (thread_get_state (thread, MACH_EXC_STATE_FLAVOR,
(natural_t *)&exc_state, &exc_state_count) (natural_t *)&exc_state, &exc_state_count)
@ -116,7 +122,7 @@ catch_exception_raise (mach_port_t exception_port,
return KERN_FAILURE; 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, if (thread_get_state (thread, MACH_FLOAT_STATE_FLAVOR,
(natural_t *)&float_state, &float_state_count) (natural_t *)&float_state, &float_state_count)
!= KERN_SUCCESS) != KERN_SUCCESS)
@ -128,11 +134,11 @@ catch_exception_raise (mach_port_t exception_port,
/* Modify registers so to have the thread resume executing the /* Modify registers so to have the thread resume executing the
fault handler */ 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.. /* 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, if (thread_set_state (thread, MACH_FLOAT_STATE_FLAVOR,
(natural_t *)&float_state, float_state_count) (natural_t *)&float_state, float_state_count)
!= KERN_SUCCESS) != KERN_SUCCESS)
@ -167,7 +173,7 @@ mach_exception_thread (void *arg)
char data[1024]; char data[1024];
} }
msg; msg;
/* Buffer for a reply message. */ /* Buffer for a reply message. */
struct struct
{ {
mach_msg_header_t head; mach_msg_header_t head;
@ -230,7 +236,7 @@ void mach_initialize ()
for a particular thread. This has the effect that when our exception for a particular thread. This has the effect that when our exception
port gets the message, the thread specific exception port has already port gets the message, the thread specific exception port has already
been asked, and we don't need to bother about it. 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, if (task_set_exception_ports (self, mask, our_exception_port,
EXCEPTION_DEFAULT, MACHINE_THREAD_STATE) EXCEPTION_DEFAULT, MACHINE_THREAD_STATE)
!= KERN_SUCCESS) != KERN_SUCCESS)

View File

@ -45,7 +45,7 @@ typedef char symbol_char;
typedef pthread_t THREADHANDLE; typedef pthread_t THREADHANDLE;
THREADHANDLE start_thread(void *(*start_routine)(void *),void *args); 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 unix_init_signals();
void signal_handler(int signal, siginfo_t* siginfo, void* uap); void signal_handler(int signal, siginfo_t* siginfo, void* uap);

View File

@ -29,6 +29,7 @@ FACTOR_STDCALL LONG exception_handler(PEXCEPTION_POINTERS pe);
typedef HANDLE THREADHANDLE; typedef HANDLE THREADHANDLE;
THREADHANDLE start_thread(void *(*start_routine)(void *),void *args); THREADHANDLE start_thread(void *(*start_routine)(void *),void *args);
inline static THREADHANDLE thread_id() { return GetCurrentThread(); }
void init_platform_globals(); void init_platform_globals();
struct factor_vm; struct factor_vm;

View File

@ -796,4 +796,6 @@ struct factor_vm
#define SIGNAL_VM_PTR() tls_vm() #define SIGNAL_VM_PTR() tls_vm()
#endif #endif
extern unordered_map<THREADHANDLE, factor_vm*> thread_vms;
} }