keep a map of thread ids to vm pointers. use this to look up the correct VM to handle mach exceptions on os x
							parent
							
								
									f867a776d9
								
							
						
					
					
						commit
						435cd02200
					
				| 
						 | 
					@ -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()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -46,7 +47,7 @@ void factor_vm::default_parameters(vm_parameters *p)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	if (this == vm)
 | 
						if (this == vm)
 | 
				
			||||||
		p->console = true;
 | 
							p->console = true;
 | 
				
			||||||
	else 		
 | 
						else		
 | 
				
			||||||
		p->console = false;
 | 
							p->console = false;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue