diff options
author | Andrew Waterman <waterman@eecs.berkeley.edu> | 2014-01-26 16:26:39 -0800 |
---|---|---|
committer | Andrew Waterman <waterman@eecs.berkeley.edu> | 2014-01-26 16:26:39 -0800 |
commit | fb3be246718190972e8e30688d64632cbb910329 (patch) | |
tree | 6a1c11b2bec419946c871711dad8c793f9419ed7 /spike/xspike.cc | |
parent | afa56de3d56a00998ce8e7a0f8a73a3996bd1f25 (diff) | |
download | riscv-isa-sim-fb3be246718190972e8e30688d64632cbb910329.zip riscv-isa-sim-fb3be246718190972e8e30688d64632cbb910329.tar.gz riscv-isa-sim-fb3be246718190972e8e30688d64632cbb910329.tar.bz2 |
Eliminate hwacha <-> riscv circular dependence
We now split out the spike executable into another subproject,
which depends on both rocket and hwacha
Diffstat (limited to 'spike/xspike.cc')
-rw-r--r-- | spike/xspike.cc | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/spike/xspike.cc b/spike/xspike.cc new file mode 100644 index 0000000..4331dbe --- /dev/null +++ b/spike/xspike.cc @@ -0,0 +1,102 @@ +// See LICENSE for license details. + +// xspike forks an xterm for spike's target machine console, +// preserving the current terminal for debugging. + +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/wait.h> +#include <cstdio> +#include <climits> +#include <cstring> +#include <stdexcept> + +static pid_t fork_spike(int tty_fd, int argc, char** argv); +static pid_t fork_xterm(int* tty_fd); + +int main(int argc, char** argv) +{ + int tty_fd, wait_status, ret = -1; + pid_t xterm, spike; + + static bool signal_exit = false; + auto handle_signal = [](int) { signal_exit = true; }; + + if ((xterm = fork_xterm(&tty_fd)) < 0) + { + fprintf(stderr, "could not open xterm\n"); + goto out; + } + + signal(SIGINT, handle_signal); + + if ((spike = fork_spike(tty_fd, argc, argv)) < 0) + { + fprintf(stderr, "could not open spike\n"); + goto close_xterm; + } + + while ((ret = waitpid(spike, &wait_status, 0)) < 0) + if (signal_exit) + break; + + if (ret < 0) // signal_exit + kill(spike, SIGTERM); + else + ret = WIFEXITED(wait_status) ? WEXITSTATUS(wait_status) : -1; + +close_xterm: + kill(-xterm, SIGTERM); +out: + return ret; +} + +static pid_t fork_spike(int tty_fd, int argc, char** argv) +{ + pid_t pid = fork(); + if (pid < 0) + return -1; + + if (pid == 0) + { + if (dup2(tty_fd, STDIN_FILENO) < 0 || dup2(tty_fd, STDOUT_FILENO) < 0) + return -1; + execvp("spike", argv); + return -1; + } + + return pid; +} + +static pid_t fork_xterm(int* tty_fd) +{ + static const char cmd[] = "3>&1 xterm -title xspike -e sh -c 'tty 1>&3; termios-xspike'"; + + int fds[2]; + if (pipe(fds) < 0) + return -1; + + pid_t pid = fork(); + if (pid < 0) + return -1; + + if (pid == 0) + { + setpgid(0, 0); + if (dup2(fds[1], STDOUT_FILENO) < 0) + return -1; + execl("/bin/sh", "sh", "-c", cmd, NULL); + return -1; + } + + char tty[NAME_MAX]; + ssize_t ttylen = read(fds[0], tty, sizeof(tty)); + if (ttylen <= 1 || tty[ttylen-1] != '\n') + return -1; + tty[ttylen-1] = '\0'; + if ((*tty_fd = open(tty, O_RDWR)) < 0) + return -1; + + return pid; +} |