Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
pb_submitter.c 2.29 KiB
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>

#define PB_SET_PLAN 0x1337

typedef struct {
 	    pid_t pid;
        uint64_t *inst_cnt;
        size_t num_tasks;
} pb_plan_t;

static void usage(void)
{
    puts("Usage: ./pb_submitter <prog_name> <plan_file>");
}

static size_t count_lines(FILE *fp)
{
    char c;
    size_t lines = 0;
    while (!feof(fp)) {
        c = fgetc(fp);
        if (c == '\n') {
            lines++;
        }
    }

    rewind(fp);

    return lines;
}

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;
    }

    fp = fopen(argv[2], "r");
    if (fp == NULL) {
        usage();
        return -1;
    }

    plan.num_tasks = count_lines(fp);

    uint64_t* inst_cnt = calloc(plan.num_tasks, sizeof(uint64_t));
    if (inst_cnt == NULL) {
        perror("calloc");
        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);
        if (ret < 0) {
            perror("execve");
            return -1;
        }
    }
    else {
        /**
         * Wait for execve of child to finish else pb cycles are wasted inside
         * the execve function.
         *
         * todo: find better method to do this
         */
        sleep(0x1);
        char c;
        read(pipes[0x0], &c, sizeof(char));

        plan.pid = pid;

        ret = syscall(PB_SET_PLAN, &plan);

        if (ret < 0) {
            puts("PB_SET_PLAN failed");
            return -1;
        }
    }

    return 0;
}