--- ski-1.3.2/src/itc.c.~1~ 2014-01-27 12:51:31.790027146 +0100 +++ ski-1.3.2/src/itc.c 2014-01-28 10:29:07.082920979 +0100 @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include "itc.h" static unsigned long long itm; @@ -18,10 +21,23 @@ static unsigned long long itc; static struct timeval tv; static int itimer_active; char itc_itimer_fired; +int itc_onalrm_do_write; +int itc_onalrm_read_fd = -1; +static int itc_onalrm_write_fd = -1; static void onalrm(int sig) { itc_itimer_fired = 1; + + if (itc_onalrm_do_write) { + int oerrno; + char c; + + oerrno = errno; + c = 0; + write(itc_onalrm_write_fd, &c, 1); + errno = oerrno; + } } static void itimer_stop(void) @@ -44,7 +60,7 @@ static void itimer_start(void) { unsigned long long ticks, usecs, seconds; struct itimerval itv; - static int catch_sigalrm_done; + static int init_done; itc_itimer_fired = 0; @@ -69,10 +85,29 @@ static void itimer_start(void) itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; - if (!catch_sigalrm_done) { + if (!init_done) { + int pipefd[2]; + int i; struct sigaction act; - catch_sigalrm_done = 1; + if (pipe(pipefd) == -1) { + perror("pipe"); + exit(1); + } + + for (i = 0; i < 2; ++i) { + int flags; + + flags = fcntl(pipefd[i], F_GETFL); + if (flags == -1 + || fcntl(pipefd[i], F_SETFL, flags | O_NONBLOCK) == -1) { + perror("fcntl"); + exit(1); + } + } + + itc_onalrm_write_fd = pipefd[1]; + itc_onalrm_read_fd = pipefd[0]; memset(&act, 0, sizeof act); act.sa_handler = onalrm; @@ -81,6 +116,8 @@ static void itimer_start(void) perror("sigaction"); exit(1); } + + init_done = 1; } itimer_active = 1; --- ski-1.3.2/src/itc.h.~1~ 2014-01-27 12:51:31.790027146 +0100 +++ ski-1.3.2/src/itc.h 2014-01-27 14:10:38.311831156 +0100 @@ -16,4 +16,7 @@ static __inline__ int itc_tick_overflow( return 1; } +extern int itc_onalrm_do_write; +extern int itc_onalrm_read_fd; + #endif /* _SKI_ITC_H */ --- ski-1.3.2/src/linux/syscall-linux.c.~1~ 2014-01-27 12:51:58.660109271 +0100 +++ ski-1.3.2/src/linux/syscall-linux.c 2014-01-28 11:19:41.950285562 +0100 @@ -93,6 +93,7 @@ #include "interruption.h" #include "netdev.h" #include "os_support.h" +#include "itc.h" #if defined NEW_MP # error "not supported" @@ -4360,6 +4361,68 @@ asynckb (int sig) #endif +/* + * Sleep until SIGIO or SIGALRM is received; this relies on + * keyboard/ethernet input being detected via SIGIO, and the + * ITC now being emulated via setitimer() and SIGALRM. + * + * A SIGALRM might be delivered just before we enter the + * blocking (but interruptible) system call. To ensure that + * we notice that SIGALRM, the protocol is: + * + * 1. We set the itc_onalrm_do_write flag to non-zero. + * This informs the ITC SIGALRM handler that it should also + * write a dummy byte to itc_onalrm_write_fd -- the write + * end of a pipe whose read end is itc_onalrm_read_fd. + * (This flag is an optimization, to avoid forcing every + * ITC SIGLARM to write to the pipe.) + * + * 2. We check if an ITC SIGALRM has been received, if so we + * clear itc_onalrm_do_write and don't sleep. + * + * 3. We call select on itc_onalrm_read_fd in a loop until + * it returns success or a non-EINTR errno. + * + * 4. We clear the itc_onalrm_do_write flag. + * + * 5. We empty the pipe. + * + * Any SIGALRM before step 2 is detected by step 2, and any SIGALRM + * after step 2 is detected via the pipe by step 3. + */ +static void +doSSC_HALT_LIGHT (void) +{ + fd_set readfds; + int ret; + + if (itc_onalrm_read_fd < 0) + return; + + FD_ZERO (&readfds); + FD_SET (itc_onalrm_read_fd, &readfds); + + itc_onalrm_do_write = 1; + + if (itc_itimer_fired) { + itc_onalrm_do_write = 0; + return; + } + + do { + ret = select (itc_onalrm_read_fd + 1, &readfds, NULL, NULL, NULL); + } while (ret == -1 && errno == EINTR); + + itc_onalrm_do_write = 0; + + if (ret != -1 && FD_ISSET (itc_onalrm_read_fd, &readfds)) { + char c; + + while (read(itc_onalrm_read_fd, &c, 1) != -1) + ; + } +} + void doSSC (HWORD num, REG arg0, REG arg1, REG arg2, REG arg3, REG *ret) { @@ -4389,6 +4452,10 @@ doSSC (HWORD num, REG arg0, REG arg1, RE progStop ("SSC breakpoint\n"); break; + case SSC_HALT_LIGHT: + doSSC_HALT_LIGHT (); + break; + case SSC_CTL_TRACE: #ifdef TRACE_DAVIDM { --- ski-1.3.2/src/ssc.h.~1~ 2008-02-05 05:11:38.000000000 +0100 +++ ski-1.3.2/src/ssc.h 2014-01-27 12:52:12.250151160 +0100 @@ -28,6 +28,7 @@ #define SSC_STOP 0 +#define SSC_HALT_LIGHT 19 #define SSC_CONSOLE_INIT 20 #define SSC_GETCHAR 21 #define SSC_PUTCHAR 31