Skip to content
Snippets Groups Projects
Commit 698f664b authored by Armin Luntzer's avatar Armin Luntzer
Browse files

* fix buggy EDF queue up

* update EDF unit test
parent 58910c04
Branches
No related tags found
No related merge requests found
...@@ -12,9 +12,8 @@ ...@@ -12,9 +12,8 @@
#include <kernel/tick.h> #include <kernel/tick.h>
#include <generated/autoconf.h> /* XXX need common CPU include */ #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; // ktime now;
char state = 'U'; char state = 'U';
...@@ -24,8 +23,6 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now) ...@@ -24,8 +23,6 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
struct task_struct *tsk; struct task_struct *tsk;
struct task_struct *tmp; struct task_struct *tmp;
int cpu = leon3_cpuid();
ktime prev = 0; ktime prev = 0;
ktime prevd = 0; ktime prevd = 0;
...@@ -47,16 +44,18 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now) ...@@ -47,16 +44,18 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
state = 'I'; state = 'I';
if (tsk->state == TASK_RUN) if (tsk->state == TASK_RUN)
state = 'R'; state = 'R';
if (tsk->state == TASK_BUSY)
state = 'B';
if (tsk->slices == 0) if (tsk->slices == 0)
tsk->slices = 1; 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", 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_ms(tsk->deadline), ktime_to_ms(tsk->wakeup), state, ktime_to_us(tsk->deadline), ktime_to_us(tsk->wakeup),
ktime_to_ms(rel_wait), ktime_to_ms(rel_deadline), ktime_to_ms(tsk->runtime), ktime_to_ms(tsk->total), ktime_to_us(rel_wait), ktime_to_us(rel_deadline), ktime_to_us(tsk->runtime), ktime_to_us(tsk->total),
tsk->slices, tsk->name, tsk->slices, tsk->name,
ktime_to_ms(tsk->attr.wcet), ktime_to_us(tsk->attr.wcet),
ktime_to_ms(tsk->total/tsk->slices)); ktime_to_us(tsk->total/tsk->slices));
prev = tsk->wakeup; prev = tsk->wakeup;
prevd = tsk->deadline; prevd = tsk->deadline;
...@@ -100,9 +99,8 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now) ...@@ -100,9 +99,8 @@ void sched_print_edf_list_internal(struct task_queue *tq, ktime now)
* @returns true if can still execute before deadline * @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; int64_t to_deadline;
...@@ -113,7 +111,7 @@ static inline bool schedule_edf_can_execute(struct task_struct *tsk, ktime now) ...@@ -113,7 +111,7 @@ static inline bool schedule_edf_can_execute(struct task_struct *tsk, ktime now)
if (ktime_before(tsk->deadline, now)) { if (ktime_before(tsk->deadline, now)) {
#if 1 #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, 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->runtime, ktime_us_delta(tsk->deadline, now),
tsk->deadline, tsk->wakeup, now, tsk->exec_start); tsk->deadline, tsk->wakeup, now, tsk->exec_start);
...@@ -535,7 +533,7 @@ if (0) ...@@ -535,7 +533,7 @@ if (0)
void kthread_lock(void); void kthread_lock(void);
void kthread_unlock(void); void kthread_unlock(void);
#include <asm/processor.h>
static struct task_struct *edf_pick_next(struct task_queue *tq, int cpu, static struct task_struct *edf_pick_next(struct task_queue *tq, int cpu,
ktime now) ktime now)
{ {
...@@ -577,7 +575,7 @@ static struct task_struct *edf_pick_next(struct task_queue *tq, int cpu, ...@@ -577,7 +575,7 @@ static struct task_struct *edf_pick_next(struct task_queue *tq, int cpu,
BUG(); BUG();
} }
#endif #endif
if (!schedule_edf_can_execute(tsk, now)) { if (!schedule_edf_can_execute(tsk, cpu, now)) {
schedule_edf_reinit_task(tsk, now); schedule_edf_reinit_task(tsk, now);
/* always queue it up at the tail */ /* always queue it up at the tail */
...@@ -684,34 +682,43 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now) ...@@ -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); BUG_ON(task->on_cpu == KTHREAD_CPU_AFFINITY_NONE);
if (!list_empty(&tq[cpu].run)) { 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); /* reorder */
if (ktime_before (t->wakeup, now)) {
if (ktime_before (t->deadline - t->runtime, first->deadline)) { list_for_each_entry_safe(t, tmp, &tq[cpu].run, node) {
list_move(&t->node, &tq[cpu].run); 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 if (t->state == TASK_BUSY)
* timeslice of this running task, insert after the next wakeup continue;
*/
if (task->attr.deadline_rel < ktime_sub(t->deadline, t->wakeup)) {
//last = ktime_add(t->deadline, t->attr.period);
last = t->wakeup;
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 #endif
...@@ -726,6 +733,7 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now) ...@@ -726,6 +733,7 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now)
task->first_wake = task->wakeup; task->first_wake = task->wakeup;
task->first_dead = task->deadline; 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); list_move_tail(&task->node, &tq[cpu].run);
kthread_unlock(); kthread_unlock();
...@@ -742,9 +750,6 @@ static void edf_enqueue(struct task_queue tq[], struct task_struct *task) ...@@ -742,9 +750,6 @@ static void edf_enqueue(struct task_queue tq[], struct task_struct *task)
/* reset runtime to full */ /* reset runtime to full */
task->runtime = task->attr.wcet; task->runtime = task->attr.wcet;
/* XXX */
list_add_tail(&task->node, &tq[leon3_cpuid()].new);
if (task->sched->check_sched_attr(&task->attr)) if (task->sched->check_sched_attr(&task->attr))
return; return;
...@@ -764,7 +769,7 @@ static void edf_enqueue(struct task_queue tq[], struct task_struct *task) ...@@ -764,7 +769,7 @@ static void edf_enqueue(struct task_queue tq[], struct task_struct *task)
#endif #endif
#if 1 #if 1
list_move_tail(&task->node, &tq[cpu].wake); list_add_tail(&task->node, &tq[cpu].wake);
#endif #endif
} }
......
...@@ -36,6 +36,13 @@ int sched_register(struct scheduler *sched) ...@@ -36,6 +36,13 @@ int sched_register(struct scheduler *sched)
{ {
} }
void kthread_lock(void)
{
}
void kthread_unlock(void)
{
}
/* tests */ /* tests */
...@@ -177,7 +184,7 @@ static void sched_edf_create_tasks_test(void) ...@@ -177,7 +184,7 @@ static void sched_edf_create_tasks_test(void)
t->attr.period = us_to_ktime(1000); t->attr.period = us_to_ktime(1000);
t->attr.deadline_rel = us_to_ktime(900); t->attr.deadline_rel = us_to_ktime(900);
t->attr.wcet = us_to_ktime(250); t->attr.wcet = us_to_ktime(250);
edf_enqueue(&t->sched->tq, t); edf_enqueue(t->sched->tq, t);
/* create task 2 */ /* create task 2 */
...@@ -194,7 +201,7 @@ static void sched_edf_create_tasks_test(void) ...@@ -194,7 +201,7 @@ static void sched_edf_create_tasks_test(void)
t->attr.period = us_to_ktime(1500); t->attr.period = us_to_ktime(1500);
t->attr.deadline_rel = us_to_ktime(400); t->attr.deadline_rel = us_to_ktime(400);
t->attr.wcet = us_to_ktime(300); t->attr.wcet = us_to_ktime(300);
edf_enqueue(&t->sched->tq, t); edf_enqueue(t->sched->tq, t);
/* create task 3 */ /* create task 3 */
...@@ -211,7 +218,7 @@ static void sched_edf_create_tasks_test(void) ...@@ -211,7 +218,7 @@ static void sched_edf_create_tasks_test(void)
t->attr.period = us_to_ktime(30); t->attr.period = us_to_ktime(30);
t->attr.deadline_rel = us_to_ktime(20); t->attr.deadline_rel = us_to_ktime(20);
t->attr.wcet = us_to_ktime(10); t->attr.wcet = us_to_ktime(10);
edf_enqueue(&t->sched->tq, t); edf_enqueue(t->sched->tq, t);
/* create task 4 */ /* create task 4 */
t = kmalloc(sizeof(struct task_struct)); t = kmalloc(sizeof(struct task_struct));
...@@ -220,14 +227,14 @@ static void sched_edf_create_tasks_test(void) ...@@ -220,14 +227,14 @@ static void sched_edf_create_tasks_test(void)
t->name = kmalloc(32); t->name = kmalloc(32);
KSFT_ASSERT_PTR_NOT_NULL(t->name); KSFT_ASSERT_PTR_NOT_NULL(t->name);
snprintf(t->name, 32, "task_3"); snprintf(t->name, 32, "task_4");
t->sched = &sched_edf; t->sched = &sched_edf;
t->attr.policy = SCHED_EDF; t->attr.policy = SCHED_EDF;
t->attr.period = us_to_ktime(3000); t->attr.period = us_to_ktime(3000);
t->attr.deadline_rel = us_to_ktime(900); t->attr.deadline_rel = us_to_ktime(900);
t->attr.wcet = us_to_ktime(100); t->attr.wcet = us_to_ktime(100);
edf_enqueue(&t->sched->tq, t); edf_enqueue(t->sched->tq, t);
#endif #endif
...@@ -238,7 +245,8 @@ static void sched_edf_create_tasks_test(void) ...@@ -238,7 +245,8 @@ static void sched_edf_create_tasks_test(void)
* @test sched_edf_create_tasks_test * @test sched_edf_create_tasks_test
*/ */
#define CYCLES 2000000 #define CYCLES 1000000
#define VERBOSE 0
static void sched_edf_schedule_test(void) static void sched_edf_schedule_test(void)
{ {
...@@ -246,6 +254,8 @@ static void sched_edf_schedule_test(void) ...@@ -246,6 +254,8 @@ static void sched_edf_schedule_test(void)
int64_t wake; int64_t wake;
int64_t slice; int64_t slice;
int cpu = 0;
struct task_struct *next = NULL; struct task_struct *next = NULL;
struct task_struct *curr = NULL; struct task_struct *curr = NULL;
...@@ -258,14 +268,18 @@ static void sched_edf_schedule_test(void) ...@@ -258,14 +268,18 @@ static void sched_edf_schedule_test(void)
// printk("started: %lld now %lld\n", curr->exec_start, ktime_get()); // printk("started: %lld now %lld\n", curr->exec_start, ktime_get());
/* remove runtime of slice from curr */ /* remove runtime of slice from curr */
curr->runtime = ktime_sub(curr->runtime, ktime_sub(ktime_get(), curr->exec_start)); curr->runtime = ktime_sub(curr->runtime, ktime_sub(ktime_get(), curr->exec_start));
curr->state = TASK_RUN;
} }
edf_wake_next(&sched_edf.tq); edf_wake_next(sched_edf.tq, cpu, ktime_get());
#if (VERBOSE)
// sched_print_edf_list_internal(&sched_edf.tq, ktime_get()); sched_print_edf_list_internal(sched_edf.tq, cpu, ktime_get());
#endif
next = edf_pick_next(&sched_edf.tq); next = edf_pick_next(sched_edf.tq, cpu, ktime_get());
// sched_print_edf_list_internal(&sched_edf.tq, ktime_get()); #if (VERBOSE)
sched_print_edf_list_internal(sched_edf.tq, cpu, ktime_get());
#endif
if (next) { if (next) {
slice = next->runtime; slice = next->runtime;
...@@ -275,7 +289,7 @@ static void sched_edf_schedule_test(void) ...@@ -275,7 +289,7 @@ static void sched_edf_schedule_test(void)
// printk("Next: NONE\n"); // 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)); // printk("New task ready in %llu\n", ktime_to_us(wake));
if (wake < slice) { if (wake < slice) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment