#else
#include "cheneygc-internal.h"
#endif
+#include <fcntl.h>
+#ifdef LISP_FEATURE_SB_WTIMER
+# include <sys/timerfd.h>
+#endif
#ifdef LISP_FEATURE_X86
/* Prototype for personality(2). Done inline here since the header file
size_t os_vm_page_size;
-#if defined(LISP_FEATURE_SB_THREAD) && !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
+#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>
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);
#endif
}
#ifdef LISP_FEATURE_SB_THREAD
-#if !defined(LISP_FEATURE_SB_LUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
+#if defined(LISP_FEATURE_SB_FUTEX) && !defined(LISP_FEATURE_SB_PTHREAD_FUTEX)
futex_init();
#endif
if(! isnptl()) {
* 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() */
* in an error or if the value didn't change. Otherwise
* this might result in an infinite loop.
*/
- if (retval != -1 && newpers != pers) {
+
+ if (!getenv("SBCL_IS_RESTARTING") &&
+ retval != -1 && newpers != pers) {
/* Use /proc/self/exe instead of trying to figure out
* the executable path from PATH and argv[0], since
* that's unreliable. We follow the symlink instead of
char runtime[PATH_MAX+1];
int i = readlink("/proc/self/exe", runtime, PATH_MAX);
if (i != -1) {
+ environ = envp;
+ setenv("SBCL_IS_RESTARTING", "T", 1);
runtime[i] = '\0';
- execve(runtime, argv, envp);
+ execv(runtime, argv);
}
}
/* Either changing the personality or execve() failed. Either
* way we might as well continue, and hope that the random
* memory maps are ok this time around.
*/
- fprintf(stderr, "WARNING: Couldn't re-execute SBCL with the proper personality flags (maybe /proc isn't mounted?). Trying to continue anyway.\n");
+ fprintf(stderr, "WARNING:\
+\nCouldn't re-execute SBCL with proper personality flags (/proc isn't mounted? setuid?)\
+\nTrying to continue anyway.\n");
+ } else {
+ unsetenv("SBCL_IS_RESTARTING");
}
}
+#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
}
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-BYTES in\n"
+ "SBCL with a larger value for GENCGC-CARD-BYTES in\n"
"'src/compiler/target/backend-parms.lisp'.");
} else {
perror("mprotect");
}
#endif
+#ifdef LISP_FEATURE_SB_SAFEPOINT
+ if (!handle_safepoint_violation(context, addr))
+#endif
+
#ifdef LISP_FEATURE_GENCGC
if (!gencgc_handle_wp_violation(addr))
#else
{
undoably_install_low_level_interrupt_handler(SIG_MEMORY_FAULT,
sigsegv_handler);
+
+ /* OAOOM c.f. sunos-os.c.
+ * Should we have a reusable function gc_install_interrupt_handlers? */
#ifdef LISP_FEATURE_SB_THREAD
+# ifdef LISP_FEATURE_SB_SAFEPOINT
+# ifdef LISP_FEATURE_SB_THRUPTION
+ undoably_install_low_level_interrupt_handler(SIGPIPE, thruption_handler);
+# endif
+# else
undoably_install_low_level_interrupt_handler(SIG_STOP_FOR_GC,
sig_stop_for_gc_handler);
+# endif
#endif
}
char *
-os_get_runtime_executable_path()
+os_get_runtime_executable_path(int external)
{
char path[PATH_MAX + 1];
int size;
return copied_string(path);
}
+
+#ifdef LISP_FEATURE_SB_WTIMER
+/*
+ * Waitable timer implementation for the safepoint-based (SIGALRM-free)
+ * timer facility using timerfd_create().
+ */
+int
+os_create_wtimer()
+{
+ int fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ if (fd == -1)
+ lose("os_create_wtimer: timerfd_create");
+
+ /* Cannot count on TFD_CLOEXEC availability, so do it manually: */
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+ lose("os_create_wtimer: fcntl");
+
+ return fd;
+}
+
+int
+os_wait_for_wtimer(int fd)
+{
+ unsigned char buf[8];
+ int n = read(fd, buf, sizeof(buf));
+ if (n == -1) {
+ if (errno == EINTR)
+ return -1;
+ lose("os_wtimer_listen failed");
+ }
+ if (n != sizeof(buf))
+ lose("os_wtimer_listen read too little");
+ return 0;
+}
+
+void
+os_close_wtimer(int fd)
+{
+ if (close(fd) == -1)
+ lose("os_close_wtimer failed");
+}
+
+void
+os_set_wtimer(int fd, int sec, int nsec)
+{
+ struct itimerspec spec = { {0,0}, {0,0} };
+ spec.it_value.tv_sec = sec;
+ spec.it_value.tv_nsec = nsec;
+ if (timerfd_settime(fd, 0, &spec, 0) == -1)
+ lose("timerfd_settime");
+}
+
+void
+os_cancel_wtimer(int fd)
+{
+ os_set_wtimer(fd, 0, 0);
+}
+#endif