X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Flinux-os.c;h=2e582666aa7ebafb874855c27a591159e8b8c6b2;hb=b6a842dc8eb0c3aa0364c26b5b41bfc3b38fef31;hp=fbc888e5579a9806d7c13bbeb34fe5d15df29e15;hpb=60ce532301c8f4b7ed289d049717ee16639bc4d4;p=sbcl.git diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index fbc888e..2e58266 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -52,6 +52,8 @@ #include "gc.h" #if defined LISP_FEATURE_GENCGC #include "gencgc-internal.h" +#else +#include "cheneygc-internal.h" #endif #ifdef LISP_FEATURE_X86 @@ -62,7 +64,7 @@ int personality (unsigned long); size_t os_vm_page_size; -#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_LUTEX) +#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX) #include #include #include @@ -70,39 +72,84 @@ size_t os_vm_page_size; /* values taken from the kernel's linux/futex.h. This header file doesn't exist in userspace, which is our excuse for not grovelling them automatically */ -#define FUTEX_WAIT (0) -#define FUTEX_WAKE (1) +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +/* This is also copied from linux/futex.h so that a binary compiled on + * a not so recent Linux system can still take advantage of private + * futexes when available.*/ +#define FUTEX_WAIT_PRIVATE (0+128) +#define FUTEX_WAKE_PRIVATE (1+128) #define FUTEX_FD (2) #define FUTEX_REQUEUE (3) +/* Not static so that Lisp may query it. */ +boolean futex_private_supported_p; + +static inline int +futex_wait_op() +{ + return (futex_private_supported_p ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT); +} + +static inline int +futex_wake_op() +{ + return (futex_private_supported_p ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE); +} + #define sys_futex sbcl_sys_futex static inline int sys_futex (void *futex, int op, int val, struct timespec *rel) { return syscall (SYS_futex, futex, op, val, rel); } -int -futex_wait(int *lock_word, int oldval) +static void +futex_init() { - int t; - again: - t = sys_futex(lock_word,FUTEX_WAIT,oldval, 0); + int x = 0; + sys_futex(&x, FUTEX_WAIT, 1, 0); + if (errno == ENOSYS) + lose("This version of SBCL is compiled with threading support, but your kernel\n" + "is too old to support this. Please use a more recent kernel or\n" + "a version of SBCL without threading support.\n"); + sys_futex(&x, FUTEX_WAIT_PRIVATE, 1, 0); + if (errno == EWOULDBLOCK) { + futex_private_supported_p = 1; + } else { + futex_private_supported_p = 0; + SHOW("No futex private suppport\n"); + } +} - /* Interrupted FUTEX_WAIT calls may return early. - * - * If someone manages to wake the futex while we're spinning - * around it, we will just return with -1 and errno EWOULDBLOCK, - * because the value has changed, so that's ok. */ - if (t != 0 && errno == EINTR) - goto again; +int +futex_wait(int *lock_word, int oldval, long sec, unsigned long usec) +{ + struct timespec timeout; + int t; - return t; + if (sec<0) { + t = sys_futex(lock_word, futex_wait_op(), oldval, 0); + } + else { + timeout.tv_sec = sec; + timeout.tv_nsec = usec * 1000; + t = sys_futex(lock_word, futex_wait_op(), oldval, &timeout); + } + if (t==0) + return 0; + else if (errno==ETIMEDOUT) + return 1; + else if (errno==EINTR) + return 2; + else + /* EWOULDBLOCK and others, need to check the lock */ + return -1; } int futex_wake(int *lock_word, int n) { - return sys_futex(lock_word,FUTEX_WAKE,n,0); + return sys_futex(lock_word, futex_wake_op(),n,0); } #endif @@ -145,9 +192,6 @@ os_init(char *argv[], char *envp[]) { /* Conduct various version checks: do we have enough mmap(), is * this a sparc running 2.2, can we do threads? */ -#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_LUTEX) - int *futex=0; -#endif struct utsname name; int major_version; int minor_version; @@ -171,13 +215,8 @@ os_init(char *argv[], char *envp[]) #endif } #ifdef LISP_FEATURE_SB_THREAD -#if !defined(LISP_FEATURE_SB_LUTEX) - futex_wait(futex,-1); - if(errno==ENOSYS) { - lose("This version of SBCL is compiled with threading support, but your kernel\n" - "is too old to support this. Please use a more recent kernel or\n" - "a version of SBCL without threading support.\n"); - } +#if !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX) + futex_init(); #endif if(! isnptl()) { lose("This version of SBCL only works correctly with the NPTL threading\n" @@ -185,7 +224,12 @@ os_init(char *argv[], char *envp[]) "LD_ASSUME_KERNEL\n"); } #endif - os_vm_page_size = getpagesize(); + + /* Don't use getpagesize(), since it's not constant across Linux + * kernel versions on some architectures (for example PPC). FIXME: + * possibly the same should be done on other architectures too. + */ + os_vm_page_size = BACKEND_PAGE_BYTES; /* KLUDGE: Disable memory randomization on new Linux kernels * by setting a personality flag and re-executing. (We need @@ -200,7 +244,9 @@ os_init(char *argv[], char *envp[]) /* Some old kernels will apparently lose unsupported personality flags * on exec() */ && ((minor_version == 6 && patch_version >= 11) - || (minor_version > 6))) + || (minor_version > 6) + /* This is what RHEL 3 reports */ + || (minor_version == 4 && patch_version > 20))) || major_version >= 3) { int pers = personality(0xffffffffUL); @@ -360,9 +406,8 @@ is_valid_lisp_addr(os_vm_address_t addr) * page fault on this OS. */ static void -sigsegv_handler(int signal, siginfo_t *info, void* void_context) +sigsegv_handler(int signal, siginfo_t *info, os_context_t *context) { - os_context_t *context = arch_os_get_context(&void_context); os_vm_address_t addr = arch_get_bad_addr(signal, info, context); #ifdef LISP_FEATURE_ALPHA @@ -384,14 +429,10 @@ sigsegv_handler(int signal, siginfo_t *info, void* void_context) #ifdef LISP_FEATURE_GENCGC if (!gencgc_handle_wp_violation(addr)) #else - if (!interrupt_maybe_gc(signal, info, context)) + if (!cheneygc_handle_wp_violation(context, addr)) #endif if (!handle_guard_page_triggered(context, addr)) -#ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK - arrange_return_to_lisp_function(context, SymbolFunction(MEMORY_FAULT_ERROR)); -#else - interrupt_handle_now(signal, info, context); -#endif + lisp_memory_fault_error(context, addr); } void @@ -400,8 +441,6 @@ os_install_interrupt_handlers(void) undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT, sigsegv_handler); #ifdef LISP_FEATURE_SB_THREAD - undoably_install_low_level_interrupt_handler(SIG_INTERRUPT_THREAD, - interrupt_thread_handler); undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC, sig_stop_for_gc_handler); #endif