From 698f664b1693ed5873c016961da9ec24c9bc3e63 Mon Sep 17 00:00:00 2001
From: Armin Luntzer <armin.luntzer@univie.ac.at>
Date: Tue, 15 Oct 2019 15:29:23 +0200
Subject: [PATCH] * fix buggy EDF queue up * update EDF unit test

---
 kernel/sched/edf.c                    | 81 ++++++++++++++-------------
 tools/testing/unittest/edf/edf_test.c | 38 +++++++++----
 2 files changed, 69 insertions(+), 50 deletions(-)

diff --git a/kernel/sched/edf.c b/kernel/sched/edf.c
index 1471fcd..bc70a09 100644
--- a/kernel/sched/edf.c
+++ b/kernel/sched/edf.c
@@ -12,9 +12,8 @@
 #include <kernel/tick.h>
 
 #include <generated/autoconf.h> /* XXX need common CPU include */
-#include <asm/processor.h>
 
-void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
+void sched_print_edf_list_internal(struct task_queue *tq, int cpu, ktime now)
 {
 //	ktime now;
 	char state = 'U';
@@ -24,8 +23,6 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
 	struct task_struct *tsk;
 	struct task_struct *tmp;
 
-	int cpu = leon3_cpuid();
-
 
 	ktime prev = 0;
 	ktime prevd = 0;
@@ -47,16 +44,18 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
 			state = 'I';
 		if (tsk->state == TASK_RUN)
 			state = 'R';
+		if (tsk->state == TASK_BUSY)
+			state = 'B';
 
 		if (tsk->slices == 0)
 			tsk->slices = 1;
 
-		printk("%c\t%lld\t%lld\t\t%lld\t%lld\t%lld\t%lld\t%d\t%s\t|\t%lld\t%lld\n",
-		       state, ktime_to_ms(tsk->deadline), ktime_to_ms(tsk->wakeup),
-		       ktime_to_ms(rel_wait), ktime_to_ms(rel_deadline), ktime_to_ms(tsk->runtime), ktime_to_ms(tsk->total),
+		printk("%c\t%lld\t\t%lld\t\t%lld\t%lld\t%lld\t%lld\t%d\t%s\t|\t%lld\t%lld\n",
+		       state, ktime_to_us(tsk->deadline), ktime_to_us(tsk->wakeup),
+		       ktime_to_us(rel_wait), ktime_to_us(rel_deadline), ktime_to_us(tsk->runtime), ktime_to_us(tsk->total),
 		       tsk->slices, tsk->name,
-		       ktime_to_ms(tsk->attr.wcet),
-		       ktime_to_ms(tsk->total/tsk->slices));
+		       ktime_to_us(tsk->attr.wcet),
+		       ktime_to_us(tsk->total/tsk->slices));
 
 		prev = tsk->wakeup;
 		prevd = tsk->deadline;
@@ -100,9 +99,8 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
  * @returns true if can still execute before deadline
  */
 
-static inline bool schedule_edf_can_execute(struct task_struct *tsk, ktime now)
+static inline bool schedule_edf_can_execute(struct task_struct *tsk, int cpu, ktime now)
 {
-	int cpu = leon3_cpuid();
 	int64_t to_deadline;
 
 
@@ -113,7 +111,7 @@ static inline bool schedule_edf_can_execute(struct task_struct *tsk, ktime now)
 
 	if (ktime_before(tsk->deadline, now))  {
 #if 1
-		sched_print_edf_list_internal(&tsk->sched->tq[cpu], now);
+		sched_print_edf_list_internal(&tsk->sched->tq[cpu], cpu, now);
 		printk("%s violated, %lld %lld, dead %lld wake %lld now %lld start %lld\n", tsk->name,
 		       tsk->runtime, ktime_us_delta(tsk->deadline, now),
 		       tsk->deadline, tsk->wakeup, now, tsk->exec_start);
@@ -535,7 +533,7 @@ if (0)
 
  void kthread_lock(void);
  void kthread_unlock(void);
-#include <asm/processor.h>
+
 static struct task_struct *edf_pick_next(struct task_queue *tq, int cpu,
 					 ktime now)
 {
@@ -577,7 +575,7 @@ static struct task_struct *edf_pick_next(struct task_queue *tq, int cpu,
 				BUG();
 			}
 #endif
-			if (!schedule_edf_can_execute(tsk, now)) {
+			if (!schedule_edf_can_execute(tsk, cpu, now)) {
 				schedule_edf_reinit_task(tsk, now);
 
 				/* always queue it up at the tail */
@@ -684,34 +682,43 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now)
 	BUG_ON(task->on_cpu == KTHREAD_CPU_AFFINITY_NONE);
 
 	if (!list_empty(&tq[cpu].run)) {
-	list_for_each_entry_safe(t, tmp, &tq[cpu].run, node) {
-		first = list_first_entry(&tq[cpu].run, struct task_struct, node);
-		if (ktime_before (t->wakeup, now)) {
-			if (ktime_before (t->deadline - t->runtime, first->deadline)) {
-				list_move(&t->node, &tq[cpu].run);
+
+		/* reorder */
+
+		list_for_each_entry_safe(t, tmp, &tq[cpu].run, node) {
+			first = list_first_entry(&tq[cpu].run, struct task_struct, node);
+			if (ktime_before (t->wakeup, now)) {
+				if (ktime_before (t->deadline - t->runtime, first->deadline)) {
+					list_move(&t->node, &tq[cpu].run);
+				}
 			}
 		}
-	}
-	}
 
-	list_for_each_entry_safe(t, tmp, &tq[cpu].run, node) {
+		list_for_each_entry_safe(t, tmp, &tq[cpu].run, node) {
 
-		/* if the relative deadline of task-to-wake can fit in between the unused
-		 * timeslice of this running task, insert after the next wakeup
-		 */
-		if (task->attr.deadline_rel < ktime_sub(t->deadline, t->wakeup)) {
-		    //last = ktime_add(t->deadline, t->attr.period);
-		    last = t->wakeup;
+			if (t->state == TASK_BUSY)
+				continue;
 
+			if (ktime_before (t->wakeup, now))
+				continue;
 
-		    break;
-		}
+			/* if the relative deadline of task-to-wake can fit in between the unused
+			 * timeslice of this running task, insert after the next wakeup
+			 */
+			if (task->attr.deadline_rel < ktime_sub(t->deadline, t->wakeup)) {
+				//last = ktime_add(t->deadline, t->attr.period);
+				last = t->wakeup;
 
-		if (task->attr.wcet < ktime_sub(t->deadline, t->wakeup)) {
-		    //last = ktime_add(t->deadline, t->attr.period);
-		    last = t->deadline;
 
-		    break;
+				break;
+			}
+
+			if (task->attr.wcet < ktime_sub(t->deadline, t->wakeup)) {
+				//last = ktime_add(t->deadline, t->attr.period);
+				last = t->deadline;
+
+				break;
+			}
 		}
 	}
 #endif
@@ -726,6 +733,7 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now)
 	task->first_wake = task->wakeup;
 	task->first_dead = task->deadline;
 
+	printk("%s now %lld, last %lld, wake at %lld dead at %lld\n", task->name, now, last, task->wakeup, task->deadline);
 
 	list_move_tail(&task->node, &tq[cpu].run);
 	kthread_unlock();
@@ -742,9 +750,6 @@ static void edf_enqueue(struct task_queue tq[], struct task_struct *task)
 	/* reset runtime to full */
 	task->runtime = task->attr.wcet;
 
-	/* XXX */
-	list_add_tail(&task->node, &tq[leon3_cpuid()].new);
-
 
 	if (task->sched->check_sched_attr(&task->attr))
 		return;
@@ -764,7 +769,7 @@ static void edf_enqueue(struct task_queue tq[], struct task_struct *task)
 
 #endif
 #if 1
-	list_move_tail(&task->node, &tq[cpu].wake);
+	list_add_tail(&task->node, &tq[cpu].wake);
 #endif
 
 }
diff --git a/tools/testing/unittest/edf/edf_test.c b/tools/testing/unittest/edf/edf_test.c
index 231a133..9a58e2e 100644
--- a/tools/testing/unittest/edf/edf_test.c
+++ b/tools/testing/unittest/edf/edf_test.c
@@ -36,6 +36,13 @@ int sched_register(struct scheduler *sched)
 {
 }
 
+void kthread_lock(void)
+{
+}
+
+void kthread_unlock(void)
+{
+}
 
 /* tests */
 
@@ -177,7 +184,7 @@ static void sched_edf_create_tasks_test(void)
 	t->attr.period       = us_to_ktime(1000);
 	t->attr.deadline_rel = us_to_ktime(900);
 	t->attr.wcet         = us_to_ktime(250);
-	edf_enqueue(&t->sched->tq, t);
+	edf_enqueue(t->sched->tq, t);
 
 
 	/* create task 2 */
@@ -194,7 +201,7 @@ static void sched_edf_create_tasks_test(void)
 	t->attr.period       = us_to_ktime(1500);
 	t->attr.deadline_rel = us_to_ktime(400);
 	t->attr.wcet         = us_to_ktime(300);
-	edf_enqueue(&t->sched->tq, t);
+	edf_enqueue(t->sched->tq, t);
 
 
 	/* create task 3 */
@@ -211,7 +218,7 @@ static void sched_edf_create_tasks_test(void)
 	t->attr.period       = us_to_ktime(30);
 	t->attr.deadline_rel = us_to_ktime(20);
 	t->attr.wcet         = us_to_ktime(10);
-	edf_enqueue(&t->sched->tq, t);
+	edf_enqueue(t->sched->tq, t);
 
 	/* create task 4 */
 	t = kmalloc(sizeof(struct task_struct));
@@ -220,14 +227,14 @@ static void sched_edf_create_tasks_test(void)
 	t->name = kmalloc(32);
 	KSFT_ASSERT_PTR_NOT_NULL(t->name);
 
-	snprintf(t->name, 32, "task_3");
+	snprintf(t->name, 32, "task_4");
 
 	t->sched = &sched_edf;
 	t->attr.policy       = SCHED_EDF;
 	t->attr.period       = us_to_ktime(3000);
 	t->attr.deadline_rel = us_to_ktime(900);
 	t->attr.wcet         = us_to_ktime(100);
-	edf_enqueue(&t->sched->tq, t);
+	edf_enqueue(t->sched->tq, t);
 #endif
 
 
@@ -238,7 +245,8 @@ static void sched_edf_create_tasks_test(void)
  * @test sched_edf_create_tasks_test
  */
 
-#define CYCLES 2000000
+#define CYCLES 1000000
+#define VERBOSE 0
 
 static void sched_edf_schedule_test(void)
 {
@@ -246,6 +254,8 @@ static void sched_edf_schedule_test(void)
 	int64_t wake;
 	int64_t slice;
 
+	int cpu = 0;
+
 	struct task_struct *next = NULL;
 	struct task_struct *curr = NULL;
 
@@ -258,14 +268,18 @@ static void sched_edf_schedule_test(void)
 		//	printk("started: %lld now %lld\n", curr->exec_start, ktime_get());
 			/* remove runtime of slice from curr */
 			curr->runtime = ktime_sub(curr->runtime, ktime_sub(ktime_get(), curr->exec_start));
+			curr->state = TASK_RUN;
 		}
 
-		edf_wake_next(&sched_edf.tq);
-
-	//	sched_print_edf_list_internal(&sched_edf.tq, ktime_get());
+		edf_wake_next(sched_edf.tq, cpu, ktime_get());
+#if (VERBOSE)
+		sched_print_edf_list_internal(sched_edf.tq, cpu, ktime_get());
+#endif
 
-		next = edf_pick_next(&sched_edf.tq);
-	//	sched_print_edf_list_internal(&sched_edf.tq, ktime_get());
+		next = edf_pick_next(sched_edf.tq, cpu, ktime_get());
+#if (VERBOSE)
+		sched_print_edf_list_internal(sched_edf.tq, cpu, ktime_get());
+#endif
 
 		if (next) {
 			slice = next->runtime;
@@ -275,7 +289,7 @@ static void sched_edf_schedule_test(void)
 		//	printk("Next: NONE\n");
 		}
 
-		wake = edf_task_ready_ns(&sched_edf.tq);
+		wake = edf_task_ready_ns(sched_edf.tq, cpu, ktime_get());
 //		printk("New task ready in %llu\n", ktime_to_us(wake));
 
 		if (wake < slice) {
-- 
GitLab