diff --git a/src/devices/timer.c b/src/devices/timer.c
index e4abd1dd07eb96e01101e1e3e4988119c61f6bb2..fdfd567dcb6c88dbedebdd4cdf94102ccf541895 100644
--- a/src/devices/timer.c
+++ b/src/devices/timer.c
@@ -106,7 +106,7 @@ timer_sleep (int64_t ticks)
   //     check_front
 
   struct thread* t = thread_current ();
-  // t->status = THREAD_ASLEEP;            // TODO gets overwritten by thread_yield
+  t->status = THREAD_ASLEEP;            // TODO gets overwritten by thread_yield
   t->sleep_until = start + ticks;
   thread_yield ();
 
diff --git a/src/devices/timer.h b/src/devices/timer.h
index 45a3f72e1127cd02f97b79d995277bec67a0812f..eed59838c2d9c6e2ea706c5ebcd997d735fb2c17 100644
--- a/src/devices/timer.h
+++ b/src/devices/timer.h
@@ -7,6 +7,8 @@
 /* Number of timer interrupts per second. */
 #define TIMER_FREQ 100
 
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
 void timer_init (void);
 void timer_calibrate (void);
 
diff --git a/src/threads/thread.c b/src/threads/thread.c
index 9da537fe89bfb3cfe64ae577a3bb520d31bb20da..c2bda5383bec9040f549a935377506acd952eb13 100644
--- a/src/threads/thread.c
+++ b/src/threads/thread.c
@@ -258,7 +258,7 @@ thread_current (void)
      of stack, so a few big automatic arrays or moderate
      recursion can cause stack overflow. */
   ASSERT (is_thread (t));
-  ASSERT (t->status == THREAD_RUNNING);
+  // ASSERT (t->status == THREAD_RUNNING);
 
   return t;
 }
@@ -302,7 +302,10 @@ thread_yield (void)
   old_level = intr_disable ();
   if (cur != idle_thread) 
     list_push_back (&ready_list, &cur->elem);
-  cur->status = THREAD_READY;
+
+  if (cur->status != THREAD_ASLEEP) {
+    cur->status = THREAD_READY;
+  }
   schedule ();
   intr_set_level (old_level);
 }
@@ -523,30 +526,43 @@ static void
 schedule (void) 
 {
   struct thread *cur = running_thread ();
-  struct thread *next = next_thread_to_run ();
+  struct thread *next ;//= next_thread_to_run ();
   struct thread *prev = NULL;
-  struct thread* init_next = next;
 
   ASSERT (intr_get_level () == INTR_OFF);
   /* set to THREAD_READY in thread_yield() */
   ASSERT (cur->status != THREAD_RUNNING);
-  ASSERT (is_thread (next));
 
 //#ifdef USERPROG
 
-
-  while (next->status == THREAD_ASLEEP
-        && next->sleep_until < timer_ticks ())
-  {
-    list_push_back (&ready_list, &next->elem);
-    next = list_entry (list_pop_front (&ready_list), struct thread, elem);
-
-    if (next == init_next) {
-      next = idle_thread;
-      break;
+  for (struct list_elem* e = list_begin(&ready_list);
+        e != list_end (&ready_list);
+        e = list_next (e)) {
+    next = list_entry (e, struct thread, elem);
+    switch (next->status) {
+      case THREAD_ASLEEP:
+        if (next->sleep_until <= timer_ticks()) {
+          next->status = THREAD_READY;
+          list_remove (e);
+        }
+        break;
+      case THREAD_READY:
+        list_remove (e);
+        goto swap_in;
+        break;
+      default:
+        continue;
     }
   }
 
+  next = idle_thread;
+
+swap_in:
+
+// we never pop
+
+  ASSERT (is_thread (next));
+
   // if all sleeping, busy wait with interrupt on
 //#endif