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. --- interrupt/fault.cpp | 6 ++++-- os/thread.cpp | 1 + os/thread.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++---- os/time.h | 9 +-------- 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/interrupt/fault.cpp b/interrupt/fault.cpp index 9af0eb8..8a577bf 100644 --- a/interrupt/fault.cpp +++ b/interrupt/fault.cpp @@ -13,9 +13,11 @@ inline void __attribute__((naked)) switch_context() { // Update running thread. if(!Thread::reschedule()) { - // TODO: Set SLEEPONEXIT + // No threads are ready - set SLEEPONEXIT. + SCB.SCR = 1 << 1; } else { - // TODO: Clear SLEEPONEXIT + // Clear SLEEPONEXIT. + SCB.SCR = 0 << 1; } // Fetch stack pointer for new thread. diff --git a/os/thread.cpp b/os/thread.cpp index 0f2437d..432727a 100644 --- a/os/thread.cpp +++ b/os/thread.cpp @@ -1,5 +1,6 @@ #include "thread.h" List Thread::ready_queue __attribute__ ((init_priority (1000))); +List Thread::sleep_queue; Thread Thread::main_thread __attribute__ ((init_priority (1001))); Thread* Thread::active_thread = &Thread::main_thread; 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"); } diff --git a/os/time.h b/os/time.h index f4e3ce6..6287834 100644 --- a/os/time.h +++ b/os/time.h @@ -1,7 +1,7 @@ #ifndef TIME_H #define TIME_H -#include "thread.h" +#include struct STK_t { volatile uint32_t CTRL; @@ -24,13 +24,6 @@ class Time { inline static uint32_t time() { return systime; } - - inline static void sleep(uint32_t ms) { - ms += systime; - while(systime < ms) { - Thread::yield(); - } - } }; #endif -- cgit v1.2.3