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
No related branches found
No related tags found
No related merge requests found
......@@ -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,6 +682,9 @@ 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)) {
/* 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)) {
......@@ -692,10 +693,15 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now)
}
}
}
}
list_for_each_entry_safe(t, tmp, &tq[cpu].run, node) {
if (t->state == TASK_BUSY)
continue;
if (ktime_before (t->wakeup, now))
continue;
/* if the relative deadline of task-to-wake can fit in between the unused
* timeslice of this running task, insert after the next wakeup
*/
......@@ -714,6 +720,7 @@ static void edf_wake_next(struct task_queue *tq, int cpu, ktime now)
break;
}
}
}
#endif
task->state = TASK_IDLE;
......@@ -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
}
......
......@@ -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) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment