From 157ea9ca4d2600f3e8c1943e3d7a8f9451f19a36 Mon Sep 17 00:00:00 2001 From: sasan-golchin <ahmad.golchin@mail.polimi.it> Date: Fri, 11 Nov 2016 13:48:00 +0100 Subject: [PATCH] EDF scheduler integrated with the ContextSwitchTimer interface --- miosix/kernel/scheduler/edf/edf_scheduler.cpp | 28 +++++++++++++++++-- miosix/kernel/scheduler/edf/edf_scheduler.h | 6 +++- .../scheduler/edf/edf_scheduler_types.h | 12 ++++++++ miosix/kernel/scheduler/timer_interrupt.h | 12 +------- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/miosix/kernel/scheduler/edf/edf_scheduler.cpp b/miosix/kernel/scheduler/edf/edf_scheduler.cpp index 38670848..cc7745ff 100644 --- a/miosix/kernel/scheduler/edf/edf_scheduler.cpp +++ b/miosix/kernel/scheduler/edf/edf_scheduler.cpp @@ -28,6 +28,8 @@ #include "edf_scheduler.h" #include "kernel/error.h" #include "kernel/process.h" +#include "interfaces/cstimer.h" +#include "kernel/scheduler/timer_interrupt.h" #include <algorithm> using namespace std; @@ -39,7 +41,11 @@ namespace miosix { //These are defined in kernel.cpp extern volatile Thread *cur; extern volatile int kernel_running; +extern IntrusiveList<SleepData> *sleepingList; +//Static members +static ContextSwitchTimer& timer = ContextSwitchTimer::instance(); +static long long nextPreemption = numeric_limits<long long>::max(); // // class EDFScheduler // @@ -105,9 +111,24 @@ void EDFScheduler::IRQsetIdleThread(Thread *idleThread) add(idleThread); } -void EDFScheduler::IRQfindNextThread() +long long EDFScheduler::IRQgetNextPreemption() { - if(kernel_running!=0) return;//If kernel is paused, do nothing + return nextPreemption; +} + +static void IRQsetNextPreemption(){ + if (sleepingList->empty()) + { + nextPreemption = numeric_limits<long long>::max(); + }else{ + nextPreemption = sleepingList->front()->wakeup_time; + } + timer.IRQsetNextInterrupt(nextPreemption); +} + +unsigned int EDFScheduler::IRQfindNextThread() +{ + if(kernel_running!=0) return 0;//If kernel is paused, do nothing Thread *walk=head; for(;;) @@ -129,7 +150,8 @@ void EDFScheduler::IRQfindNextThread() #else //WITH_PROCESSES ctxsave=cur->ctxsave; #endif //WITH_PROCESSES - return; + IRQsetNextPreemption(); + return 1; } walk=walk->schedData.next; } diff --git a/miosix/kernel/scheduler/edf/edf_scheduler.h b/miosix/kernel/scheduler/edf/edf_scheduler.h index bdabd031..8432ebde 100755 --- a/miosix/kernel/scheduler/edf/edf_scheduler.h +++ b/miosix/kernel/scheduler/edf/edf_scheduler.h @@ -133,9 +133,13 @@ public: * If the kernel is paused does nothing. * It's behaviour is to modify the global variable miosix::cur which always * points to the currently running thread. + * + * \return 1 if any active threads found and 0 otherwise */ - static void IRQfindNextThread(); + static unsigned int IRQfindNextThread(); + static long long IRQgetNextPreemption(); + private: /** diff --git a/miosix/kernel/scheduler/edf/edf_scheduler_types.h b/miosix/kernel/scheduler/edf/edf_scheduler_types.h index a2e4fc3a..a20bbd46 100644 --- a/miosix/kernel/scheduler/edf/edf_scheduler_types.h +++ b/miosix/kernel/scheduler/edf/edf_scheduler_types.h @@ -76,6 +76,18 @@ public: return this->deadline>=0 && this->deadline!=std::numeric_limits<long long>::max()-1; } + + /** + * This function acts like a less-than operator but should be only used in + * synchronization module for priority inheritance. The concept of priority + * for preemption is not exactly the same for priority inheritance, hence, + * this operation is a branch out of preemption priority for inheritance + * purpose. + * @return + */ + inline bool mutexLessOp(EDFSchedulerPriority b){ + return deadline > deadline; + } private: long long deadline;///< The deadline time diff --git a/miosix/kernel/scheduler/timer_interrupt.h b/miosix/kernel/scheduler/timer_interrupt.h index 9615ca61..5c3221c9 100644 --- a/miosix/kernel/scheduler/timer_interrupt.h +++ b/miosix/kernel/scheduler/timer_interrupt.h @@ -52,19 +52,9 @@ inline void IRQtimerInterrupt(long long currentTick) if (currentTick >= Scheduler::IRQgetNextPreemption() || hptw ){ //End of the burst || a higher priority thread has woken up Scheduler::IRQfindNextThread();//If the kernel is running, preempt + if(kernel_running!=0) tick_skew=true; } - if(kernel_running!=0) tick_skew=true; - - #ifndef SCHED_TYPE_PRIORITY - //TODO: the old tick scheduler called this function periodically, - //so the EDF scheduler would have to be called only if a thread was woken. - //Now we can have no periodic preemption, and so if we are called (and EDF - //is selected), at least one thread has woken up, so there's no need for woken - //Modify the code below accordingly - //#error "FIXME" - #endif - // miosix_private::IRQstackOverflowCheck(); // bool woken=IRQwakeThreads();//Increment tick and wake threads,if any // (void)woken; //Avoid unused variable warning. -- GitLab