X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Flinux-os.c;h=a23bc5ddb306a113a74356164bb616092ea49669;hb=f0cb0cf9c0fe1b6fce5d10dbd34a0b7b249c4ae8;hp=151aea0e7099c82a374412dd2f44e1794f8fa629;hpb=79578c137282cc8fa8eb34112915dc17a3855224;p=sbcl.git diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 151aea0..a23bc5d 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -55,6 +55,10 @@ #else #include "cheneygc-internal.h" #endif +#include +#ifdef LISP_FEATURE_SB_WTIMER +# include +#endif #ifdef LISP_FEATURE_X86 /* Prototype for personality(2). Done inline here since the header file @@ -269,7 +273,9 @@ os_init(char *argv[], char *envp[]) * 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 @@ -278,15 +284,21 @@ os_init(char *argv[], char *envp[]) 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 @@ -435,6 +447,10 @@ sigsegv_handler(int signal, siginfo_t *info, os_context_t *context) } #endif +#ifdef LISP_FEATURE_SB_SAFEPOINT + if (!handle_safepoint_violation(context, addr)) +#endif + #ifdef LISP_FEATURE_GENCGC if (!gencgc_handle_wp_violation(addr)) #else @@ -449,9 +465,18 @@ os_install_interrupt_handlers(void) { 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 } @@ -469,3 +494,61 @@ os_get_runtime_executable_path(int external) 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