From 2c56907829598886e58b2ae0c4e178d457fec091 Mon Sep 17 00:00:00 2001
From: Tobias Bouschen <tobias.bouschen@googlemail.com>
Date: Wed, 20 Mar 2019 11:39:39 +0100
Subject: [PATCH] Fix reading performance counter and returning correct task

---
 kernel/sched/pb.c                   | 35 +++++++++++++++++++----------
 kernel/sched/perf_error_detection.c | 15 +++++++------
 kernel/sched/perf_error_detection.h |  4 +++-
 3 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/kernel/sched/pb.c b/kernel/sched/pb.c
index ef82c517a410..b2a559fd3a4f 100644
--- a/kernel/sched/pb.c
+++ b/kernel/sched/pb.c
@@ -122,17 +122,25 @@ static struct task_struct * pick_next_task_pb(struct rq *rq,
 	if (next_mode == PB_EXEC_MODE)
 	{
 		if (current_mode == PB_EXEC_MODE){
-			/*
-			 * !!! perf_counter contains return value of perf_event_release_kernel(), not the event counter !!!
-			 */
-			// u64 pevent_cntval;
-			int perf_counter = terminate_perf_event(pb->pevent, pb->plan[pb->c_entry].task_id /*, &pevent_cntval */);
-			//error detection
+			u64 perf_counter;
+			u64 read_error = get_perf_counter(pb->pevent, &perf_counter);
+
+			//TODO error handling
+
+			terminate_perf_event(pb->pevent);
 
 			if (perf_counter < pb->plan[pb->c_entry].n_instr){
-			// if (pevent_cntval < pb->plan[pb->c_entry].n_instr){
-				printk(KERN_WARNING "PB TASK %llu RAN TOO SHORT\n",pb->plan[pb->c_entry].task_id);
+				u64 under_time = pb->plan[pb->c_entry].n_instr - perf_counter;
+
+				printk(KERN_WARNING "PB TASK %llu RAN  %llu INSTRUCTIONS TOO SHORT\n", pb->plan[pb->c_entry].task_id, under_time);
+
+			} else if (perf_counter > pb->plan[pb->c_entry].n_instr){
+				u64 under_time = perf_counter - pb->plan[pb->c_entry].n_instr;
+
+				printk(KERN_WARNING "PB TASK %llu  RAN %llu INSTRUCTIONS TOO LONG\n", pb->plan[pb->c_entry].task_id, under_time);
 			}
+
+
 			pb->c_entry++;
 			if (pb->c_entry >= pb->size){
 				printk(KERN_DEBUG "PLAN DONE\n");
@@ -149,7 +157,8 @@ static struct task_struct * pick_next_task_pb(struct rq *rq,
 			}
 		}else if(current_mode == PB_ADMIN_MODE){
 			printk(KERN_DEBUG "PB ADMIN,STOP,%u,%llu\n", pb->c_entry, sched_clock());
-		}else{	// PB_DISABLED_MODE
+		}else{
+			// PB_DISABLED_MODE
 			int perf_init_res = init_perf_event(pb->plan[pb->c_entry], &pb->pevent);
 
 			if(perf_init_res < 0){
@@ -160,9 +169,11 @@ static struct task_struct * pick_next_task_pb(struct rq *rq,
 
 			}
 		}
-		//TODO: pick next task from taskarray
-		picked = pb->proxy_task;
-		//TODO: call papi handler------------------------------------
+
+		if (pb->mode != PB_DISABLED_MODE){
+			// Return current task from plan if plan is enabled
+			picked = pb->plan_entry[pb->c_entry]->task_struct;
+		}
 	}
 
 	if (current_mode != next_mode){
diff --git a/kernel/sched/perf_error_detection.c b/kernel/sched/perf_error_detection.c
index 68b46e2776b6..e3b44eefd97e 100644
--- a/kernel/sched/perf_error_detection.c
+++ b/kernel/sched/perf_error_detection.c
@@ -42,17 +42,18 @@ int init_perf_event(struct plan_entry plan_entry, struct perf_event **pevent){
 	return 0;
 }
 
-//terminate perf event - return performance counter value
+
 /*
- * TODO: return the event counter value
- *
+ * Must not be called after the event is terminated.
  */
-long long terminate_perf_event(struct perf_event *pevent, u64 task_id /*, u64 *pevent_cntval */){
+u64 get_perf_counter(struct perf_event *pevent, u64 *perf_counter)
+{
+	return perf_event_read_local(pevent, perf_counter);
+}
 
-	// TODO:
-	// *pevent_cntval = get the counter value here
+u64 terminate_perf_event(struct perf_event *pevent)
+{
 	return perf_event_release_kernel(pevent);
-
 }
 
 
diff --git a/kernel/sched/perf_error_detection.h b/kernel/sched/perf_error_detection.h
index 06b0767616b0..ae6a341a4432 100644
--- a/kernel/sched/perf_error_detection.h
+++ b/kernel/sched/perf_error_detection.h
@@ -12,7 +12,9 @@
 
 int init_perf_event(struct plan_entry, struct perf_event **pevent);
 
-long long terminate_perf_event(struct perf_event *pevent, u64 task_id);
+u64 get_perf_counter(struct perf_event *pevent, u64 *perf_counter);
+
+u64 terminate_perf_event(struct perf_event *pevent);
 
 void overflow_handler(
 		struct perf_event *,
-- 
GitLab