X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fbsd-os.c;h=f9cf70c8b92ca088847f2d21a3647e4980d40c48;hb=5de74c72e5a9522c7fdd3dbb31a39641e9de8877;hp=63b28ef652453f239fa6a7f794ebe617aad3b179;hpb=5e1fcdac979db9a6aebe69531229355def8c0f90;p=sbcl.git diff --git a/src/runtime/bsd-os.c b/src/runtime/bsd-os.c index 63b28ef..f9cf70c 100644 --- a/src/runtime/bsd-os.c +++ b/src/runtime/bsd-os.c @@ -32,6 +32,9 @@ #include "interr.h" #include "lispregs.h" #include "thread.h" +#include "runtime.h" +#include "genesis/static-symbols.h" +#include "genesis/fdefn.h" #include #include @@ -47,14 +50,25 @@ os_vm_size_t os_vm_page_size; static void netbsd_init(); #endif /* __NetBSD__ */ - -void os_init(void) + +#ifdef __FreeBSD__ +#include +#include + +static void freebsd_init(); +#endif /* __FreeBSD__ */ + +void +os_init(char *argv[], char *envp[]) { os_vm_page_size = getpagesize(); #ifdef __NetBSD__ netbsd_init(); #endif /* __NetBSD__ */ +#ifdef __FreeBSD__ + freebsd_init(); +#endif /* __FreeBSD__ */ } int *os_context_pc_addr(os_context_t *context) @@ -65,6 +79,8 @@ int *os_context_pc_addr(os_context_t *context) return CONTEXT_ADDR_FROM_STEM(pc); #elif defined __NetBSD__ return CONTEXT_ADDR_FROM_STEM(EIP); +#elif defined(LISP_FEATURE_DARWIN) && defined(LISP_FEATURE_X86) + return CONTEXT_ADDR_FROM_STEM(eip); #elif defined LISP_FEATURE_DARWIN return &context->uc_mcontext->ss.srr0; #else @@ -78,9 +94,9 @@ 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__ || __NetBSD__ || defined LISP_FEATURE_DARWIN +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(LISP_FEATURE_DARWIN) return &context->uc_sigmask; -#elif defined __OpenBSD__ +#elif defined (__OpenBSD__) return &context->sc_mask; #else #error unsupported BSD variant @@ -93,13 +109,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; @@ -109,20 +125,20 @@ 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\n"); } return addr; @@ -132,7 +148,7 @@ 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"); } } @@ -152,12 +168,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; } @@ -175,29 +191,42 @@ is_valid_lisp_addr(os_vm_address_t addr) static void 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__) || defined(__OpenBSD__) || defined(__NetBSD__) - void *fault_addr = siginfo->si_addr; -#elif defined LISP_FEATURE_DARWIN - void *fault_addr = siginfo->si_addr; -#else -#error unsupported BSD variant + os_context_t *context = arch_os_get_context(&void_context); + void *fault_addr = arch_get_bad_addr(signal, siginfo, context); + +#if defined(MEMORY_FAULT_DEBUG) + fprintf(stderr, "Memory fault at: %p, PC: %x\n", fault_addr, *os_context_pc_addr(context)); +#if defined(ARCH_HAS_STACK_POINTER) + fprintf(stderr, "Stack pointer: %x\n", *os_context_sp_addr(context)); +#endif #endif - os_context_t *context = arch_os_get_context(&void_context); - if (!gencgc_handle_wp_violation(fault_addr)) - if(!handle_guard_page_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 + if (!interrupt_maybe_gc_int(signal, siginfo, context)) { + interrupt_handle_now(signal, siginfo, context); + } +#if defined(LISP_FEATURE_DARWIN) + /* Work around G5 bug; fix courtesy gbyers */ + DARWIN_FIX_CONTEXT(context); +#endif +#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); +#ifdef SIG_MEMORY_FAULT2 + undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT2, + memory_fault_handler); +#endif SHOW("leaving os_install_interrupt_handlers()"); } @@ -209,13 +238,13 @@ 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); + if(!handle_guard_page_triggered(context,addr)) + interrupt_handle_now(signal, info, context); /* Work around G5 bug; fix courtesy gbyers */ - sigreturn(void_context); + DARWIN_FIX_CONTEXT(context); } void @@ -223,7 +252,11 @@ 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); + sigsegv_handler); +#ifdef SIG_MEMORY_FAULT2 + undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT2, + sigsegv_handler); +#endif } #endif /* defined GENCGC */ @@ -244,10 +277,10 @@ static void netbsd_init() /* 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"); + 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); @@ -257,14 +290,37 @@ static void netbsd_init() -- 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\ + fprintf (stderr, + "RUNTIME WARNING: unable to raise process data size limit:\n\ %s.\n\ The system may fail to start.\n", - strerror(errno)); + strerror(errno)); } } #endif /* __NetBSD__ */ + +#ifdef __FreeBSD__ +static void freebsd_init() +{ + /* Quote from sbcl-devel (NIIMI Satoshi): "Some OSes, like FreeBSD + * 4.x with GENERIC kernel, does not enable SSE support even on + * SSE capable CPUs". Detect this situation and skip the + * fast_bzero sse/base selection logic that's normally done in + * x86-assem.S. + */ +#ifdef LISP_FEATURE_X86 + size_t len; + int instruction_sse; + + len = sizeof(instruction_sse); + if (sysctlbyname("hw.instruction_sse", &instruction_sse, &len, NULL, 0) == 0 + && instruction_sse != 0) { + /* Use the SSE detector */ + fast_bzero_pointer = fast_bzero_detect; + } +#endif /* LISP_FEATURE_X86 */ +} +#endif /* __FreeBSD__ */ /* threads */ @@ -289,3 +345,45 @@ int arch_os_thread_cleanup(struct thread *thread) { return 1; /* success */ } #endif + +#ifdef LISP_FEATURE_DARWIN +/* defined in ppc-darwin-os.c instead */ +#elif defined(LISP_FEATURE_FREEBSD) +#ifndef KERN_PROC_PATHNAME +#define KERN_PROC_PATHNAME 12 +#endif + +char * +os_get_runtime_executable_path() +{ + char path[PATH_MAX + 1]; + + if (getosreldate() >= 600024) { + /* KERN_PROC_PATHNAME is available */ + size_t len = PATH_MAX + 1; + int mib[4]; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + if (sysctl(mib, 4, &path, &len, NULL, 0) != 0) + return NULL; + } else { + int size; + size = readlink("/proc/curproc/file", path, sizeof(path) - 1); + if (size < 0) + return NULL; + path[size] = '\0'; + } + if (strcmp(path, "unknown") == 0) + return NULL; + return copied_string(path); +} +#else /* Not DARWIN or FREEBSD */ +char * +os_get_runtime_executable_path() +{ + return NULL; +} +#endif