X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fx86-darwin-os.c;h=8489322b71dbd261ecdf65a41fb4084e6f5bb84b;hb=bf40ae88bc289fd765a33861cc4bc0853ed483ba;hp=1650517fc88798db799b0dfdd2ba50b477d3391f;hpb=18a22e950b490011aac1ecce4b5d8a86d333fd00;p=sbcl.git diff --git a/src/runtime/x86-darwin-os.c b/src/runtime/x86-darwin-os.c index 1650517..8489322 100644 --- a/src/runtime/x86-darwin-os.c +++ b/src/runtime/x86-darwin-os.c @@ -1,5 +1,3 @@ - - #ifdef LISP_FEATURE_SB_THREAD #include #include @@ -25,6 +23,7 @@ #include #include #include +#include #ifdef LISP_FEATURE_SB_THREAD @@ -45,14 +44,23 @@ void set_data_desc_addr(data_desc_t* desc, void* addr) #endif -#ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER -kern_return_t mach_thread_init(mach_port_t thread_exception_port); +#ifdef LISP_FEATURE_SB_THREAD +void +arch_os_load_ldt(struct thread *thread) +{ + sel_t sel; + + sel.index = thread->tls_cookie; + sel.rpl = USER_PRIV; + sel.ti = SEL_LDT; + + __asm__ __volatile__ ("mov %0, %%fs" : : "r"(sel)); +} #endif int arch_os_thread_init(struct thread *thread) { #ifdef LISP_FEATURE_SB_THREAD int n; - sel_t sel; data_desc_t ldt_entry = { 0, 0, 0, DESC_DATA_WRITE, 3, 1, 0, DESC_DATA_32B, DESC_GRAN_BYTE, 0 }; @@ -70,17 +78,13 @@ int arch_os_thread_init(struct thread *thread) { thread_mutex_unlock(&modify_ldt_lock); FSHOW_SIGNAL((stderr, "/ TLS: Allocated LDT %x\n", n)); - sel.index = n; - sel.rpl = USER_PRIV; - sel.ti = SEL_LDT; - - __asm__ __volatile__ ("mov %0, %%fs" : : "r"(sel)); - thread->tls_cookie=n; + arch_os_load_ldt(thread); + pthread_setspecific(specials,thread); #endif #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER - mach_thread_init(THREAD_STRUCT_TO_EXCEPTION_PORT(thread)); + mach_lisp_thread_init(thread); #endif #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK @@ -116,16 +120,10 @@ int arch_os_thread_cleanup(struct thread *thread) { #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER -void sigill_handler(int signal, siginfo_t *siginfo, void *void_context); -void sigtrap_handler(int signal, siginfo_t *siginfo, void *void_context); -void memory_fault_handler(int signal, siginfo_t *siginfo, void *void_context); - -/* exc_server handles mach exception messages from the kernel and - * calls catch exception raise. We use the system-provided - * mach_msg_server, which, I assume, calls exc_server in a loop. - * - */ -extern boolean_t exc_server(); +void sigill_handler(int signal, siginfo_t *siginfo, os_context_t *context); +void sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context); +void memory_fault_handler(int signal, siginfo_t *siginfo, + os_context_t *context); /* This executes in the faulting thread as part of the signal * emulation. It is passed a context with the uc_mcontext field @@ -254,18 +252,10 @@ void signal_emulation_wrapper(x86_thread_state32_t *thread_state, */ os_context_t *context; -#if MAC_OS_X_VERSION_10_5 - struct __darwin_mcontext32 *regs; -#else - struct mcontext *regs; -#endif + mcontext_t *regs; context = (os_context_t*) os_validate(0, sizeof(os_context_t)); -#if MAC_OS_X_VERSION_10_5 - regs = (struct __darwin_mcontext32*) os_validate(0, sizeof(struct __darwin_mcontext32)); -#else - regs = (struct mcontext*) os_validate(0, sizeof(struct mcontext)); -#endif + regs = (mcontext_t*) os_validate(0, sizeof(mcontext_t)); context->uc_mcontext = regs; /* when BSD signals are fired, they mask they signals in sa_mask @@ -278,22 +268,18 @@ void signal_emulation_wrapper(x86_thread_state32_t *thread_state, build_fake_signal_context(context, thread_state, float_state); - block_blockable_signals(); + block_blockable_signals(0, 0); handler(signal, siginfo, context); update_thread_state_from_context(thread_state, float_state, context); os_invalidate((os_vm_address_t)context, sizeof(os_context_t)); -#if MAC_OS_X_VERSION_10_5 - os_invalidate((os_vm_address_t)regs, sizeof(struct __darwin_mcontext32)); -#else - os_invalidate((os_vm_address_t)regs, sizeof(struct mcontext)); -#endif + os_invalidate((os_vm_address_t)regs, sizeof(mcontext_t)); /* Trap to restore the signal context. */ - asm volatile ("movl %0, %%eax; movl %1, %%ebx; .long 0xffff0b0f" - : : "r" (thread_state), "r" (float_state)); + asm volatile (".long 0xffff0b0f" + : : "a" (thread_state), "c" (float_state)); } /* Convenience wrapper for the above */ @@ -312,6 +298,7 @@ void call_handler_on_thread(mach_port_t thread, /* Initialize the new state */ new_state = *thread_state; open_stack_allocation(&new_state); + stack_allocate(&new_state, 256); /* Save old state */ save_thread_state = (x86_thread_state32_t *)stack_allocate(&new_state, sizeof(*save_thread_state)); *save_thread_state = *thread_state; @@ -382,19 +369,18 @@ void dump_context(x86_thread_state32_t *thread_state) #endif void -control_stack_exhausted_handler(int signal, siginfo_t *siginfo, void *void_context) { - os_context_t *context = arch_os_get_context(&void_context); +control_stack_exhausted_handler(int signal, siginfo_t *siginfo, + os_context_t *context) { + unblock_signals_in_context_and_maybe_warn(context); arrange_return_to_lisp_function - (context, SymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); + (context, StaticSymbolFunction(CONTROL_STACK_EXHAUSTED_ERROR)); } void -undefined_alien_handler(int signal, siginfo_t *siginfo, void *void_context) { - os_context_t *context = arch_os_get_context(&void_context); - +undefined_alien_handler(int signal, siginfo_t *siginfo, os_context_t *context) { arrange_return_to_lisp_function - (context, SymbolFunction(UNDEFINED_ALIEN_VARIABLE_ERROR)); + (context, StaticSymbolFunction(UNDEFINED_ALIEN_VARIABLE_ERROR)); } kern_return_t @@ -405,7 +391,6 @@ catch_exception_raise(mach_port_t exception_port, exception_data_t code_vector, mach_msg_type_number_t code_count) { - struct thread *th = (struct thread*) exception_port; x86_thread_state32_t thread_state; mach_msg_type_number_t state_count; vm_address_t region_addr; @@ -417,8 +402,12 @@ catch_exception_raise(mach_port_t exception_port, int signal = 0; void (*handler)(int, siginfo_t *, void *) = NULL; siginfo_t siginfo; - kern_return_t ret; + kern_return_t ret, dealloc_ret; + struct thread *th; + + FSHOW((stderr,"/entering catch_exception_raise with exception: %d\n", exception)); + th = *(struct thread**)exception_port; /* Get state and info */ state_count = x86_THREAD_STATE32_COUNT; if ((ret = thread_get_state(thread, @@ -442,36 +431,13 @@ catch_exception_raise(mach_port_t exception_port, } /* At stack guard */ if (os_trunc_to_page(addr) == CONTROL_STACK_GUARD_PAGE(th)) { - protect_control_stack_guard_page_thread(0, th); - protect_control_stack_return_guard_page_thread(1, th); + lower_thread_control_stack_guard_page(th); handler = control_stack_exhausted_handler; break; } /* Return from stack guard */ if (os_trunc_to_page(addr) == CONTROL_STACK_RETURN_GUARD_PAGE(th)) { - protect_control_stack_guard_page_thread(1, th); - protect_control_stack_return_guard_page_thread(0, th); - break; - } - /* Get vm_region info */ - region_addr = (vm_address_t)code_vector[1]; - info_count = VM_REGION_BASIC_INFO_COUNT; - if ((ret = vm_region(mach_task_self(), - ®ion_addr, - ®ion_size, - VM_REGION_BASIC_INFO, - (vm_region_info_t)®ion_info, - &info_count, - ®ion_name))) - lose("vm_region (VM_REGION_BASIC_INFO) failed failed %d\n", ret); - /* Check if still protected */ - if ((region_info.protection & OS_VM_PROT_ALL) == 0) { - /* KLUDGE: - * If two threads fault on the same page, the protection - * is cleared as the first thread runs memory_fault_handler. - * Grep for "not marked as write-protected" in gencgc.c - */ - ret = KERN_SUCCESS; + reset_thread_control_stack_guard_page(th); break; } /* Regular memory fault */ @@ -520,7 +486,7 @@ catch_exception_raise(mach_port_t exception_port, lose("thread_set_state (x86_THREAD_STATE32) failed %d\n", ret); if ((ret = thread_set_state(thread, x86_FLOAT_STATE32, - (thread_state_t)thread_state.EBX, + (thread_state_t)thread_state.ECX, x86_FLOAT_STATE32_COUNT)) != KERN_SUCCESS) lose("thread_set_state (x86_FLOAT_STATE32) failed %d\n", ret); break; @@ -537,117 +503,30 @@ catch_exception_raise(mach_port_t exception_port, siginfo.si_addr = addr; call_handler_on_thread(thread, &thread_state, signal, &siginfo, handler); } - return ret; -} - -void * -mach_exception_handler(void *port) -{ - mach_msg_server(exc_server, 2048, (mach_port_t) port, 0); - /* mach_msg_server should never return, but it should dispatch mach - * exceptions to our catch_exception_raise function - */ - abort(); -} - -#endif - -#ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER - -/* Sets up the thread that will listen for mach exceptions. note that - the exception handlers will be run on this thread. This is - different from the BSD-style signal handling situation in which the - signal handlers run in the relevant thread directly. */ - -mach_port_t mach_exception_handler_port_set = MACH_PORT_NULL; - -pthread_t -setup_mach_exception_handling_thread() -{ - kern_return_t ret; - pthread_t mach_exception_handling_thread = NULL; - pthread_attr_t attr; - - /* allocate a mach_port for this process */ - ret = mach_port_allocate(mach_task_self(), - MACH_PORT_RIGHT_PORT_SET, - &mach_exception_handler_port_set); - - /* create the thread that will receive the mach exceptions */ - - FSHOW((stderr, "Creating mach_exception_handler thread!\n")); - - pthread_attr_init(&attr); - pthread_create(&mach_exception_handling_thread, - &attr, - mach_exception_handler, - (void*) mach_exception_handler_port_set); - pthread_attr_destroy(&attr); - - return mach_exception_handling_thread; -} - -/* tell the kernel that we want EXC_BAD_ACCESS exceptions sent to the - exception port (which is being listened to do by the mach - exception handling thread). */ -kern_return_t -mach_thread_init(mach_port_t thread_exception_port) -{ - kern_return_t ret; - /* allocate a named port for the thread */ - - FSHOW((stderr, "Allocating mach port %x\n", thread_exception_port)); - - ret = mach_port_allocate_name(mach_task_self(), - MACH_PORT_RIGHT_RECEIVE, - thread_exception_port); - if (ret) { - lose("mach_port_allocate_name failed with return_code %d\n", ret); - } - - /* establish the right for the thread_exception_port to send messages */ - ret = mach_port_insert_right(mach_task_self(), - thread_exception_port, - thread_exception_port, - MACH_MSG_TYPE_MAKE_SEND); - if (ret) { - lose("mach_port_insert_right failed with return_code %d\n", ret); - } - ret = thread_set_exception_ports(mach_thread_self(), - EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION, - thread_exception_port, - EXCEPTION_DEFAULT, - THREAD_STATE_NONE); - if (ret) { - lose("thread_set_exception_port failed with return_code %d\n", ret); + dealloc_ret = mach_port_deallocate (current_mach_task, thread); + if (dealloc_ret) { + lose("mach_port_deallocate (thread) failed with return_code %d\n", dealloc_ret); } - ret = mach_port_move_member(mach_task_self(), - thread_exception_port, - mach_exception_handler_port_set); - if (ret) { - lose("mach_port_ failed with return_code %d\n", ret); + dealloc_ret = mach_port_deallocate (current_mach_task, task); + if (dealloc_ret) { + lose("mach_port_deallocate (task) failed with return_code %d\n", dealloc_ret); } return ret; } void -setup_mach_exceptions() { - setup_mach_exception_handling_thread(); - mach_thread_init(THREAD_STRUCT_TO_EXCEPTION_PORT(all_threads)); -} - -pid_t -mach_fork() { - pid_t pid = fork(); - if (pid == 0) { - setup_mach_exceptions(); - return pid; - } else { - return pid; - } +os_restore_fp_control(os_context_t *context) +{ + /* KLUDGE: The x87 FPU control word is some nasty bitfield struct + * thing. Rather than deal with that, just grab it as a 16-bit + * integer. */ + unsigned short fpu_control_word = + *((unsigned short *)&context->uc_mcontext->FS.FPU_FCW); + /* reset exception flags and restore control flags on x87 FPU */ + asm ("fldcw %0" : : "m" (fpu_control_word)); } #endif