diff options
author | Vegard Storheil Eriksen <zyp@jvnv.net> | 2013-07-20 08:41:41 +0200 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@jvnv.net> | 2013-07-20 08:43:10 +0200 |
commit | e14b2f0d2406311a6fcdaea313584995ec8adefd (patch) | |
tree | f2cffca4fe334aeb873cce8a77bd5b6f98cc0096 | |
parent | 657d427aa41e6e05c8c4d4b1179b42d3363e8018 (diff) |
Add support for sleeping threads.scheduler_improvements
-rw-r--r-- | interrupt/fault.cpp | 6 | ||||
-rw-r--r-- | os/thread.cpp | 1 | ||||
-rw-r--r-- | os/thread.h | 55 | ||||
-rw-r--r-- | 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> Thread::ready_queue __attribute__ ((init_priority (1000))); +List<Thread> 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 <stdint.h> #include <util/intrusive_list.h> +#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<Thread> queue_handle; static List<Thread> ready_queue; + static List<Thread> 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"); } @@ -1,7 +1,7 @@ #ifndef TIME_H #define TIME_H -#include "thread.h" +#include <stdint.h> 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 |