X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fruntime%2Fbsd-os.c;h=3199a86ab269cb0ea5be9a3e2a8683a8aa598bfe;hb=79cc569a97e444389350ea3f5b1017374fe16bec;hp=64aba2cd0a569f71d59b3fb0113af6780f9162f6;hpb=3e067c214b51d4800ef1f1e56860d3711900f64d;p=sbcl.git diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index 64aba2c..3199a86 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include "sbcl.h" #include "./signal.h" #include "os.h" #include "arch.h" @@ -28,90 +31,57 @@ #include "interrupt.h" #include "interr.h" #include "lispregs.h" -#include "sbcl.h" #include "thread.h" +#include "runtime.h" +#include "genesis/static-symbols.h" +#include "genesis/fdefn.h" #include #include /* #include */ #include "validate.h" -vm_size_t os_vm_page_size; + +os_vm_size_t os_vm_page_size; +#ifdef __NetBSD__ +#include +#include +#include -/* The different BSD variants have diverged in exactly where they - * store signal context information, but at least they tend to use the - * same stems to name the structure fields, so by using this macro we - * can share a fair amount of code between different variants. */ -#if defined __FreeBSD__ -#define CONTEXT_ADDR_FROM_STEM(stem) &context->uc_mcontext.mc_ ## stem -#elif defined __OpenBSD__ -#define CONTEXT_ADDR_FROM_STEM(stem) &context->sc_ ## stem -#else -#error unsupported BSD variant -#endif - -void -os_init(void) +static void netbsd_init(); +#endif /* __NetBSD__ */ + +void os_init(void) { os_vm_page_size = getpagesize(); -} -/* 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. */ - -int * -os_context_register_addr(os_context_t *context, int offset) -{ - switch(offset) { - case 0: - return CONTEXT_ADDR_FROM_STEM(eax); - case 2: - return CONTEXT_ADDR_FROM_STEM(ecx); - case 4: - return CONTEXT_ADDR_FROM_STEM(edx); - case 6: - return CONTEXT_ADDR_FROM_STEM(ebx); - case 8: - return CONTEXT_ADDR_FROM_STEM(esp); - case 10: - return CONTEXT_ADDR_FROM_STEM(ebp); - case 12: - return CONTEXT_ADDR_FROM_STEM(esi); - case 14: - return CONTEXT_ADDR_FROM_STEM(edi); - default: - return 0; - } +#ifdef __NetBSD__ + netbsd_init(); +#endif /* __NetBSD__ */ } -int * -os_context_pc_addr(os_context_t *context) +int *os_context_pc_addr(os_context_t *context) { #if defined __FreeBSD__ return CONTEXT_ADDR_FROM_STEM(eip); #elif defined __OpenBSD__ return CONTEXT_ADDR_FROM_STEM(pc); +#elif defined __NetBSD__ + return CONTEXT_ADDR_FROM_STEM(EIP); +#elif defined LISP_FEATURE_DARWIN + return &context->uc_mcontext->ss.srr0; #else #error unsupported BSD variant #endif } -int * -os_context_sp_addr(os_context_t *context) -{ - return CONTEXT_ADDR_FROM_STEM(esp); -} - sigset_t * os_context_sigmask_addr(os_context_t *context) { /* (Unlike most of the other context fields that we access, the * signal mask field is a field of the basic, outermost context * struct itself both in FreeBSD 4.0 and in OpenBSD 2.6.) */ -#if defined __FreeBSD__ +#if defined __FreeBSD__ || __NetBSD__ || defined LISP_FEATURE_DARWIN return &context->uc_sigmask; #elif defined __OpenBSD__ return &context->sc_mask; @@ -126,13 +96,13 @@ os_validate(os_vm_address_t addr, os_vm_size_t len) int flags = MAP_PRIVATE | MAP_ANON; if (addr) - flags |= MAP_FIXED; + flags |= MAP_FIXED; addr = mmap(addr, len, OS_VM_PROT_ALL, flags, -1, 0); if (addr == MAP_FAILED) { - perror("mmap"); - return NULL; + perror("mmap"); + return NULL; } return addr; @@ -142,39 +112,30 @@ void os_invalidate(os_vm_address_t addr, os_vm_size_t len) { if (munmap(addr, len) == -1) - perror("munmap"); + perror("munmap"); } os_vm_address_t os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len) { addr = mmap(addr, len, - OS_VM_PROT_ALL, - MAP_PRIVATE | MAP_FILE | MAP_FIXED, - fd, (off_t) offset); + OS_VM_PROT_ALL, + MAP_PRIVATE | MAP_FILE | MAP_FIXED, + fd, (off_t) offset); if (addr == MAP_FAILED) { - perror("mmap"); - lose("unexpected mmap(..) failure"); + perror("mmap"); + lose("unexpected mmap(..) failure"); } return addr; } -/* FIXME: If this can be a no-op on BSD/x86, then it - * deserves a more precise name. - * - * (Perhaps os_prepare_data_area_to_be_executed()?) */ -void -os_flush_icache(os_vm_address_t address, os_vm_size_t length) -{ -} - void os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot) { if (mprotect(address, length, prot) == -1) { - perror("mprotect"); + perror("mprotect"); } } @@ -194,12 +155,12 @@ is_valid_lisp_addr(os_vm_address_t addr) if(in_range_p(addr, READ_ONLY_SPACE_START, READ_ONLY_SPACE_SIZE) || in_range_p(addr, STATIC_SPACE_START , STATIC_SPACE_SIZE) || in_range_p(addr, DYNAMIC_SPACE_START , DYNAMIC_SPACE_SIZE)) - return 1; + return 1; for_each_thread(th) { - if((th->control_stack_start <= addr) && (addr < th->control_stack_end)) - return 1; - if(in_range_p(addr, th->binding_stack_start, BINDING_STACK_SIZE)) - return 1; + if((th->control_stack_start <= addr) && (addr < th->control_stack_end)) + return 1; + if(in_range_p(addr, th->binding_stack_start, BINDING_STACK_SIZE)) + return 1; } return 0; } @@ -219,38 +180,96 @@ memory_fault_handler(int signal, siginfo_t *siginfo, void *void_context) { /* The way that we extract low level information like the fault * address is not specified by POSIX. */ -#if defined __FreeBSD__ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) void *fault_addr = siginfo->si_addr; -#elif defined __OpenBSD__ +#elif defined LISP_FEATURE_DARWIN void *fault_addr = siginfo->si_addr; #else #error unsupported BSD variant #endif + os_context_t *context = arch_os_get_context(&void_context); - if (!gencgc_handle_wp_violation(fault_addr)) - if(!handle_control_stack_guard_triggered(context,fault_addr)) - /* FIXME is this context or void_context? not that it */ - /* makes a difference currently except on linux/sparc */ - interrupt_handle_now(signal, siginfo, void_context); + if (!gencgc_handle_wp_violation(fault_addr)) + if(!handle_guard_page_triggered(context,fault_addr)) +#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK + arrange_return_to_lisp_function(context, SymbolFunction(MEMORY_FAULT_ERROR)); +#else + interrupt_handle_now(signal, siginfo, context); +#endif } void os_install_interrupt_handlers(void) { SHOW("os_install_interrupt_handlers()/bsd-os/defined(GENCGC)"); undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT, - memory_fault_handler); + memory_fault_handler); SHOW("leaving os_install_interrupt_handlers()"); } -#else -/* As of 2002.07.31, this configuration has never been tested */ +#else /* Currently Darwin only */ + +static void +sigsegv_handler(int signal, siginfo_t *info, void* void_context) +{ + os_context_t *context = arch_os_get_context(&void_context); + unsigned int pc = (unsigned int *)(*os_context_pc_addr(context)); + os_vm_address_t addr; + + addr = arch_get_bad_addr(signal,info,context); + if(!interrupt_maybe_gc(signal, info, context)) + if(!handle_guard_page_triggered(context,addr)) + interrupt_handle_now(signal, info, context); + /* Work around G5 bug; fix courtesy gbyers */ + DARWIN_FIX_CONTEXT(context); +} + void os_install_interrupt_handlers(void) { SHOW("os_install_interrupt_handlers()/bsd-os/!defined(GENCGC)"); + undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT, + sigsegv_handler); } #endif /* defined GENCGC */ + +#ifdef __NetBSD__ +static void netbsd_init() +{ + struct rlimit rl; + int mib[2], osrev; + size_t len; + + /* Are we running on a sufficiently functional kernel? */ + mib[0] = CTL_KERN; + mib[1] = KERN_OSREV; + + len = sizeof(osrev); + sysctl(mib, 2, &osrev, &len, NULL, 0); + + /* If we're older than 2.0... */ + if (osrev < 200000000) { + fprintf(stderr, "osrev = %d (needed at least 200000000).\n", osrev); + lose("NetBSD kernel too old to run sbcl.\n"); + } + + /* NetBSD counts mmap()ed space against the process's data size limit, + * so yank it up. This might be a nasty thing to do? */ + getrlimit (RLIMIT_DATA, &rl); + /* Amazingly for such a new port, the provenance and meaning of + this number are unknown. It might just mean REALLY_BIG_LIMIT, + or possibly it should be calculated from dynamic space size. + -- CSR, 2004-04-08 */ + rl.rlim_cur = 1073741824; + if (setrlimit (RLIMIT_DATA, &rl) < 0) { + fprintf (stderr, + "RUNTIME WARNING: unable to raise process data size limit:\n\ + %s.\n\ +The system may fail to start.\n", + strerror(errno)); + } +} +#endif /* __NetBSD__ */ /* threads */ @@ -258,9 +277,6 @@ os_install_interrupt_handlers(void) #ifdef LISP_FEATURE_SB_THREAD #error "Define threading support functions" #else -struct thread *arch_os_get_current_thread() { - return all_threads; -} int arch_os_thread_init(struct thread *thread) { stack_t sigstack; #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK