diff --git a/include/kernel/kthread.h b/include/kernel/kthread.h index ab0c7a84ed255491536cf083f8205143d73dbb2b..89598fd0434685d45e757d9bd629c8c19bd3fc0d 100644 --- a/include/kernel/kthread.h +++ b/include/kernel/kthread.h @@ -76,6 +76,8 @@ struct task_struct { */ int unused; + ktime last_visit; + ktime last_adjust; ktime runtime; /* remaining runtime in this period */ ktime wakeup; /* start of next period */ ktime deadline; /* deadline of current period */ diff --git a/init/main.c b/init/main.c index 060710388a1a53103dd5f522d8f6d66bbf43d2cd..d6dc2325f73100a581402efe07c914b927c3b8a4 100644 --- a/init/main.c +++ b/init/main.c @@ -45,7 +45,19 @@ #endif /* GCC_VERSION */ volatile int inc; -volatile int xa, xb, xc; +volatile unsigned int xa, xb, xc, xd; + +int task0(void *data) +{ + while (1) { + + xd++; + + // printk("t1 %d %llu\n", leon3_cpuid(), ktime_to_us(ktime_get())); + // sched_yield(); + } +} + int task1(void *data) { while (1) { @@ -70,12 +82,8 @@ int task2(void *data) // sched_yield(); } } -static int cnt; -static ktime buf[1024]; int task3(void *data) { - ktime last = 0; - while (1) { #if 0 ktime now; @@ -99,14 +107,19 @@ int task3(void *data) } #include <kernel/sysctl.h> extern ktime sched_last_time; + void sched_print_edf_list_internal(struct task_queue *tq, int cpu, ktime now); extern uint32_t sched_ev; -int task0(void *data) + + +extern struct scheduler sched_edf; +int task_rr(void *data) { int last = 0; int curr = 0; char buf1[64]; uint32_t last_call = 0; + int a, b, c, d; ktime sched_time; struct sysobj *sys_irq = NULL; @@ -117,20 +130,19 @@ int task0(void *data) sys_irq = sysset_find_obj(sys_set, "/sys/irl/primary"); - int a, b, c; while (1) { - +#if 0 if (sys_irq) sysobj_show_attr(sys_irq, "irl", buf1); a = xa; b = xb; c = xc; + d = xd; sched_time = sched_last_time; curr = atoi(buf1)/2; - printk("%d %d %d %llu ", a, b, c, ktime_get()); - printk("irq: %s %d per sec; ", buf1, (curr -last)); + printk("%u %u %u %u %llu ", a, b, c, d, ktime_get()); // printk("sched %llu us ", ktime_to_us(sched_last_time)); printk("%llu per call ", sched_last_time /sched_ev); // printk("calls %d ", sched_ev - last_call); @@ -140,6 +152,14 @@ int task0(void *data) last = curr; last_call = sched_ev; +#endif + + sched_print_edf_list_internal(&sched_edf.tq[0], 0, ktime_get()); + sched_print_edf_list_internal(&sched_edf.tq[1], 1, ktime_get()); + + + + sched_yield(); } } @@ -290,14 +310,14 @@ int kernel_main(void) #endif -#if 1 +#if 0 - t = kthread_create(task0, NULL, KTHREAD_CPU_AFFINITY_NONE, "res"); + t = kthread_create(task0, NULL, KTHREAD_CPU_AFFINITY_NONE, "task0"); sched_get_attr(t, &attr); attr.policy = SCHED_EDF; attr.period = ms_to_ktime(100); attr.deadline_rel = ms_to_ktime(90); - attr.wcet = ms_to_ktime(30); + attr.wcet = ms_to_ktime(39); sched_set_attr(t, &attr); kthread_wake_up(t); #endif @@ -310,18 +330,18 @@ int kernel_main(void) attr.policy = SCHED_EDF; attr.period = ms_to_ktime(50); attr.deadline_rel = ms_to_ktime(40); - attr.wcet = ms_to_ktime(31); + attr.wcet = ms_to_ktime(33); sched_set_attr(t, &attr); kthread_wake_up(t); #endif -#if 1 +#if 0 t = kthread_create(task2, NULL, KTHREAD_CPU_AFFINITY_NONE, "task2"); sched_get_attr(t, &attr); attr.policy = SCHED_EDF; attr.period = ms_to_ktime(40); - attr.deadline_rel = ms_to_ktime(25); - attr.wcet = ms_to_ktime(20); + attr.deadline_rel = ms_to_ktime(22); + attr.wcet = ms_to_ktime(17); sched_set_attr(t, &attr); kthread_wake_up(t); #endif @@ -332,12 +352,20 @@ int kernel_main(void) attr.policy = SCHED_EDF; attr.period = ms_to_ktime(80); attr.deadline_rel = ms_to_ktime(70); - attr.wcet = ms_to_ktime(10); + attr.wcet = ms_to_ktime(13); sched_set_attr(t, &attr); kthread_wake_up(t); #endif +#if 0 + t = kthread_create(task_rr, NULL, KTHREAD_CPU_AFFINITY_NONE, "task_rr"); + sched_get_attr(t, &attr); + attr.policy = SCHED_RR; + attr.priority = 1; + sched_set_attr(t, &attr); + kthread_wake_up(t); +#endif #endif diff --git a/kernel/sched/edf.c b/kernel/sched/edf.c index 5617fb32dcda146ed2852d7c56e225341cbc8b9f..f7b88b43187f5cb5c91f903a02c6ce44b2edb445 100644 --- a/kernel/sched/edf.c +++ b/kernel/sched/edf.c @@ -27,8 +27,8 @@ void sched_print_edf_list_internal(struct task_queue *tq, int cpu, ktime now) ktime prev = 0; ktime prevd = 0; - printk("\nktime: %lld\n", ktime_to_ms(now)); - printk("S\tDeadline\tWakeup\t\tdelta W\tdelta P\tt_rem\ttotal\tslices\tName\twcet\tavg\n"); + printk("\nktime: %lld CPU %d\n", ktime_to_ms(now), cpu); + printk("S\tDeadline\tWakeup\t\tdelta W\tdelta P\tt_rem\ttotal\tslices\tName\t\twcet\tavg\n"); printk("---------------------------------------------------------------------------------------------------------------------------------\n"); list_for_each_entry_safe(tsk, tmp, &tq->run, node) { @@ -104,11 +104,16 @@ static inline bool schedule_edf_can_execute(struct task_struct *tsk, int cpu, kt /* should to consider twice the min tick period for overhead */ + if (tsk->runtime < 0) + return false; + if (tsk->runtime <= (tick_get_period_min_ns() << 1)) return false; to_deadline = ktime_delta(tsk->deadline, now); + barrier(); + tsk->last_visit = now; /* should to consider twice the min tick period for overhead */ if (to_deadline <= (tick_get_period_min_ns() << 1)) return false; @@ -119,25 +124,31 @@ static inline bool schedule_edf_can_execute(struct task_struct *tsk, int cpu, kt static inline void schedule_edf_reinit_task(struct task_struct *tsk, ktime now) { + ktime new_wake; + + BUG_ON(tsk->runtime == tsk->attr.wcet); + tsk->state = TASK_IDLE; - tsk->wakeup = ktime_add(tsk->wakeup, tsk->attr.period); + new_wake = ktime_add(tsk->wakeup, tsk->attr.period); #if 1 /* need FDIR procedure for this situation */ - if (ktime_after(now, tsk->wakeup)){ /* deadline missed earlier? */ - printk("%s delta %lld\n",tsk->name, ktime_us_delta(tsk->wakeup, 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); + if (ktime_after(now, new_wake)){ /* deadline missed earlier? */ + printk("%s violated, rt: %lld %lld, last_visit %lld, last_adjust %lld delta %lld next wake: %lld %llx\n", tsk->name, + tsk->runtime, ktime_to_us(tsk->last_visit), ktime_to_us(tsk->last_adjust), ktime_us_delta(tsk->last_visit, tsk->last_adjust), ktime_to_us(tsk->wakeup), tsk->attr.period); sched_print_edf_list_internal(&tsk->sched->tq[tsk->on_cpu], tsk->on_cpu, now); BUG(); } #endif + tsk->wakeup = new_wake; + tsk->deadline = ktime_add(tsk->wakeup, tsk->attr.deadline_rel); tsk->runtime = tsk->attr.wcet; + tsk->last_adjust = now; + tsk->slices++; } @@ -252,7 +263,7 @@ static ktime edf_hyperperiod(struct task_queue tq[], int cpu, const struct task_ * * XXX function needs adaptation */ -#define UTIL_MAX 0.8 +#define UTIL_MAX 0.9 static int edf_schedulable(struct task_queue tq[], const struct task_struct *task) { struct task_struct *tsk = NULL; @@ -364,6 +375,7 @@ if (1) printk("t0: %s (cpu %d)\n", t0->name, cpu); h = p / t0->attr.period; + h = 1; printk("Period factor %lld, duration %lld actual period: %lld\n", h, ktime_to_ms(p), ktime_to_ms(t0->attr.period)); @@ -554,7 +566,7 @@ if (1) printk("changed task mode to RR\n", u); } - printk("Utilisation: %g\n---\n", u); + printk("Utilisation: %g CPU %d", u, cpu); /* TODO check against projected interrupt rate, we really need a limit @@ -917,7 +929,7 @@ ktime edf_task_ready_ns(struct task_queue *tq, int cpu, ktime now) } -static struct scheduler sched_edf = { +struct scheduler sched_edf = { .policy = SCHED_EDF, .pick_next_task = edf_pick_next, .wake_next_task = edf_wake_next,