vm: handle async signals at safepoints on unix
Factor now supports the new 4.0BSD feature of "signals".db4
parent
6f75e84d93
commit
b3e5f75c9e
|
@ -43,6 +43,12 @@ struct code_heap {
|
|||
void flush_icache();
|
||||
void guard_safepoint();
|
||||
void unguard_safepoint();
|
||||
|
||||
bool safepoint_p(cell addr)
|
||||
{
|
||||
cell page_mask = ~(getpagesize() - 1);
|
||||
return (addr & page_mask) == (cell)safepoint_page;
|
||||
}
|
||||
};
|
||||
|
||||
struct code_heap_room {
|
||||
|
|
|
@ -84,9 +84,9 @@ void factor_vm::not_implemented_error()
|
|||
|
||||
void factor_vm::memory_protection_error(cell addr)
|
||||
{
|
||||
/* Retain and call stack underflows are not supposed to happen */
|
||||
|
||||
if(ctx->datastack_seg->underflow_p(addr))
|
||||
if(code->safepoint_p(addr))
|
||||
handle_safepoint();
|
||||
else if(ctx->datastack_seg->underflow_p(addr))
|
||||
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
|
||||
else if(ctx->datastack_seg->overflow_p(addr))
|
||||
general_error(ERROR_DATASTACK_OVERFLOW,false_object,false_object);
|
||||
|
@ -134,15 +134,17 @@ void memory_signal_handler_impl()
|
|||
current_vm()->memory_signal_handler_impl();
|
||||
}
|
||||
|
||||
void factor_vm::misc_signal_handler_impl()
|
||||
void factor_vm::synchronous_signal_handler_impl()
|
||||
{
|
||||
scrub_return_address();
|
||||
signal_error(signal_number);
|
||||
}
|
||||
|
||||
void misc_signal_handler_impl()
|
||||
void synchronous_signal_handler_impl()
|
||||
{
|
||||
current_vm()->misc_signal_handler_impl();
|
||||
factor_vm *vm = current_vm_p();
|
||||
if (vm)
|
||||
vm->synchronous_signal_handler_impl();
|
||||
}
|
||||
|
||||
void factor_vm::fp_signal_handler_impl()
|
||||
|
@ -159,4 +161,24 @@ void fp_signal_handler_impl()
|
|||
current_vm()->fp_signal_handler_impl();
|
||||
}
|
||||
|
||||
void factor_vm::enqueue_safepoint_signal(cell signal)
|
||||
{
|
||||
safepoint_signal_number = signal;
|
||||
code->guard_safepoint();
|
||||
}
|
||||
|
||||
void factor_vm::handle_safepoint()
|
||||
{
|
||||
assert(safepoint_signal_number != 0);
|
||||
code->unguard_safepoint();
|
||||
cell signal = safepoint_signal_number;
|
||||
safepoint_signal_number = 0;
|
||||
general_error(ERROR_SIGNAL,from_unsigned_cell(signal),false_object);
|
||||
}
|
||||
|
||||
void factor_vm::primitive_guard_safepoint()
|
||||
{
|
||||
code->guard_safepoint();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,6 @@ void critical_error(const char *msg, cell tagged);
|
|||
void out_of_memory();
|
||||
void memory_signal_handler_impl();
|
||||
void fp_signal_handler_impl();
|
||||
void misc_signal_handler_impl();
|
||||
void synchronous_signal_handler_impl();
|
||||
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ void factor_vm::call_fault_handler(
|
|||
default: signal_number = SIGABRT; break;
|
||||
}
|
||||
|
||||
MACH_PROGRAM_COUNTER(thread_state) = (cell)factor::misc_signal_handler_impl;
|
||||
MACH_PROGRAM_COUNTER(thread_state) = (cell)factor::synchronous_signal_handler_impl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,8 @@ void register_vm_with_thread(factor_vm *vm)
|
|||
global_vm = vm;
|
||||
}
|
||||
|
||||
factor_vm *current_vm()
|
||||
factor_vm *current_vm_p()
|
||||
{
|
||||
assert(global_vm != NULL);
|
||||
return global_vm;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,10 +16,9 @@ void register_vm_with_thread(factor_vm *vm)
|
|||
pthread_setspecific(current_vm_tls_key,vm);
|
||||
}
|
||||
|
||||
factor_vm *current_vm()
|
||||
factor_vm *current_vm_p()
|
||||
{
|
||||
factor_vm *vm = (factor_vm*)pthread_getspecific(current_vm_tls_key);
|
||||
assert(vm != NULL);
|
||||
return vm;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,9 @@ void register_vm_with_thread(factor_vm *vm)
|
|||
fatal_error("TlsSetValue() failed",0);
|
||||
}
|
||||
|
||||
factor_vm *current_vm()
|
||||
factor_vm *current_vm_p()
|
||||
{
|
||||
factor_vm *vm = (factor_vm *)TlsGetValue(current_vm_tls_key);
|
||||
assert(vm != NULL);
|
||||
return vm;
|
||||
return (factor_vm *)TlsGetValue(current_vm_tls_key);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,14 @@ namespace factor
|
|||
|
||||
void init_mvm();
|
||||
void register_vm_with_thread(factor_vm *vm);
|
||||
factor_vm *current_vm();
|
||||
factor_vm *current_vm_p();
|
||||
|
||||
inline factor_vm *current_vm()
|
||||
{
|
||||
factor_vm *vm = current_vm_p();
|
||||
assert(vm != NULL);
|
||||
return vm;
|
||||
}
|
||||
|
||||
VM_C_API THREADHANDLE start_standalone_factor_in_new_thread(int argc, vm_char **argv);
|
||||
|
||||
|
|
|
@ -151,11 +151,18 @@ void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
|||
vm->dispatch_signal(uap,factor::memory_signal_handler_impl);
|
||||
}
|
||||
|
||||
void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
void synchronous_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
factor_vm *vm = current_vm();
|
||||
vm->signal_number = signal;
|
||||
vm->dispatch_signal(uap,factor::misc_signal_handler_impl);
|
||||
vm->dispatch_signal(uap,factor::synchronous_signal_handler_impl);
|
||||
}
|
||||
|
||||
void next_safepoint_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
factor_vm *vm = current_vm_p();
|
||||
if (vm)
|
||||
vm->enqueue_safepoint_signal(signal);
|
||||
}
|
||||
|
||||
void ignore_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
|
@ -171,7 +178,7 @@ void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
|||
|
||||
vm->dispatch_signal(uap,
|
||||
(siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF)
|
||||
? factor::misc_signal_handler_impl
|
||||
? factor::synchronous_signal_handler_impl
|
||||
: factor::fp_signal_handler_impl);
|
||||
}
|
||||
|
||||
|
@ -206,7 +213,8 @@ void factor_vm::unix_init_signals()
|
|||
#endif
|
||||
|
||||
struct sigaction memory_sigaction;
|
||||
struct sigaction misc_sigaction;
|
||||
struct sigaction synchronous_sigaction;
|
||||
struct sigaction next_safepoint_sigaction;
|
||||
struct sigaction fpe_sigaction;
|
||||
struct sigaction ignore_sigaction;
|
||||
|
||||
|
@ -226,13 +234,25 @@ void factor_vm::unix_init_signals()
|
|||
|
||||
sigaction_safe(SIGFPE,&fpe_sigaction,NULL);
|
||||
|
||||
memset(&misc_sigaction,0,sizeof(struct sigaction));
|
||||
sigemptyset(&misc_sigaction.sa_mask);
|
||||
misc_sigaction.sa_sigaction = misc_signal_handler;
|
||||
misc_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
memset(&synchronous_sigaction,0,sizeof(struct sigaction));
|
||||
sigemptyset(&synchronous_sigaction.sa_mask);
|
||||
synchronous_sigaction.sa_sigaction = synchronous_signal_handler;
|
||||
synchronous_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
|
||||
sigaction_safe(SIGQUIT,&misc_sigaction,NULL);
|
||||
sigaction_safe(SIGILL,&misc_sigaction,NULL);
|
||||
sigaction_safe(SIGILL,&synchronous_sigaction,NULL);
|
||||
sigaction_safe(SIGABRT,&synchronous_sigaction,NULL);
|
||||
|
||||
memset(&next_safepoint_sigaction,0,sizeof(struct sigaction));
|
||||
sigemptyset(&next_safepoint_sigaction.sa_mask);
|
||||
next_safepoint_sigaction.sa_sigaction = next_safepoint_signal_handler;
|
||||
next_safepoint_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
|
||||
sigaction_safe(SIGALRM,&next_safepoint_sigaction,NULL);
|
||||
sigaction_safe(SIGVTALRM,&next_safepoint_sigaction,NULL);
|
||||
sigaction_safe(SIGPROF,&next_safepoint_sigaction,NULL);
|
||||
sigaction_safe(SIGQUIT,&next_safepoint_sigaction,NULL);
|
||||
sigaction_safe(SIGINT,&next_safepoint_sigaction,NULL);
|
||||
sigaction_safe(SIGUSR1,&next_safepoint_sigaction,NULL);
|
||||
sigaction_safe(SIGUSR2,&next_safepoint_sigaction,NULL);
|
||||
|
||||
/* We don't use SA_IGN here because then the ignore action is inherited
|
||||
by subprocesses, which we don't want. There is a unit test in
|
||||
|
|
|
@ -89,6 +89,7 @@ namespace factor
|
|||
_(ftell) \
|
||||
_(full_gc) \
|
||||
_(fwrite) \
|
||||
_(guard_safepoint) \
|
||||
_(identity_hashcode) \
|
||||
_(innermost_stack_frame_executing) \
|
||||
_(innermost_stack_frame_scan) \
|
||||
|
|
|
@ -8,6 +8,7 @@ factor_vm::factor_vm() :
|
|||
callback_id(0),
|
||||
c_to_factor_func(NULL),
|
||||
profiling_p(false),
|
||||
safepoint_signal_number(0),
|
||||
gc_off(false),
|
||||
current_gc(NULL),
|
||||
gc_events(NULL),
|
||||
|
|
|
@ -57,6 +57,7 @@ struct factor_vm
|
|||
cell signal_number;
|
||||
cell signal_fault_addr;
|
||||
unsigned int signal_fpu_status;
|
||||
cell safepoint_signal_number;
|
||||
|
||||
/* GC is off during heap walking */
|
||||
bool gc_off;
|
||||
|
@ -179,8 +180,11 @@ struct factor_vm
|
|||
void fp_trap_error(unsigned int fpu_status);
|
||||
void primitive_unimplemented();
|
||||
void memory_signal_handler_impl();
|
||||
void misc_signal_handler_impl();
|
||||
void synchronous_signal_handler_impl();
|
||||
void fp_signal_handler_impl();
|
||||
void enqueue_safepoint_signal(cell signal);
|
||||
void handle_safepoint();
|
||||
void primitive_guard_safepoint();
|
||||
|
||||
// bignum
|
||||
int bignum_equal_p(bignum * x, bignum * y);
|
||||
|
|
Loading…
Reference in New Issue