diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index b7adbd31d6b2688490cbcdc597fe663d5955f7da..2d1cdb3917184c7ae713849af6b1343239595f1f 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -208,7 +208,7 @@ extern struct trace_event_functions exit_syscall_print_funcs; static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)) -asmlinkage long sys_pb_set_plan(struct pb_plan __user *plan); +asmlinkage long sys_pb_set_plan(pid_t reference_proc_pid); asmlinkage long sys_pbm_set_root_proc(void); asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr); diff --git a/kernel/sched/pb.c b/kernel/sched/pb.c index 06059907d6075a308f8e3e6bec5ed3ea9e09ca54..f01375d73a0bd6e0375548e31a2ec1ce353ce974 100644 --- a/kernel/sched/pb.c +++ b/kernel/sched/pb.c @@ -9,8 +9,7 @@ typedef struct pb_plan pb_plan_t; -SYSCALL_DEFINE1(pb_set_plan, pb_plan_t __user*, plan) { - pb_plan_t _plan; +SYSCALL_DEFINE1(pb_set_plan, pid_t, reference_proc_pid) { struct task_struct* task; struct rq* rq; struct pb_rq* pb_rq; diff --git a/pb_utils/pb_submitter/pb_submitter.c b/pb_utils/pb_submitter/pb_submitter.c index 04856044452683865a931a55cdb017b476987f20..296c8d011ae287bb91973b2fca0644abc9270fa5 100644 --- a/pb_utils/pb_submitter/pb_submitter.c +++ b/pb_utils/pb_submitter/pb_submitter.c @@ -3,126 +3,116 @@ #include <unistd.h> #include <stdint.h> #include <stdlib.h> +#include <signal.h> +#include <errno.h> // errno #define PB_SET_PLAN 0x1337 +// FIXME DRY with the same struct in sched.h typedef struct { pid_t pid; uint64_t *inst_cnt; size_t num_tasks; + pid_t ref_pid; } pb_plan_t; static void usage(void) { - puts("Usage: ./pb_submitter <prog_name> <plan_file>"); + puts("Usage: echo '<ref_proc_pid>' | ./pb_submitter <prog_name> <prog_arg_0> ..."); } -static size_t count_lines(FILE *fp) +volatile sig_atomic_t stop; + +static void handler(int n) { - char c; - size_t lines = 0; - while (!feof(fp)) { - c = fgetc(fp); - if (c == '\n') { - lines++; - } - } + stop = 1; +} - rewind(fp); +volatile sig_atomic_t stop; - return lines; +static void handler(int n) +{ + stop = 1; } int main(int argc, char** argv) { - if (argc < 0x3) { - usage(); - return -1; - } - int ret; - pb_plan_t plan = { 0 }; - FILE *fp; - char *line = NULL; - size_t len = 0; - ssize_t cnt; - int pipes[0x2]; - - ret = pipe(pipes); - if (ret < 0) { - perror("pipe"); - return -1; - } + pid_t ref_proc; + errno = 0; - fp = fopen(argv[2], "r"); - if (fp == NULL) { + char buf[12]; // large enough buffer for even the largest pid + scanf("%11s", buf); // read what we have in stdin and drop the ending null + if (sscanf(buf, "%u", &ref_proc) != 1) { + printf("Error: Invalid stdin input (pid expected): %s; Errno: \n", strerror(errno)); usage(); return -1; } + printf("Got: %u\n", ref_proc); - plan.num_tasks = count_lines(fp); - - uint64_t* inst_cnt = calloc(plan.num_tasks, sizeof(uint64_t)); - if (inst_cnt == NULL) { - perror("calloc"); + // TODO Add the reference proc pid as argument (arc < 3)? + if (argc < 2) { + usage(); return -1; } - size_t i; - for (i = 0; i < plan.num_tasks; i++) { - cnt = getline(&line, &len, fp); - - if (cnt < 0) { - perror("getline"); - return -1; - } - - uint64_t cnt = strtoull(line, NULL, 10); - - if (inst_cnt == 0) { - puts("Inst_cnt conversion failure"); - return -1; - } - - inst_cnt[i] = cnt; - } - - plan.inst_cnt = inst_cnt; - pid_t pid = fork(); if (pid == 0x0) { - char *const args[] = {argv[1], NULL}; - char *const env[] = {NULL}; - - write(pipes[0x1], "a", sizeof("a")); - - ret = execve(argv[1], args, env); + // drop the first element of argv (the name of this program) so that only + // the name and arguments of the program to run remain + char ** args = &argv[1]; + + puts(" ###### STOP"); + kill(getpid(), SIGTSTP); + puts(" ###### CONTINUE"); + + // replace this process with the chosen program since we want to keep using + // the same PID for simplicity purposes (forking a new process would have + // worked as well but this process is not needed anymore anyways) + ret = execvp(argv[1], args); if (ret < 0) { perror("execve"); return -1; } - } - else { + } else { /** * Wait for execve of child to finish else pb cycles are wasted inside * the execve function. * - * todo: find better method to do this + * Setup a signal handler for the SIGCHLD-Signal that the parent receives when the child is + * stopped (by SIGTSTP) + * + * idea for the signal handler: + * https://stackoverflow.com/questions/40098170/handling-sigtstp-signals-in-c/40116030#40116030 + * idea for using it in combination with pause() instead of wait: + * https://stackoverflow.com/questions/12683466/after-suspending-child-process-with-sigtstp-shell-not-responding/43614414#43614414 */ - sleep(0x1); - char c; - read(pipes[0x0], &c, sizeof(char)); + struct sigaction sa; + sa.sa_handler = handler; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + perror("Couldn't set SIGCHLD handler"); + exit(EXIT_FAILURE); + } + // wait for the child to signal the stop + pause(); - plan.pid = pid; + printf("Selected plan (reference pid): %u, real pid: %u\n", ref_proc, pid); + ret = syscall(PB_SET_PLAN, ref_proc); - ret = syscall(PB_SET_PLAN, &plan); + // continue running the child + kill(pid, SIGCONT); if (ret < 0) { puts("PB_SET_PLAN failed"); return -1; } + + // continue running the child + kill(pid, SIGCONT); } return 0;