From 0582049eb884469ad8e7b0a0f57317efe7a1f164 Mon Sep 17 00:00:00 2001
From: Luis Gerhorst <luis.gerhorst@fau.de>
Date: Mon, 25 Jun 2018 15:51:02 +0200
Subject: [PATCH] Prepare/do/postprocess trigger

---
 arch/arm/measuremore/trigger.c | 129 ++++++++++++++++++++++++++-------
 1 file changed, 102 insertions(+), 27 deletions(-)

diff --git a/arch/arm/measuremore/trigger.c b/arch/arm/measuremore/trigger.c
index 29ed3b0..b1ab2e0 100644
--- a/arch/arm/measuremore/trigger.c
+++ b/arch/arm/measuremore/trigger.c
@@ -139,15 +139,15 @@ enum memo_delay_type {
 static char *delay_type_map_strings[] = {"udelay\n", "usleep_range\n", NULL};
 static enum memo_delay_type delay_type_map[] = {MMDT_UDELAY, MMDT_USLEEP_RANGE};
 
-static const char *option_delay_type_str = "udelay\n";
-static enum memo_delay_type option_delay_type = MMDT_UDELAY;
+static const char *debugfs_delay_type_str = "udelay\n";
+static enum memo_delay_type debugfs_delay_type = MMDT_UDELAY;
 
 static ssize_t delay_type_read(struct file *fp, char __user *user_buffer,
 			      size_t count, loff_t *position)
 {
 	return simple_read_from_buffer(user_buffer, count, position,
-				       option_delay_type_str,
-				       strlen(option_delay_type_str));
+				       debugfs_delay_type_str,
+				       strlen(debugfs_delay_type_str));
 }
 
 static ssize_t delay_type_write(struct file *fp, const char __user *user_buffer,
@@ -161,8 +161,8 @@ static ssize_t delay_type_write(struct file *fp, const char __user *user_buffer,
 
 	for (int i = 0; delay_type_map_strings[i]; i++) {
 		if (strcmp(delay_type_map_strings[i], buf) == 0) {
-			option_delay_type = delay_type_map[i];
-			option_delay_type_str = delay_type_map_strings[i];
+			debugfs_delay_type = delay_type_map[i];
+			debugfs_delay_type_str = delay_type_map_strings[i];
 			return count;
 		}
 	}
@@ -181,7 +181,7 @@ static const struct file_operations debugfs_delay_type_fops = {
  * Vars Exposed Through Sysfs *
  ******************************/
 
-static u64 debugfs_trigger_since_boot = 0;
+static u64 debugfs_do_trigger_since_boot = 0;
 static u64 debugfs_delay_ms = 20;
 static u64 debugfs_reps = 1000;
 static u64 debugfs_cp_capacity = 25;
@@ -226,24 +226,71 @@ static void memo_trigger_interrupt(void)
 	gpio_set_value(GPIO_OUT, 0);
 }
 
-static int memo_trigger(void) {
-	debugfs_trigger_since_boot++;
+enum memo_trigger_state {
+	MMTS_PREPARED,
+	MMTS_DONE,
+	MMTS_POSTPROCESSED
+};
+
+static enum memo_trigger_state current_trigger_state = MMTS_POSTPROCESSED;
+
+/* Prepare Trigger */
+
+static int memo_prepare_trigger(void) {
+	if (current_trigger_state != MMTS_POSTPROCESSED) {
+		return -1;
+	}
+	current_trigger_state = MMTS_PREPARED;
+
+	const unsigned long reps = debugfs_reps;
+	const unsigned long cp_capacity = debugfs_cp_capacity;
+	return memo_start_benchmark(reps, cp_capacity);
+}
+
+static ssize_t prepare_trigger_write(struct file *file, const char __user *addr,
+			     size_t len, loff_t *pos)
+{
+	int err = memo_prepare_trigger();
+	if (err) {
+		pr_err("prepare_trigger failed with error %d\n", err);
+	}
+	return len;
+}
+
+static ssize_t memo_empty_read(struct file *fp, char __user *user_buffer,
+			       size_t count, loff_t *position)
+{
+	return simple_read_from_buffer(user_buffer, count, position, "", 0);
+}
+
+static const struct file_operations prepare_trigger_fops = {
+	.write = prepare_trigger_write,
+	.read = memo_empty_read,
+	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
+};
+
+/* Do Trigger */
+
+static int memo_do_trigger(void) {
+	if (current_trigger_state != MMTS_PREPARED) {
+		return -1;
+	}
+	current_trigger_state = MMTS_DONE;
+
+	debugfs_do_trigger_since_boot++;
 
 	const uint64_t delay_ms = debugfs_delay_ms;
 	const uint64_t delay_us = delay_ms*1000;
 	const uint64_t delay_ns = delay_ms*1000*1000;
 	const unsigned long reps = debugfs_reps;
-	const unsigned long cp_capacity = debugfs_cp_capacity;
 
-	const enum memo_delay_type delay_type_function = option_delay_type;
-	memo_start_benchmark(reps, cp_capacity);
 	for (uint64_t i = 0; i < reps; i++) {
 		memo_start_run();
 		memo_checkpoint("checkpoint_1");
 		memo_checkpoint("checkpoint_2");
 		memo_checkpoint("checkpoint_3");
 		memo_trigger_interrupt();
-		switch (delay_type_function) {
+		switch (debugfs_delay_type) {
 		case MMDT_USLEEP_RANGE:
 			usleep_range(delay_us, delay_us);
 			break;
@@ -256,30 +303,53 @@ static int memo_trigger(void) {
 		}
 		memo_stop_run();
 	}
-	memo_stop_benchmark();
+
 	return 0; /* TODO: Signal error. */
 }
 
-static ssize_t trigger_write(struct file *file, const char __user *addr,
+static ssize_t do_trigger_write(struct file *file, const char __user *addr,
 			     size_t len, loff_t *pos)
 {
-	pr_info("trigger write\n");
-	int err = memo_trigger();
+	int err = memo_do_trigger();
 	if (err) {
-		pr_err("trigger failed with error %d\n", err);
+		pr_err("do_trigger failed with error %d\n", err);
 	}
 	return len;
 }
 
-static ssize_t memo_empty_read(struct file *fp, char __user *user_buffer,
-			       size_t count, loff_t *position)
+/* TODO: Does block when logging in, triggering, logging out, triggering again. */
+static const struct file_operations do_trigger_fops = {
+	.write = do_trigger_write,
+	.read = memo_empty_read,
+	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
+};
+
+/* Postprocess Trigger */
+
+static int memo_postprocess_trigger(void) {
+	if (current_trigger_state != MMTS_DONE) {
+		return -1;
+	}
+	current_trigger_state = MMTS_POSTPROCESSED;
+
+	memo_stop_benchmark();
+	return 0;
+}
+
+static ssize_t postprocess_trigger_write(struct file *file,
+					 const char __user *addr, size_t len,
+					 loff_t *pos)
 {
-	return simple_read_from_buffer(user_buffer, count, position, "", 0);
+
+	int err = memo_postprocess_trigger();
+	if (err) {
+		pr_err("postprocess_trigger failed with error %d\n", err);
+	}
+	return len;
 }
 
-/* TODO: Does block when logging in, triggering, logging out, triggering again. */
-static const struct file_operations trigger_fops = {
-	.write = trigger_write,
+static const struct file_operations postprocess_trigger_fops = {
+	.write = postprocess_trigger_write,
 	.read = memo_empty_read,
 	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
 };
@@ -312,8 +382,8 @@ static int create_files(void)
 
 	debugfs_create_bool("vmalloc_checkpoint_matrix", 0400, memo_root,
 			    &debugfs_vmalloc_cp_matrix);
-	debugfs_create_u64("trigger_since_boot", 0600, memo_root,
-			   &debugfs_trigger_since_boot);
+	debugfs_create_u64("do_trigger_since_boot", 0600, memo_root,
+			   &debugfs_do_trigger_since_boot);
 
 	debugfs_create_u64("delay_ms", 0600, memo_root, &debugfs_delay_ms);
 	debugfs_create_u64("reps", 0600, memo_root, &debugfs_reps);
@@ -331,7 +401,12 @@ static int create_files(void)
 	 * those calls to remove would deadlock. TODO: Not sure whether this is
 	 * the right solution, maybe, to be completely correct, we must use
 	 * debugfs_use_file_start/finish() inside the write function. */
-	debugfs_create_file_unsafe("trigger", 0600, memo_root, NULL, &trigger_fops);
+	debugfs_create_file("prepare_trigger", 0600, memo_root, NULL,
+			    &prepare_trigger_fops);
+	debugfs_create_file("do_trigger", 0600, memo_root, NULL,
+			    &do_trigger_fops);
+	debugfs_create_file_unsafe("postprocess_trigger", 0600, memo_root, NULL,
+				   &postprocess_trigger_fops);
 
 	return 0;
 }
-- 
GitLab