X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Flinux-os.c;h=d44f19f4e2fe63f9d06983b0d369c45907d4e15c;hb=1e4629723d19f96d752235ffde34fe58431431ae;hp=3e68e12ca9694dfe8f61e8f9b99b5dfebc7de0fa;hpb=c8322df812da6eb4ef1ae51735b224b2ad0f1503;p=sbcl.git diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 3e68e12..d44f19f 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -48,6 +48,10 @@ size_t os_vm_page_size; #include "gencgc.h" #endif + +#ifdef sparc +int early_kernel = 0; +#endif void os_init(void) { /* Early versions of Linux don't support the mmap(..) functionality @@ -55,17 +59,29 @@ void os_init(void) { struct utsname name; int major_version; +#ifdef sparc + int minor_version; +#endif uname(&name); major_version = atoi(name.release); if (major_version < 2) { lose("linux major version=%d (can't run in version < 2.0.0)", major_version); } +#ifdef sparc + /* KLUDGE: This will break if Linux moves to a uname() version number + * that has more than one digit initially -- CSR, 2002-02-12 */ + minor_version = atoi(name.release+2); + if (minor_version < 4) { + FSHOW((stderr,"linux minor version=%d;\n enabling workarounds for SPARC kernel bugs in signal handling.\n", minor_version)); + early_kernel = 1; + } +#endif } os_vm_page_size = getpagesize(); - /* this could just as well be in arch_init, but it's not */ -#ifdef i386 + /* This could just as well be in arch_init(), but it's not. */ +#ifdef __i386__ SET_FPU_CONTROL_WORD(0x1372|4|8|16|32); /* no interrupts */ #endif } @@ -182,7 +198,7 @@ os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len) MAP_PRIVATE | MAP_FILE | MAP_FIXED, fd, (off_t) offset); - if(addr == MAP_FAILED) { + if (addr == MAP_FAILED) { perror("mmap"); lose("unexpected mmap(..) failure"); } @@ -234,7 +250,7 @@ is_valid_lisp_addr(os_vm_address_t addr) void sigsegv_handler(int signal, siginfo_t *info, void* void_context) { - os_context_t *context = (os_context_t*)void_context; + os_context_t *context = arch_os_get_context(&void_context); void* fault_addr = (void*)context->uc_mcontext.cr2; if (!gencgc_handle_wp_violation(fault_addr)) { interrupt_handle_now(signal, info, void_context); @@ -246,37 +262,42 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) static void sigsegv_handler(int signal, siginfo_t *info, void* void_context) { - os_context_t *context = (os_context_t*)void_context; + os_context_t *context = arch_os_get_context(&void_context); os_vm_address_t addr; -#ifdef i386 +#ifdef __i386__ interrupt_handle_now(signal,contextstruct); #else -#define CONTROL_STACK_TOP (((char*)CONTROL_STACK_START)+CONTROL_STACK_SIZE) + char *control_stack_top = (char*)CONTROL_STACK_START + CONTROL_STACK_SIZE; addr = arch_get_bad_addr(signal,info,context); - if(addr != NULL && + if (addr != NULL && *os_context_register_addr(context,reg_ALLOC) & (1L<<63)){ + /* This is the end of a pseudo-atomic section during which * a signal was received. We must deal with the pending interrupt * (see also interrupt.c, ../code/interrupt.lisp) */ - /* (how we got here: when interrupting, we set bit 63 in * reg_Alloc. At the end of the atomic section we tried to - * write to reg_Alloc, got a SIGSEGV (there's nothing mapped + * write to reg_ALLOC, got a SIGSEGV (there's nothing mapped * there) so ended up here */ *os_context_register_addr(context,reg_ALLOC) -= (1L<<63); interrupt_handle_pending(context); - } else if (addr > CONTROL_STACK_TOP && addr < BINDING_STACK_START) { - fprintf(stderr, "Possible stack overflow at 0x%016lX: CONTROL_STACK_TOP=%lx, BINDING_STACK_START=%lx\n",addr, CONTROL_STACK_TOP,BINDING_STACK_START); - /* try to fix control frame pointer */ + } else if (addr > control_stack_top && addr < BINDING_STACK_START) { + fprintf(stderr, + "Possible stack overflow at 0x%016lX:\n" + "control_stack_top=%lx, BINDING_STACK_START=%lx\n", + addr, + control_stack_top, + BINDING_STACK_START); + /* Try to fix control frame pointer. */ while ( ! (CONTROL_STACK_START <= *current_control_frame_pointer && - *current_control_frame_pointer <= CONTROL_STACK_TOP)) + *current_control_frame_pointer <= control_stack_top)) ((char*)current_control_frame_pointer) -= sizeof(lispobj); - ldb_monitor(); + monitor_or_something(); } else if (!interrupt_maybe_gc(signal, info, context)) { interrupt_handle_now(signal, info, context); } @@ -284,11 +305,9 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) } #endif - - void os_install_interrupt_handlers(void) { - interrupt_install_low_level_handler(SIGSEGV, sigsegv_handler); + undoably_install_low_level_interrupt_handler(SIGSEGV, sigsegv_handler); }