diff --git a/init/main.c b/init/main.c
index c98e734f0fd2c74f146a35a46482c1c0a4c7a228..02e403738e6e59b64d9c0cf94197504c3560ae35 100644
--- a/init/main.c
+++ b/init/main.c
@@ -58,8 +58,11 @@ int task1(void *data)
 int task2(void *data)
 {
 	while (1) {
-		printk("-");
-		sched_yield();
+		//printk("x %llu\n", ktime_get());
+		printk("_\n");
+	//	sched_yield();
+//		printk("-");
+	//	sched_yield();
 	}
 }
 static int cnt;
@@ -81,7 +84,9 @@ int task3(void *data)
 		//	sched_yield();
 
 #endif
-		printk("%llu\n", ktime_get());
+		//printk("y %llu\n", ktime_get());
+		printk(".\n");
+
 	//	sched_yield();
 	}
 }
@@ -223,12 +228,21 @@ int kernel_main(void)
 	kthread_wake_up(t);
 #endif
 #if 1
-	t = kthread_create(task3, NULL, KTHREAD_CPU_AFFINITY_NONE, "edfprint");
+	t = kthread_create(task2, NULL, KTHREAD_CPU_AFFINITY_NONE, "print1");
+	sched_get_attr(t, &attr);
+	attr.policy = SCHED_EDF;
+	attr.period       = ms_to_ktime(1000);
+	attr.deadline_rel = ms_to_ktime(900);
+	attr.wcet         = ms_to_ktime(200);
+	sched_set_attr(t, &attr);
+	kthread_wake_up(t);
+
+	t = kthread_create(task3, NULL, KTHREAD_CPU_AFFINITY_NONE, "print2");
 	sched_get_attr(t, &attr);
 	attr.policy = SCHED_EDF;
-	attr.period       = ms_to_ktime(3000);
-	attr.deadline_rel = ms_to_ktime(2000);
-	attr.wcet         = ms_to_ktime(1000);
+	attr.period       = ms_to_ktime(1000);
+	attr.deadline_rel = ms_to_ktime(900);
+	attr.wcet         = ms_to_ktime(200);
 	sched_set_attr(t, &attr);
 	kthread_wake_up(t);
 #endif
@@ -263,6 +277,7 @@ int kernel_main(void)
 		i++;
 #endif
 	//	sched_yield();
+#if 0
 		if (cnt > 1023) {
 			int i;
 			for (i = 1; i < 1024; i++)
@@ -270,10 +285,12 @@ int kernel_main(void)
 		//	cnt = 0;
 			break;
 		}
-		printk("xxx %llu\n", ktime_get());
+#endif
+//		printk("xxx %llu\n", ktime_get());
 
 		//printk("%d\n", cnt);
 
+		printk("o\n");
 
 	//	sched_yield();
 	//	cpu_relax();
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index bd4b56f883450006d922e69dcc9cc0bb563f9d81..0425e0add446a4f9776b3206236ffd08f9fb0fa7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -34,7 +34,7 @@ void schedule(void)
 
 	struct task_struct *next = NULL;
 
-	struct task_struct *current = current_set[0]->task;
+	struct task_struct *current;
 	int64_t slot_ns;
 	int64_t wake_ns = 0;
 
@@ -52,6 +52,11 @@ void schedule(void)
 	arch_local_irq_disable();
 	/* kthread_lock(); */
 
+	/* get the current task for this CPU */
+	current = current_set[0]->task;
+
+	/** XXX need timeslice_update callback for schedulers */
+	/* update remaining runtime of current thread */
 	current->runtime = ktime_sub(current->exec_start, ktime_get());
 
 
@@ -62,77 +67,95 @@ void schedule(void)
 		sched->wake_next_task(&sched->tq);
 	}
 
-	current = current_set[0]->task;
 
 	/* XXX need sorted list: highest->lowest scheduler priority, e.g.:
 	 * EDF -> RMS -> FIFO -> RR
 	 * TODO: scheduler priority value
 	 */
