From e14b2f0d2406311a6fcdaea313584995ec8adefd Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Sat, 20 Jul 2013 08:41:41 +0200 Subject: Add support for sleeping threads. --- os/thread.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'os/thread.h') diff --git a/os/thread.h b/os/thread.h index 72ee275..9270727 100644 --- a/os/thread.h +++ b/os/thread.h @@ -4,6 +4,8 @@ #include #include +#include "time.h" + class Thread { friend void switch_context(); @@ -33,20 +35,42 @@ class Thread { int_frame_t* sp; + enum State { + Running, + Sleeping, + }; + + State state; + uint32_t sleep_deadline; + ListHandle queue_handle; static List ready_queue; + static List sleep_queue; static Thread* active_thread; static Thread main_thread; static bool reschedule() { - //active_thread = active_thread->next; + uint32_t now = Time::time(); - // TODO: Check whether active thread still is ready. + // Go through sleep queue. + for(auto h : sleep_queue) { + // Move to ready queue if deadline has expired. + if(h->p->sleep_deadline <= now) { + h->p->state = Running; + ready_queue.append(*h); + + // Moving one element makes the iterator unusable, so break here. + break; + } + } - // Move thread to end of ready queue. - ready_queue.append(active_thread->queue_handle); + // Check whether active thread still is ready. + if(active_thread->state == Running) { + // Move thread to end of ready queue. + ready_queue.append(active_thread->queue_handle); + } // Check whether any threads are ready to run. if(ready_queue.empty()) { @@ -78,6 +102,29 @@ class Thread { ready_queue.append(queue_handle); } + void set_sleeping(uint32_t until) { + sleep_deadline = until; + state = Sleeping; + + // Search for thread with later deadline. + for(auto h : sleep_queue) { + // Insert before if found. + if(h->p->sleep_deadline > sleep_deadline) { + queue_handle.insert_before(*h); + return; + } + } + + // Otherwise append to end of queue. + sleep_queue.append(queue_handle); + } + + static void sleep(uint32_t delay) { + active_thread->set_sleeping(Time::time() + delay); + + yield(); + } + static inline void yield() { asm volatile("svc 0" ::: "memory"); } -- cgit v1.2.3