From 650a0ddc0aa02e3f000100977eac95cef5a695dd Mon Sep 17 00:00:00 2001
From: Ollrogge <nils-ollrogge@outlook.de>
Date: Tue, 13 Sep 2022 17:18:25 +0200
Subject: [PATCH] code cleanup && working pb_submitter

---
 kernel/sched/pb.c                    | 39 ++++++++++--------
 pb_utils/pb_submitter/example_plan   | 10 -----
 pb_utils/pb_submitter/example_run.sh |  2 +-
 pb_utils/pb_submitter/pb_submitter.c | 59 +++++++++++++++++++++-------
 pb_utils/pb_submitter/test_prog.c    |  8 ++--
 5 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/kernel/sched/pb.c b/kernel/sched/pb.c
index 7a180f593fc1..704c6f03da93 100644
--- a/kernel/sched/pb.c
+++ b/kernel/sched/pb.c
@@ -4,11 +4,11 @@
 #include <linux/syscalls.h>
 #include <linux/spinlock.h>
 #include <linux/perf_event.h>
+#include <linux/kthread.h>
 
 typedef struct pb_plan pb_plan_t;
 
 SYSCALL_DEFINE1(pb_set_plan, pb_plan_t __user*, plan) {
-	
 	pb_plan_t _plan;
 	struct task_struct* task;
 	struct rq* rq;
@@ -23,7 +23,6 @@ SYSCALL_DEFINE1(pb_set_plan, pb_plan_t __user*, plan) {
 	copied = copy_from_user(&_plan, plan, sizeof(pb_plan_t));
 	
 	if (copied != 0) {
-		printk("copy_from_user pb_plan failed \n");
 		return -1;
 	}
 
@@ -45,14 +44,13 @@ SYSCALL_DEFINE1(pb_set_plan, pb_plan_t __user*, plan) {
 	task = find_task_by_vpid(_plan.pid);
 
 	if (!task) {
-		printk("!task\n");
 		return -1;
 	}
 
-	task->sched_class = &pb_sched_class;
-	
 	rq = this_rq();
 
+	task->sched_class = &pb_sched_class;
+
 	pb_rq = &rq->pb;
 
 	set_pb_plan_size(pb_rq, _plan.num_tasks);
@@ -67,6 +65,8 @@ SYSCALL_DEFINE1(pb_set_plan, pb_plan_t __user*, plan) {
 		);
 	}
 
+	kfree(inst_cnt);
+
 	res = pb_submit_plan(rq);
 
 	if (res == -1) {
@@ -74,10 +74,6 @@ SYSCALL_DEFINE1(pb_set_plan, pb_plan_t __user*, plan) {
 		return res;
 	}
 
-	// TODO:
-	// - perf_event stuff
-	// - syscall for error message retrieval?
-	// - ... 
 	return 0;
 }
 
@@ -96,7 +92,6 @@ int pb_submit_plan(struct rq *rq)
 		return -1;
 	}
 
-
 	int perf_init_res = init_perf_event(&pb->plan[i], &pb->pevent);
 	if(perf_init_res < 0) {
 		//initialization error detection/handling could happen here
@@ -105,7 +100,6 @@ int pb_submit_plan(struct rq *rq)
 		printk(KERN_DEBUG "PB INIT,%u\n", i);
 	}
 
-
 	pb->c_entry = 0;
 	pb->count_pb_cycles = 0;
 	pb->count_admin_cycles = 0;
@@ -143,7 +137,7 @@ EXPORT_SYMBOL(set_pb_plan_entry);
 // called by core.c sched_init
 void init_pb_rq(struct pb_rq *pb_rq)
 {
-	pb_rq->n_pb_cycles = 100;
+	pb_rq->n_pb_cycles = 20;
 	pb_rq->count_pb_cycles = 0;
 	pb_rq->n_admin_cycles = 20;
 	pb_rq->count_admin_cycles = 0;
@@ -189,6 +183,7 @@ static struct task_struct * pick_next_task_pb(struct rq *rq,
 	struct task_struct *picked = NULL;
 	enum pb_mode current_mode, next_mode;
 	struct pb_rq *pb = &(rq->pb);
+	bool premature_finish = false;
 
     unsigned long flags;
 	pb->l_entry = pb->c_entry;
@@ -243,20 +238,30 @@ static struct task_struct * pick_next_task_pb(struct rq *rq,
 		}
 
 		pb->c_entry++;
-		
-		if (pb->c_entry >= pb->size) {
+
+		/**
+		 * Don't schedule a task that is dead. (e.g. plan was incorrect and program finished quicker)
+		 * todo: if we have multiple tasks structs just try the next plan entry
+		 */
+		if (pb->plan[pb->c_entry].task_struct->state == TASK_DEAD) {
+			premature_finish = true;
+		}
+
+		if (pb->c_entry >= pb->size || premature_finish) {
 			raw_spin_lock_irqsave(pb->pb_lock, flags);
 			terminate_perf_event(pb->pevent);
 			raw_spin_unlock_irqrestore(pb->pb_lock, flags);
 			pb->pevent = NULL;
 			// TODO: Check if we have to free the memory or if perf takes care of it
 			// see 'perf_event_release_kernel(struct perf_event *event)' in core.c
-			printk(KERN_DEBUG "PLAN DONE\n");
 			pb->mode = PB_DISABLED_MODE;
+			next_mode = PB_DISABLED_MODE;
+			picked = NULL;
 			pb->is_initialized = 0;
+			printk(KERN_WARNING "PLAN DONE \n");
 		}
 		pb->is_in_critical = false;
-	printk("DONE");
+		printk("DONE");
 	}
 
 	// EXEC Mode is next, so we return our next task to be executed
@@ -300,7 +305,7 @@ static void task_tick_pb(struct rq *rq, struct task_struct *p, int queued)
 	// printk("TICK #%d\n",pb->count_pb_cycles);
 
 	if (determine_next_mode_pb(rq) != PB_EXEC_MODE && pb->mode == PB_EXEC_MODE && !pb->is_preempted && !pb->is_in_critical) {
-		printk("Reschudling in task_tick_pb");
+		//printk("Reschudling in task_tick_pb");
 		if (pb->l_entry != pb->c_entry){
 			// If the currrent task is not the last finished one, that means its unfinished and thus we set the preemtped flag
 			pb->is_preempted = true;
diff --git a/pb_utils/pb_submitter/example_plan b/pb_utils/pb_submitter/example_plan
index d3a1ca1428a9..83181673a10b 100644
--- a/pb_utils/pb_submitter/example_plan
+++ b/pb_utils/pb_submitter/example_plan
@@ -98,13 +98,3 @@
 100000
 100000
 100000
-100000
-100000
-100000
-100000
-100000
-100000
-100000
-100000
-100000
-100000
diff --git a/pb_utils/pb_submitter/example_run.sh b/pb_utils/pb_submitter/example_run.sh
index f4ebc4074e57..380e11c0c248 100755
--- a/pb_utils/pb_submitter/example_run.sh
+++ b/pb_utils/pb_submitter/example_run.sh
@@ -1,3 +1,3 @@
 #!/bin/sh
 
-./pb_submitter test example_plan
+./pb_submitter test_prog example_plan
diff --git a/pb_utils/pb_submitter/pb_submitter.c b/pb_utils/pb_submitter/pb_submitter.c
index 3a677d3c30b6..023146b98c0c 100644
--- a/pb_utils/pb_submitter/pb_submitter.c
+++ b/pb_utils/pb_submitter/pb_submitter.c
@@ -45,7 +45,15 @@ int main(int argc, char** argv)
     FILE *fp;
     char *line = NULL;
     size_t len = 0;
-    ssize_t read;
+    ssize_t cnt;
+    int pipes[0x2];
+
+    ret = pipe(pipes);
+
+    if (ret < 0) {
+        perror("pipe");
+        return -1;
+    }
     
     fp = fopen(argv[2], "r");
     if (fp == NULL) {
@@ -64,9 +72,9 @@ int main(int argc, char** argv)
     }
 
     for (size_t i = 0; i < plan.num_tasks; i++) {
-        read = getline(&line, &len, fp);
+        cnt = getline(&line, &len, fp);
 
-        if (read < 0) {
+        if (cnt < 0) {
             perror("getline");
             return -1;
         }
@@ -83,20 +91,41 @@ int main(int argc, char** argv)
 
     plan.inst_cnt = inst_cnt;
 
-    plan.pid = getpid();
+    printf("Execve: %s \n", argv[1]);
 
-    ret = syscall(PB_SET_PLAN, &plan);
-    if (ret < 0) {
-        puts("PB_SET_PLAN failed");
-        return -1;
-    }
+    pid_t pid = fork();
 
-    char *const args[] = {argv[1], NULL};
-    char *const env[] = {NULL};
-    ret = execve(argv[1], args, env);
-    if (ret < 0) {
-        perror("execve");
-        return -1;
+    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;
diff --git a/pb_utils/pb_submitter/test_prog.c b/pb_utils/pb_submitter/test_prog.c
index 07e16b3618d0..3c28f823f380 100644
--- a/pb_utils/pb_submitter/test_prog.c
+++ b/pb_utils/pb_submitter/test_prog.c
@@ -1,18 +1,18 @@
 #include <stdio.h>
+#include <unistd.h>
 
 int main(void)
 {
+    sleep(1);
     unsigned int c = 0;
-    // printk(KERN_WARNING "Hello from Module.\n");
     int a = 0;
     int b = 0;
-    // printk(KERN_WARNING "A.\n");
     for (;b < 100; b++) {
+      // check if program runs && syscall to switch tasks
+      puts("loop");
       for (;a < 100000; a++){asm("");}
     }
-    // printk(KERN_WARNING "B.\n");
     c++;
-    // printk(KERN_WARNING "Bye from module.\n");
     return 0;
 }
 
-- 
GitLab