0.9.13.26: Life after heap exhaustion on GENCGC
[sbcl.git] / src / runtime / linux-os.c
index 85221c5..faf1a47 100644 (file)
 #include "runtime.h"
 #include "genesis/static-symbols.h"
 #include "genesis/fdefn.h"
+
 #include <sys/socket.h>
 #include <sys/utsname.h>
+#include <errno.h>
 
 #include <sys/types.h>
 #include <signal.h>
@@ -60,7 +62,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_LUTEX)
 #include <sys/syscall.h>
 #include <unistd.h>
 #include <errno.h>
@@ -95,7 +97,6 @@ futex_wake(int *lock_word, int n)
 
 \f
 int linux_sparc_siginfo_bug = 0;
-int linux_no_threads_p = 0;
 
 #ifdef LISP_FEATURE_SB_THREAD
 int
@@ -118,20 +119,23 @@ 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
+#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_LUTEX)
     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);
     if (major_version<2) {
-        lose("linux kernel version too old: major version=%d (can't run in version < 2.0.0)",
+        lose("linux kernel version too old: major version=%d (can't run in version < 2.0.0)\n",
              major_version);
     }
     if (!(major_version>2 || minor_version >= 4)) {
@@ -141,13 +145,18 @@ 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 is too old to support this.\n\
-Please use a more recent kernel or a version of SBCL without threading support.\n");
+       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");
     }
+#endif
     if(! isnptl()) {
-       lose("This version of SBCL only works correctly with the NPTL threading library. Please use a newer glibc, use an older SBCL, or stop using LD_ASSUME_KERNEL");
+       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();
@@ -161,7 +170,11 @@ Please use a more recent kernel or a version of SBCL without threading support.\
      * don't do this trick on other platforms.
      */
 #ifdef LISP_FEATURE_X86
-    if ((major_version == 2 && minor_version >= 6)
+    if ((major_version == 2
+         /* Some old kernels will apparently lose unsupported personality flags
+          * on exec() */
+         && ((minor_version == 6 && patch_version >= 11)
+             || (minor_version > 6)))
         || major_version >= 3)
     {
         int pers = personality(0xffffffffUL);
@@ -198,6 +211,10 @@ Please use a more recent kernel or a version of SBCL without threading support.\
             fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n");
         }
     }
+    /* 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
 }
 
@@ -260,7 +277,7 @@ os_map(int fd, int offset, os_vm_address_t addr, os_vm_size_t len)
                   fd, (off_t) offset);
     if (actual == MAP_FAILED || (addr && (addr != actual))) {
         perror("mmap");
-        lose("unexpected mmap(..) failure");
+        lose("unexpected mmap(..) failure\n");
     }
 
     return actual;
@@ -270,7 +287,14 @@ 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");
+        if (errno == ENOMEM) {
+            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'.");
+        } else {
+            perror("mprotect");
+        }
     }
 }
 \f
@@ -356,3 +380,18 @@ os_install_interrupt_handlers(void)
                                                  sig_stop_for_gc_handler);
 #endif
 }
+
+char *
+os_get_runtime_executable_path()
+{
+    char path[PATH_MAX + 1];
+    int size;
+
+    size = readlink("/proc/self/exe", path, sizeof(path)-1);
+    if (size < 0)
+        return NULL;
+    else
+        path[size] = '\0';
+
+    return copied_string(path);
+}