diff --git a/kernel/sched/edf.c b/kernel/sched/edf.c index 1471fcd00f52fdf0907c52e6a3c97e5468403a9d..bc70a099066fb808340b19cc2e69b4a93b6bb5e6 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 231a133baa50865699f739a97864d17494744dfc..9a58e2ecad147060e16288c8a3bc759bb3db7fa6 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) {