+
 	list_for_each_entry(sched, &kernel_schedulers, node) {
-	//	struct task_struct *tmpn;
+
+
+
+		/* if one of the schedulers have a task which needs to run now,
+		 * next is non-NULL
+		 */
 		next = sched->pick_next_task(&sched->tq);
+#if 0
+		if (next)
+			printk("next %s %llu %llu\n", next->name, next->first_wake, ktime_get());
+		else
+			printk("NULL\n");
+#endif
 
 		/* check if we need to limit the next tasks timeslice;
 		 * since our scheduler list is sorted by scheduler priority,
 		 * only update the value if wake_next is not set;
+		 *
+		 * because our schedulers are sorted, this means that if next
+		 * is set, the highest priority scheduler will both tell us
+		 * whether it has another task pending soon. If next is not set,
+		 * a lower-priority scheduler may set the next thread to run,
+		 * but we will take the smallest timeout from high to low
+		 * priority schedulers, so we enter this function again when
+		 * the timeslice of the next thread is over and we can determine
+		 * what needs to be run in the following scheduling cycle. This
+		 * way, we will distribute CPU time even to the lowest priority
+		 * scheduler, if available, but guarantee, that the highest
+		 * priority threads are always ranked and executed on time
+		 *
 		 * we assume that the timeslice is reasonable; if not fix it in
 		 * the corresponding scheduler
 		 */
-		//int64_t tmp;
+
 		if (!wake_ns)
 			wake_ns = sched->task_ready_ns(&sched->tq);
-#if 0
-		if (next)
-			printk("next %s\n", next->name);
-		printk("wake_ns %llu\n", wake_ns);
-#endif
-#if 0
-		else {
-			tmp = sched->task_ready_ns(&sched->tq);
-			if (tmp > wake_ns) {
-				wake_ns = tmp;
-				next = tmpn;
-			}
-		}
-
-		if (!next)
-			next = tmpn;
 
-#endif
+		/* we found something to execute, off we go */
 		if (next)
 			break;
 	}
 
 
 	if (!next) {
-		/* nothing to do, check again later */
-		if (wake_ns) {
+		/* there is absolutely nothing nothing to do, check again later */
+		if (wake_ns)
 			tick_set_next_ns(wake_ns);
-		}
 		else
-			tick_set_next_ns(1e9);	/* XXX pause for a second */
+			tick_set_next_ns(1e9);	/* XXX pause for a second, there are no threads in any scheduler */
 
 		goto exit;
 	}
 
-	/* see if we can use a full slice or if we have to wake earlier */
-	slot_ns = wake_ns;
-		slot_ns = next->sched->timeslice_ns(next);
+	/* see if the remaining runtime in a thread is smaller than the wakeup
+	 * timeout. In this case, we will restrict ourselves to the remaining
+	 * runtime. This is particularly needeed for strictly periodic
+	 * schedulers, e.g. EDF
+	 */
+
+	slot_ns = next->sched->timeslice_ns(next);
+
 	if (wake_ns < slot_ns)
-		slot_ns = wake_ns;
+		slot_ns  = wake_ns;
 
 	/* statistics */
 	next->exec_start = ktime_get();
+//	printk("at %llu\n", next->exec_start);
 
 //		if (next)
 //			printk("real next %s %llu %llu\n", next->name, next->exec_start, slot_ns);
 	/* kthread_unlock(); */
 
 //	printk("wake %llu\n", slot_ns);
+
 	/* subtract readout overhead */
 	tick_set_next_ns(ktime_sub(slot_ns, 1000LL));
-//	tick_set_next_ns(slot_ns);
-
+#if 0
+	if (slot_ns < 20000UL) {
+		printk("wake %llu\n", slot_ns);
+		BUG();
+	}
+#endif
 	prepare_arch_switch(1);
 	switch_to(next);
 
diff --git a/kernel/sched/edf.c b/kernel/sched/edf.c
index e3f6406d19820e2ab648c823f325412f80ad3d1a..ae07794f2b588b5883207d640aebb7ae6fe96f26 100644
--- a/kernel/sched/edf.c
+++ b/kernel/sched/edf.c
@@ -148,7 +148,7 @@ static inline void schedule_edf_reinit_task(struct task_struct *tsk, ktime now)
 	tsk->state = TASK_IDLE;
 
 	tsk->wakeup = ktime_add(tsk->wakeup, tsk->attr.period);
-#if 0
+#if 1
 	if (ktime_after(now, tsk->wakeup))
 		printk("%s delta %lld\n",tsk->name, ktime_us_delta(tsk->wakeup, now));
 
