cleanup: types in gc_alloc_large
[sbcl.git] / src / runtime / linux-os.c
index 026923a..151aea0 100644 (file)
@@ -34,6 +34,7 @@
 #include "runtime.h"
 #include "genesis/static-symbols.h"
 #include "genesis/fdefn.h"
+
 #include <sys/socket.h>
 #include <sys/utsname.h>
 #include <errno.h>
@@ -51,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
@@ -61,7 +64,7 @@ int personality (unsigned long);
 
 size_t os_vm_page_size;
 
-#ifdef LISP_FEATURE_SB_THREAD
+#if defined(LISP_FEATURE_SB_THREAD) && defined(LISP_FEATURE_SB_FUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
 #include <sys/syscall.h>
 #include <unistd.h>
 #include <errno.h>
@@ -69,33 +72,103 @@ 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);
 }
 
+static void
+futex_init()
+{
+    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");
+    }
+}
+
 int
-futex_wait(int *lock_word, int oldval)
+futex_wait(int *lock_word, int oldval, long sec, unsigned long usec)
 {
-    int t= sys_futex(lock_word,FUTEX_WAIT,oldval, 0);
-    return t;
+  struct timespec timeout;
+  int 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
 
 \f
 int linux_sparc_siginfo_bug = 0;
+
+/* This variable was in real use for a few months, basically for
+ * storing autodetected information about whether the Linux
+ * installation was recent enough to support SBCL threads, and make
+ * some run-time decisions based on that. But this turned out to be
+ * unstable, so now we just flat-out refuse to start on the old installations
+ * when thread support has been compiled in.
+ *
+ * Unfortunately, in the meanwhile Slime started depending on this
+ * variable for deciding which communication style to use. So even
+ * though this variable looks unused, it shouldn't be deleted until
+ * it's no longer used in the versions of Slime that people are
+ * likely to download first. -- JES, 2006-06-07
+ */
 int linux_no_threads_p = 0;
 
 #ifdef LISP_FEATURE_SB_THREAD
@@ -119,21 +192,24 @@ 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? */
-#ifdef LISP_FEATURE_SB_THREAD
-    int *futex=0;
-#endif
     struct utsname name;
     int major_version;
     int minor_version;
     int patch_version;
     char *p;
     uname(&name);
+
     p=name.release;
     major_version = atoi(p);
-    p=strchr(p,'.')+1;
-    minor_version = atoi(p);
-    p=strchr(p,'.')+1;
-    patch_version = atoi(p);
+    minor_version = patch_version = 0;
+    p=strchr(p,'.');
+    if (p != NULL) {
+            minor_version = atoi(++p);
+            p=strchr(p,'.');
+            if (p != NULL)
+                    patch_version = atoi(++p);
+    }
+
     if (major_version<2) {
         lose("linux kernel version too old: major version=%d (can't run in version < 2.0.0)\n",
              major_version);
@@ -145,19 +221,21 @@ os_init(char *argv[], char *envp[])
 #endif
     }
 #ifdef LISP_FEATURE_SB_THREAD
-    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_FUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
+    futex_init();
+#endif
     if(! isnptl()) {
        lose("This version of SBCL only works correctly with the NPTL threading\n"
             "library. Please use a newer glibc, use an older SBCL, or stop using\n"
             "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
@@ -167,12 +245,14 @@ os_init(char *argv[], char *envp[])
      * Since randomization is currently implemented only on x86 kernels,
      * don't do this trick on other platforms.
      */
-#ifdef LISP_FEATURE_X86
+#if defined(LISP_FEATURE_X86) || defined(LISP_FEATURE_X86_64)
     if ((major_version == 2
          /* 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);
@@ -209,11 +289,13 @@ os_init(char *argv[], char *envp[])
             fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n");
         }
     }
+#ifdef LISP_FEATURE_X86
     /* Use SSE detector.  Recent versions of Linux enable SSE support
      * on SSE capable CPUs.  */
     /* FIXME: Are there any old versions that does not support SSE?  */
     fast_bzero_pointer = fast_bzero_detect;
 #endif
+#endif
 }
 
 
@@ -289,7 +371,8 @@ os_protect(os_vm_address_t address, os_vm_size_t length, os_vm_prot_t prot)
             lose("An mprotect call failed with ENOMEM. This probably means that the maximum amount\n"
                  "of separate memory mappings was exceeded. To fix the problem, either increase\n"
                  "the maximum with e.g. 'echo 262144 > /proc/sys/vm/max_map_count' or recompile\n"
-                 "SBCL with a larger value for GENCGC-PAGE-SIZE in 'src/target/parms.lisp'.");
+                 "SBCL with a larger value for GENCGC-CARD-BYTES in\n"
+                 "'src/compiler/target/backend-parms.lisp'.");
         } else {
             perror("mprotect");
         }
@@ -332,9 +415,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
@@ -356,14 +438,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
@@ -372,15 +450,13 @@ 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
 }
 
 char *
-os_get_runtime_executable_path()
+os_get_runtime_executable_path(int external)
 {
     char path[PATH_MAX + 1];
     int size;