vm: handle async signals at safepoints on unix

Factor now supports the new 4.0BSD feature of "signals".
db4
Joe Groff 2011-10-19 15:39:44 -07:00
parent 6f75e84d93
commit b3e5f75c9e
12 changed files with 85 additions and 28 deletions

View File

@ -43,6 +43,12 @@ struct code_heap {
void flush_icache(); void flush_icache();
void guard_safepoint(); void guard_safepoint();
void unguard_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 { struct code_heap_room {

View File

@ -84,9 +84,9 @@ void factor_vm::not_implemented_error()
void factor_vm::memory_protection_error(cell addr) void factor_vm::memory_protection_error(cell addr)
{ {
/* Retain and call stack underflows are not supposed to happen */ if(code->safepoint_p(addr))
handle_safepoint();
if(ctx->datastack_seg->underflow_p(addr)) else if(ctx->datastack_seg->underflow_p(addr))
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object); general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
else if(ctx->datastack_seg->overflow_p(addr)) else if(ctx->datastack_seg->overflow_p(addr))
general_error(ERROR_DATASTACK_OVERFLOW,false_object,false_object); general_error(ERROR_DATASTACK_OVERFLOW,false_object,false_object);
@ -134,15 +134,17 @@ void memory_signal_handler_impl()
current_vm()->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(); scrub_return_address();
signal_error(signal_number); 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() void factor_vm::fp_signal_handler_impl()
@ -159,4 +161,24 @@ void fp_signal_handler_impl()
current_vm()->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();
}
} }

View File

@ -29,6 +29,6 @@ void critical_error(const char *msg, cell tagged);
void out_of_memory(); void out_of_memory();
void memory_signal_handler_impl(); void memory_signal_handler_impl();
void fp_signal_handler_impl(); void fp_signal_handler_impl();
void misc_signal_handler_impl(); void synchronous_signal_handler_impl();
} }

View File

@ -60,7 +60,7 @@ void factor_vm::call_fault_handler(
default: signal_number = SIGABRT; break; 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;
} }
} }

View File

@ -19,9 +19,8 @@ void register_vm_with_thread(factor_vm *vm)
global_vm = vm; global_vm = vm;
} }
factor_vm *current_vm() factor_vm *current_vm_p()
{ {
assert(global_vm != NULL);
return global_vm; return global_vm;
} }

View File

@ -16,10 +16,9 @@ void register_vm_with_thread(factor_vm *vm)
pthread_setspecific(current_vm_tls_key,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); factor_vm *vm = (factor_vm*)pthread_getspecific(current_vm_tls_key);
assert(vm != NULL);
return vm; return vm;
} }

View File

@ -17,11 +17,9 @@ void register_vm_with_thread(factor_vm *vm)
fatal_error("TlsSetValue() failed",0); fatal_error("TlsSetValue() failed",0);
} }
factor_vm *current_vm() factor_vm *current_vm_p()
{ {
factor_vm *vm = (factor_vm *)TlsGetValue(current_vm_tls_key); return (factor_vm *)TlsGetValue(current_vm_tls_key);
assert(vm != NULL);
return vm;
} }
} }

View File

@ -3,7 +3,14 @@ namespace factor
void init_mvm(); void init_mvm();
void register_vm_with_thread(factor_vm *vm); 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); VM_C_API THREADHANDLE start_standalone_factor_in_new_thread(int argc, vm_char **argv);

View File

@ -151,11 +151,18 @@ void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
vm->dispatch_signal(uap,factor::memory_signal_handler_impl); 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(); factor_vm *vm = current_vm();
vm->signal_number = signal; 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) 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, vm->dispatch_signal(uap,
(siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF) (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); : factor::fp_signal_handler_impl);
} }
@ -206,7 +213,8 @@ void factor_vm::unix_init_signals()
#endif #endif
struct sigaction memory_sigaction; struct sigaction memory_sigaction;
struct sigaction misc_sigaction; struct sigaction synchronous_sigaction;
struct sigaction next_safepoint_sigaction;
struct sigaction fpe_sigaction; struct sigaction fpe_sigaction;
struct sigaction ignore_sigaction; struct sigaction ignore_sigaction;
@ -226,13 +234,25 @@ void factor_vm::unix_init_signals()
sigaction_safe(SIGFPE,&fpe_sigaction,NULL); sigaction_safe(SIGFPE,&fpe_sigaction,NULL);
memset(&misc_sigaction,0,sizeof(struct sigaction)); memset(&synchronous_sigaction,0,sizeof(struct sigaction));
sigemptyset(&misc_sigaction.sa_mask); sigemptyset(&synchronous_sigaction.sa_mask);
misc_sigaction.sa_sigaction = misc_signal_handler; synchronous_sigaction.sa_sigaction = synchronous_signal_handler;
misc_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK; synchronous_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigaction_safe(SIGQUIT,&misc_sigaction,NULL); sigaction_safe(SIGILL,&synchronous_sigaction,NULL);
sigaction_safe(SIGILL,&misc_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 /* 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 by subprocesses, which we don't want. There is a unit test in

View File

@ -89,6 +89,7 @@ namespace factor
_(ftell) \ _(ftell) \
_(full_gc) \ _(full_gc) \
_(fwrite) \ _(fwrite) \
_(guard_safepoint) \
_(identity_hashcode) \ _(identity_hashcode) \
_(innermost_stack_frame_executing) \ _(innermost_stack_frame_executing) \
_(innermost_stack_frame_scan) \ _(innermost_stack_frame_scan) \

View File

@ -8,6 +8,7 @@ factor_vm::factor_vm() :
callback_id(0), callback_id(0),
c_to_factor_func(NULL), c_to_factor_func(NULL),
profiling_p(false), profiling_p(false),
safepoint_signal_number(0),
gc_off(false), gc_off(false),
current_gc(NULL), current_gc(NULL),
gc_events(NULL), gc_events(NULL),

View File

@ -57,6 +57,7 @@ struct factor_vm
cell signal_number; cell signal_number;
cell signal_fault_addr; cell signal_fault_addr;
unsigned int signal_fpu_status; unsigned int signal_fpu_status;
cell safepoint_signal_number;
/* GC is off during heap walking */ /* GC is off during heap walking */
bool gc_off; bool gc_off;
@ -179,8 +180,11 @@ struct factor_vm
void fp_trap_error(unsigned int fpu_status); void fp_trap_error(unsigned int fpu_status);
void primitive_unimplemented(); void primitive_unimplemented();
void memory_signal_handler_impl(); void memory_signal_handler_impl();
void misc_signal_handler_impl(); void synchronous_signal_handler_impl();
void fp_signal_handler_impl(); void fp_signal_handler_impl();
void enqueue_safepoint_signal(cell signal);
void handle_safepoint();
void primitive_guard_safepoint();
// bignum // bignum
int bignum_equal_p(bignum * x, bignum * y); int bignum_equal_p(bignum * x, bignum * y);