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;
unordered_map<THREADHANDLE, factor_vm*> 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);
}

View File

@ -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<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
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)

View File

@ -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);

View File

@ -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;

View File

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