#include #include "sbcl.h" #include "runtime.h" #include "thread.h" #include "lispregs.h" #if defined(LISP_FEATURE_FREEBSD) #include #endif #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER #include kern_return_t mach_thread_init(mach_port_t thread_exception_port); #endif /* KLUDGE: There is strong family resemblance in the signal context * stuff in FreeBSD and OpenBSD, but in detail they're different in * almost every line of code. It would be nice to find some way to * factor out the commonality better; failing that, it might be best * just to split this generic-BSD code into one variant for each BSD. * * KLUDGE II: this split has begun with the addition of the Darwin BSD * flavour, with the cross-architecture complications that this * entails; unfortunately, currently the situation is worse, not * better, than in the above paragraph. */ #if defined(LISP_FEATURE_FREEBSD) || defined(LISP_FEATURE_DARWIN) os_context_register_t * os_context_register_addr(os_context_t *context, int offset) { switch(offset) { case reg_RAX: return CONTEXT_ADDR_FROM_STEM(rax); case reg_RCX: return CONTEXT_ADDR_FROM_STEM(rcx); case reg_RDX: return CONTEXT_ADDR_FROM_STEM(rdx); case reg_RBX: return CONTEXT_ADDR_FROM_STEM(rbx); case reg_RSP: return CONTEXT_ADDR_FROM_STEM(rsp); case reg_RBP: return CONTEXT_ADDR_FROM_STEM(rbp); case reg_RSI: return CONTEXT_ADDR_FROM_STEM(rsi); case reg_RDI: return CONTEXT_ADDR_FROM_STEM(rdi); case reg_R8: return CONTEXT_ADDR_FROM_STEM(r8); case reg_R9: return CONTEXT_ADDR_FROM_STEM(r9); case reg_R10: return CONTEXT_ADDR_FROM_STEM(r10); case reg_R11: return CONTEXT_ADDR_FROM_STEM(r11); case reg_R12: return CONTEXT_ADDR_FROM_STEM(r12); case reg_R13: return CONTEXT_ADDR_FROM_STEM(r13); case reg_R14: return CONTEXT_ADDR_FROM_STEM(r14); case reg_R15: return CONTEXT_ADDR_FROM_STEM(r15); default: return 0; } } os_context_register_t * os_context_sp_addr(os_context_t *context) { return CONTEXT_ADDR_FROM_STEM(rsp); } os_context_register_t * os_context_pc_addr(os_context_t *context) { return CONTEXT_ADDR_FROM_STEM(rip); } #endif void os_flush_icache(os_vm_address_t address, os_vm_size_t length) { } int arch_os_thread_init(struct thread *thread) { stack_t sigstack; #ifdef LISP_FEATURE_SB_THREAD #ifdef LISP_FEATURE_GCC_TLS current_thread = thread; #else pthread_setspecific(specials,thread); #endif #endif #ifdef LISP_FEATURE_MACH_EXCEPTION_HANDLER mach_thread_init(THREAD_STRUCT_TO_EXCEPTION_PORT(thread)); #endif #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK /* Signal handlers are run on the control stack, so if it is exhausted * we had better use an alternate stack for whatever signal tells us * we've exhausted it */ sigstack.ss_sp=((void *) thread)+dynamic_values_bytes; sigstack.ss_flags=0; sigstack.ss_size = 32*SIGSTKSZ; sigaltstack(&sigstack,0); #endif return 1; /* success */ } int arch_os_thread_cleanup(struct thread *thread) { return 1; /* success */ } #if defined(LISP_FEATURE_FREEBSD) void os_restore_fp_control(os_context_t *context) { struct envxmm *ex = (struct envxmm*)(&context->uc_mcontext.mc_fpstate); /* reset exception flags and restore control flags on SSE2 FPU */ unsigned int temp = (ex->en_mxcsr) & ~0x3F; asm ("ldmxcsr %0" : : "m" (temp)); /* same for x87 FPU. */ asm ("fldcw %0" : : "m" (ex->en_cw)); } #endif