X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Flinux-os.c;h=d44f19f4e2fe63f9d06983b0d369c45907d4e15c;hb=94ac5b7c3ff37850210b6fc9a7593cf1c5752993;hp=e5e17c08cccb0d480a595838271dd02196248193;hpb=35e306eeebc40ce947247e3df47a63f47d01734d;p=sbcl.git diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index e5e17c0..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,12 +59,24 @@ 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(); @@ -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,7 +262,7 @@ 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__ @@ -256,16 +272,16 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) 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); @@ -281,7 +297,7 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) while ( ! (CONTROL_STACK_START <= *current_control_frame_pointer && *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); }