@@ -583,7 +583,7 @@ static int edf_schedulable(struct task_queue *tq, const struct task_struct *task
 
 	static int64_t dmin = 0x7fffffffffffffLL;
 
-	printk("\nvvvv EDF analysis vvvv (%lld) \n\n", p);
+	printk("\nvvvv EDF analysis vvvv (%lld ms) \n\n", ktime_to_ms(p));
 
 	/* list_empty(....) */
 
@@ -615,12 +615,42 @@ static int edf_schedulable(struct task_queue *tq, const struct task_struct *task
 	printk("max UH: %lld, UT: %lld\n", ktime_to_ms(uh), ktime_to_ms(ut));
 
 
-	list_for_each_entry_safe(tsk, tmp, &tq->new, node) {
-		ktime sh, st;
 
-		if (tsk == t0)
+	/* add all in wakeup */
+	struct task_struct *tsk2 = NULL;
+	struct task_struct *tmp2;
+	if (!list_empty(&tq->wake)) {
+	list_for_each_entry_safe(tsk2, tmp2, &tq->wake, node) {
+
+		printk("%d\n", __LINE__);
+		if (tsk2->attr.policy != SCHED_EDF)
+			continue;
+
+		u += (double) (int32_t) tsk2->attr.wcet / (double) (int32_t) tsk2->attr.period;
+	}
+	}
+
+	/* add all running */
+	if (!list_empty(&tq->run)) {
+	list_for_each_entry_safe(tsk2, tmp2, &tq->run, node) {
+
+		printk("%d\n", __LINE__);
+		if (tsk2->attr.policy != SCHED_EDF)
 			continue;
 
+		u += (double) (int32_t) tsk2->attr.wcet / (double) (int32_t) tsk2->attr.period;
+	}
+	}
+
+
+	//list_for_each_entry_safe(tsk, tmp, &tq->new, node)
+	{
+		tsk = t0;
+		ktime sh, st;
+
+	//	if (tsk == t0)
+	//		continue;
+
 
 		if (tsk->attr.deadline_rel < t0->attr.deadline_rel) {
 
@@ -659,16 +689,11 @@ static int edf_schedulable(struct task_queue *tq, const struct task_struct *task
 		u += (double) (int32_t) task->attr.wcet / (double) (int32_t) task->attr.period;
 
 
-		list_for_each_entry_safe(tsk, tmp, &tq->new, node) {
 
-			if (tsk->attr.policy != SCHED_EDF)
-				continue;
 
-			u += (double) (int32_t) tsk->attr.wcet / (double) (int32_t) tsk->attr.period;
-		}
 
 		if (u > 1.0) {
-			printk("I am NOT schedul-ableh: %g ", u);
+			printk("I am NOT schedul-ableh: %f ", u);
 			return -EINVAL;
 			printk("changed task mode to RR\n", u);
 		} else {
@@ -693,7 +718,7 @@ static int64_t slot;
 
 static struct task_struct *edf_pick_next(struct task_queue *tq)
 {
-#define SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE 100000LL
+#define SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE 111111LL
 	int64_t delta;
 
 
@@ -701,23 +726,25 @@ static struct task_struct *edf_pick_next(struct task_queue *tq)
 	struct task_struct *tsk;
 	struct task_struct *tmp;
 	ktime now = ktime_get();
-slot = SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE;
+	slot = 1000000000000; //SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE;
 
 
-//	printk("-\n");
 	list_for_each_entry_safe(tsk, tmp, &tq->run, node) {
 
 		/* time to wake up yet? */
 		delta = ktime_delta(tsk->wakeup, now);
+
 		if (delta >= 0) {
+
 			/* nope, just update minimum runtime for this slot */
+
 			if (delta < slot) {
 				slot = delta;
-			//	printk("d %lld now: %lld \n", ktime_to_us(delta), now);
+//				printk("d %lld now: %lld \n", ktime_to_us(delta), now);
 			}
-		//	printk("delta %llu %llu\n", delta, tsk->wakeup);
+//			printk("delta %llu %llu\n", delta, tsk->wakeup);
 
-//			continue;
+		//	continue;
 		}
 		if (delta < 0) {
 
@@ -736,10 +763,14 @@ slot = SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE;
 				if (delta < 0) {
 					delta = tsk->attr.wcet;
 					slot = delta;
+			//		printk("NOW!\n");
 				}
 #endif
-				if (delta < slot)
+				if (delta < slot) {
+			//		printk("HERE!\n");
+
 					slot = delta;
+				}
 				if (delta < 0)
 					printk("delta %lld %lld\n", ktime_to_us(delta), ktime_to_us(tick_get_period_min_ns()));
 				BUG_ON(delta < 0);
@@ -748,6 +779,7 @@ slot = SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE;
 			}
 
 			/* move to top */
+			go = tsk;
 			list_move(&tsk->node, &tq->run);
 			continue;
 		}
@@ -758,39 +790,58 @@ slot = SOME_DEFAULT_TICK_PERIOD_FOR_SCHED_MODE;
 			/* move to top */
 			list_move(&tsk->node, &tq->run);
 			go = tsk;
+			break;
 		}
 
 	}
-
+#if 0
 	/** XXX **/
-	//tsk = list_entry(tq->run.next, struct task_struct, node);
+	tsk = list_entry(tq->run.next, struct task_struct, node);
 
 	if (tsk->state == TASK_RUN)
 		return tsk;
 	else
-		return go;
+#endif
+	return go;
 }
 
 
 static void edf_wake_next(struct task_queue *tq)
 {
-
+	struct task_struct *tsk;
+	struct task_struct *tmp;
 	struct task_struct *task;
 
+	ktime last=0;
+
 	if (list_empty(&tq->wake))
 		return;
 
 	task = list_entry(tq->wake.next, struct task_struct, node);
 
-//		if (next->attr.policy == SCHED_EDF)
-//			return;
-		/* initially set current time as wakeup */
-		task->wakeup = ktime_add(ktime_get(), task->attr.period);
-		task->deadline = ktime_add(task->wakeup, task->attr.deadline_rel);
-		task->first_wake = task->wakeup;
-		task->first_dead = task->deadline;
 
-		list_move(&task->node, &tq->run);
+	last = ktime_get();
+
+	list_for_each_entry_safe(tsk, tmp, &tq->run, node) {
+		if (tsk->deadline > last)
+			last = tsk->deadline;
+	}
+
+//	if (next->attr.policy == SCHED_EDF)
+//		return;
+//
+	/* initially furthest deadline as wakeup */
+	task->wakeup = ktime_add(last, task->attr.period);
+	/* add overhead */
+	task->wakeup = ktime_add(task->wakeup, 2000UL);
+
+	task->deadline = ktime_add(task->wakeup, task->attr.deadline_rel);
+	task->first_wake = task->wakeup;
+	task->first_dead = task->deadline;
+
+//	printk("---- %s %llu\n", task->name, task->first_wake);
+
+	list_move(&task->node, &tq->run);
 }
 
 
@@ -812,20 +863,23 @@ static void edf_enqueue(struct task_queue *tq, struct task_struct *task)
 		printk("---- NOT SCHEDUL-ABLE---\n");
 		return;
 	}
-
-
+#if 0
 	/** XXX **/
 	if (task->state == TASK_RUN)
-		list_add_tail(&task->node, &tq->run);
+		list_move(&task->node, &tq->run);
 	else
-		list_add_tail(&task->node, &tq->wake);
+
+#endif
+#if 1
+	list_move(&task->node, &tq->wake);
+#endif
 
 }
 
 
 static ktime edf_timeslice_ns(struct task_struct *task)
 {
-	return 0;
+	return (ktime) (task->runtime);
 }
 
 static int edf_check_sched_attr(struct sched_attr *attr)
diff --git a/kernel/sched/rr.c b/kernel/sched/rr.c
index f67bcc5807e1c05085fd3d04e4f8eeb74ae285b8..2cf78792420c8a88d9580f89bf9dcb7432b35ef2 100644
--- a/kernel/sched/rr.c
+++ b/kernel/sched/rr.c
@@ -30,6 +30,10 @@ static struct task_struct *rr_pick_next(struct task_queue *tq)
 			 * round robin
 			 */
 			list_move_tail(&next->node, &tq->run);
+
+			/* reset runtime */
+			next->runtime = (next->attr.priority * tick_get_period_min_ns());
+
 			break;
 		}
 
@@ -68,6 +72,7 @@ static void rr_wake_next(struct task_queue *tq)
 static void rr_enqueue(struct task_queue *tq, struct task_struct *task)
 {
 
+	task->runtime = (task->attr.priority * tick_get_period_min_ns());
 	/** XXX **/
 	if (task->state == TASK_RUN)
 		list_add_tail(&task->node, &tq->run);
@@ -89,7 +94,7 @@ static void rr_enqueue(struct task_queue *tq, struct task_struct *task)
 
 static ktime rr_timeslice_ns(struct task_struct *task)
 {
-	return (ktime) (task->attr.priority * tick_get_period_min_ns() * 1000);
+	return (ktime) (task->attr.priority * tick_get_period_min_ns());
 }