From 8abd78be5804e998f8f1c71ffdb02a1b2abbac0e Mon Sep 17 00:00:00 2001
From: sasan-golchin <ahmad.golchin@mail.polimi.it>
Date: Thu, 20 Oct 2016 16:34:29 +0200
Subject: [PATCH] Control scheduler revised to support multiburst - stage 1

---
 miosix/kernel/kernel.cpp                      |  11 +-
 miosix/kernel/kernel.h                        |   1 +
 .../scheduler/control/control_scheduler.cpp   | 209 +++++++++++++++---
 .../scheduler/control/control_scheduler.h     |  95 +-------
 .../control/control_scheduler_types.h         |  49 +++-
 miosix/kernel/scheduler/edf/edf_scheduler.h   |   2 +-
 .../scheduler/priority/priority_scheduler.cpp |   1 -
 .../scheduler/priority/priority_scheduler.h   |   2 +-
 miosix/kernel/scheduler/scheduler.h           |   4 +-
 9 files changed, 236 insertions(+), 138 deletions(-)
 mode change 100644 => 100755 miosix/kernel/kernel.cpp
 mode change 100644 => 100755 miosix/kernel/kernel.h
 mode change 100644 => 100755 miosix/kernel/scheduler/control/control_scheduler.h
 mode change 100644 => 100755 miosix/kernel/scheduler/control/control_scheduler_types.h
 mode change 100644 => 100755 miosix/kernel/scheduler/edf/edf_scheduler.h
 mode change 100644 => 100755 miosix/kernel/scheduler/priority/priority_scheduler.h
 mode change 100644 => 100755 miosix/kernel/scheduler/scheduler.h

diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp
old mode 100644
new mode 100755
index 8b88bfc9..e93630ad
--- a/miosix/kernel/kernel.cpp
+++ b/miosix/kernel/kernel.cpp
@@ -650,6 +650,7 @@ Thread *Thread::doCreate(void*(*startfunc)(void*) , unsigned int stacksize,
             reinterpret_cast<unsigned int*>(thread),argv);
 
     if((options & JOINABLE)==0) thread->flags.IRQsetDetached();
+    thread->flags.t = thread;
     return thread;
 }
 
@@ -838,31 +839,31 @@ Thread::~Thread()
 void Thread::ThreadFlags::IRQsetWait(bool waiting)
 {
     if(waiting) flags |= WAIT; else flags &= ~WAIT;
-    Scheduler::IRQwaitStatusHook();
+    Scheduler::IRQwaitStatusHook(this->t);
 }
 
 void Thread::ThreadFlags::IRQsetJoinWait(bool waiting)
 {
     if(waiting) flags |= WAIT_JOIN; else flags &= ~WAIT_JOIN;
-    Scheduler::IRQwaitStatusHook();
+    Scheduler::IRQwaitStatusHook(this->t);
 }
 
 void Thread::ThreadFlags::IRQsetCondWait(bool waiting)
 {
     if(waiting) flags |= WAIT_COND; else flags &= ~WAIT_COND;
-    Scheduler::IRQwaitStatusHook();
+    Scheduler::IRQwaitStatusHook(this->t);
 }
 
 void Thread::ThreadFlags::IRQsetSleep(bool sleeping)
 {
     if(sleeping) flags |= SLEEP; else flags &= ~SLEEP;
-    Scheduler::IRQwaitStatusHook();
+    Scheduler::IRQwaitStatusHook(this->t);
 }
 
 void Thread::ThreadFlags::IRQsetDeleted()
 {
     flags |= DELETED;
-    Scheduler::IRQwaitStatusHook();
+    Scheduler::IRQwaitStatusHook(this->t);
 }
 
 } //namespace miosix
diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h
old mode 100644
new mode 100755
index c19440be..d675a650
--- a/miosix/kernel/kernel.h
+++ b/miosix/kernel/kernel.h
@@ -861,6 +861,7 @@ private:
          */
         bool isInUserspace() const { return flags & USERSPACE; }
 
+        Thread* t;
     private:
         ///\internal Thread is in the wait status. A call to wakeup will change
         ///this
diff --git a/miosix/kernel/scheduler/control/control_scheduler.cpp b/miosix/kernel/scheduler/control/control_scheduler.cpp
index b131273d..05eb8268 100644
--- a/miosix/kernel/scheduler/control/control_scheduler.cpp
+++ b/miosix/kernel/scheduler/control/control_scheduler.cpp
@@ -30,6 +30,7 @@
 #include "kernel/process.h"
 #include <limits>
 #include "interfaces/cstimer.h"
+#include "kernel/scheduler/scheduler.h"
 
 using namespace std;
 
@@ -40,14 +41,45 @@ namespace miosix {
 //These are defined in kernel.cpp
 extern volatile Thread *cur;
 extern volatile int kernel_running;
-static ContextSwitchTimer& timer = ContextSwitchTimer::instance();
 extern IntrusiveList<SleepData> *sleepingList;
+extern bool kernel_started;
+
+//Internal
+static ContextSwitchTimer& timer = ContextSwitchTimer::instance();
 static long long burstStart = 0;
+static IntrusiveList<ThreadsListItem> activeThreads;
+static IntrusiveList<ThreadsListItem>::iterator curInRound = activeThreads.end();
 
 //
 // class ControlScheduler
 //
 
+static inline void addThreadToActiveList(ThreadsListItem *atlEntry)
+{
+    
+    switch (atlEntry->t->getPriority().getRealtime()){
+        case REALTIME_PRIORITY_IMMEDIATE:
+            activeThreads.insert(curInRound,atlEntry);
+            curInRound--;curInRound--;
+            break;
+        case REALTIME_PRIORITY_NEXT_BURST:
+        {
+            auto temp=curInRound;
+            activeThreads.insert(++temp,atlEntry);
+            break;
+        }
+        default:
+            activeThreads.push_back(atlEntry);
+    }
+}
+
+static inline void remThreadfromActiveList(ThreadsListItem *atlEntry){
+    if (curInRound==IntrusiveList<ThreadsListItem>::iterator(atlEntry)){
+        curInRound++;
+    }
+    activeThreads.erase(IntrusiveList<ThreadsListItem>::iterator(atlEntry));
+}
+
 bool ControlScheduler::PKaddThread(Thread *thread,
         ControlSchedulerPriority priority)
 {
@@ -55,6 +87,7 @@ bool ControlScheduler::PKaddThread(Thread *thread,
     if(threadListSize>=64) return false;
     #endif //SCHED_CONTROL_FIXED_POINT
     thread->schedData.priority=priority;
+    thread->schedData.atlEntry.t = thread;
     {
         //Note: can't use FastInterruptDisableLock here since this code is
         //also called *before* the kernel is started.
@@ -65,6 +98,15 @@ bool ControlScheduler::PKaddThread(Thread *thread,
         threadList=thread;
         threadListSize++;
         SP_Tr+=bNominal; //One thread more, increase round time
+        // Insert the thread in activeThreads list according to its real-time
+        // priority
+        if (thread->flags.isReady()){
+            addThreadToActiveList(&thread->schedData.atlEntry);
+            thread->schedData.lastReadyStatus = true;
+        }else{
+            thread->schedData.lastReadyStatus = false;
+        }
+        
         IRQrecalculateAlfa();
     }
     return true;
@@ -141,7 +183,7 @@ void ControlScheduler::IRQsetIdleThread(Thread *idleThread)
     //Initializing curInRound to end() so that the first time
     //IRQfindNextThread() is called the scheduling algorithm runs
     if(threadListSize!=1) errorHandler(UNEXPECTED);
-    curInRound=0;
+    curInRound=activeThreads.end();
 }
 
 Thread *ControlScheduler::IRQgetIdleThread()
@@ -195,8 +237,9 @@ unsigned int ControlScheduler::IRQfindNextThread()
     //Find next thread to run
     for(;;)
     {
-        if(curInRound!=0) curInRound=curInRound->schedData.next;
-        if(curInRound==0) //Note: do not replace with an else
+        //if(curInRound!=0) curInRound=curInRound->schedData.next;
+        if(curInRound!=activeThreads.end()) curInRound++;
+        if(curInRound==activeThreads.end()) //Note: do not replace with an else
         {
             //Check these two statements:
             //- If all threads are not ready, the scheduling algorithm must be
@@ -204,30 +247,24 @@ unsigned int ControlScheduler::IRQfindNextThread()
             //- If the inner integral regulator of all ready threads saturated
             //  then the integral regulator of the outer regulator must stop
             //  increasing because the set point cannot be attained anyway.
-            bool allThreadNotReady=true;
             bool allReadyThreadsSaturated=true;
-            for(Thread *it=threadList;it!=0;it=it->schedData.next)
+            for (auto it=activeThreads.begin() ; it!=activeThreads.end() ; it++)
             {
-                if(it->flags.isReady())
-                {
-                    allThreadNotReady=false;
-                    if(it->schedData.bo<bMax*multFactor)
-                    {
+                if((*it)->t->schedData.bo<bMax*multFactor){
                         allReadyThreadsSaturated=false;
                         //Found a counterexample for both statements,
                         //no need to scan the list further.
                         break;
-                    }
                 }
             }
-            if(allThreadNotReady)
+            if(activeThreads.empty())
             {
                 //No thread is ready, run the idle thread
 
                 //This is very important: the idle thread can *remove* dead
                 //threads from threadList, so it can invalidate iterators
                 //to any element except theadList.end()
-                curInRound=0;
+                curInRound=activeThreads.end();
                 cur=idle;
                 ctxsave=cur->ctxsave;
                 #ifdef WITH_PROCESSES
@@ -239,14 +276,15 @@ unsigned int ControlScheduler::IRQfindNextThread()
             }
 
             //End of round reached, run scheduling algorithm
-            curInRound=threadList;
+            //curInRound=threadList;
+            curInRound = activeThreads.front();
             IRQrunRegulator(allReadyThreadsSaturated);
         }
 
-        if(curInRound->flags.isReady())
+        if((*curInRound)->t->flags.isReady())
         {
             //Found a READY thread, so run this one
-            cur=curInRound;
+            cur=(*curInRound)->t;
             #ifdef WITH_PROCESSES
             if(const_cast<Thread*>(cur)->flags.isInUserspace()==false)
             {
@@ -262,78 +300,181 @@ unsigned int ControlScheduler::IRQfindNextThread()
             #endif //WITH_PROCESSES
             //miosix_private::AuxiliaryTimer::IRQsetValue(
             //        curInRound->schedData.bo/multFactor);
-            IRQsetNextPreemption(curInRound->schedData.bo/multFactor);
+            IRQsetNextPreemption(cur->schedData.bo/multFactor);
             return 0;
         } else {
             //If we get here we have a non ready thread that cannot run,
             //so regardless of the burst calculated by the scheduler
             //we do not run it and set Tp to zero.
-            curInRound->schedData.Tp=0;
+            //curInRound->schedData.Tp=0;
+            return UINT_MAX; //This case should not happen, just for debug!
         }
     }
 }
 
+void ControlScheduler::IRQwaitStatusHook(Thread* t)
+{
+    // Managing activeThreads list
+    if (t->flags.isReady() && !t->schedData.lastReadyStatus){
+        // The thread has became active -> put it in the list
+        addThreadToActiveList(&t->schedData.atlEntry);
+        t->schedData.lastReadyStatus = true;
+    }else if (!t->flags.isReady() && t->schedData.lastReadyStatus){
+        // The thread is no longer active -> remove it from the list
+        remThreadfromActiveList(&t->schedData.atlEntry);
+        t->schedData.lastReadyStatus = false;
+    }
+    #ifdef ENABLE_FEEDFORWARD
+    IRQrecalculateAlfa();
+    #endif //ENABLE_FEEDFORWARD
+}
+
 void ControlScheduler::IRQrecalculateAlfa()
 {
     //Sum of all priorities of all threads
     //Note that since priority goes from 0 to PRIORITY_MAX-1
     //but priorities we need go from 1 to PRIORITY_MAX we need to add one
     unsigned int sumPriority=0;
-    for(Thread *it=threadList;it!=0;it=it->schedData.next)
+    //for(Thread *it=threadList;it!=0;it=it->schedData.next)
+    for (auto it = activeThreads.begin() ; it != activeThreads.end() ; it++)
     {
         #ifdef ENABLE_FEEDFORWARD
         //Count only ready threads
-        if(it->flags.isReady())
-            sumPriority+=it->schedData.priority.get()+1;//Add one
+        if((*it)->t->flags.isReady())
+            sumPriority+=(*it)->t->schedData.priority.get()+1;//Add one
         #else //ENABLE_FEEDFORWARD
         //Count all threads
-        sumPriority+=it->schedData.priority.get()+1;//Add one
+        sumPriority+=(*it)->t->schedData.priority.get()+1;//Add one
         #endif //ENABLE_FEEDFORWARD
     }
     //This can happen when ENABLE_FEEDFORWARD is set and no thread is ready
     if(sumPriority==0) return;
     #ifndef SCHED_CONTROL_FIXED_POINT
     float base=1.0f/((float)sumPriority);
-    for(Thread *it=threadList;it!=0;it=it->schedData.next)
+    //for(Thread *it=threadList;it!=0;it=it->schedData.next)
+    for (auto it = activeThreads.begin() ; it != activeThreads.end() ; it++)
     {
         #ifdef ENABLE_FEEDFORWARD
         //Assign zero bursts to blocked threads
-        if(it->flags.isReady())
+        if((*it)->t->flags.isReady())
         {
-            it->schedData.alfa=base*((float)(it->schedData.priority.get()+1));
+            (*it)->t->schedData.alfa=base*((float)((*it)->t->schedData.priority.get()+1));
         } else {
-            it->schedData.alfa=0;
+            (*it)->t->schedData.alfa=0;
         }
         #else //ENABLE_FEEDFORWARD
         //Assign bursts irrespective of thread blocking status
-        it->schedData.alfa=base*((float)(it->schedData.priority.get()+1));
+        (*it)->t->schedData.alfa=base*((float)((*it)->t->schedData.priority.get()+1));
         #endif //ENABLE_FEEDFORWARD
     }
     #else //FIXED_POINT_MATH
     //Sum of all alfa is maximum value for an unsigned short
     unsigned int base=4096/sumPriority;
-    for(Thread *it=threadList;it!=0;it=it->schedData.next)
+    //for(Thread *it=threadList;it!=0;it=it->schedData.next)
+    for (auto it = activeThreads.begin() ; it != activeThreads.end() ; it++)
     {
         #ifdef ENABLE_FEEDFORWARD
         //Assign zero bursts to blocked threads
-        if(it->flags.isReady())
+        if((*it)->t->flags.isReady())
         {
-            it->schedData.alfa=base*(it->schedData.priority.get()+1);
+            (*it)->t->schedData.alfa=base*((*it)->t->schedData.priority.get()+1);
         } else {
-            it->schedData.alfa=0;
+            (*it)->t->schedData.alfa=0;
         }
         #else //ENABLE_FEEDFORWARD
         //Assign bursts irrespective of thread blocking status
-        it->schedData.alfa=base*(it->schedData.priority.get()+1);
+        (*it)->t->schedData.alfa=base*((*it)->t->schedData.priority.get()+1);
         #endif //ENABLE_FEEDFORWARD
     }
     #endif //FIXED_POINT_MATH
     reinitRegulator=true;
 }
 
+void ControlScheduler::IRQrunRegulator(bool allReadyThreadsSaturated)
+{
+    using namespace std;
+    #ifdef SCHED_CONTROL_FIXED_POINT
+    //The fixed point scheduler may overflow if Tr is higher than this
+    Tr=min(Tr,524287);
+    #endif //FIXED_POINT_MATH
+    #ifdef ENABLE_REGULATOR_REINIT
+    if(reinitRegulator==false)
+    {
+    #endif //ENABLE_REGULATOR_REINIT
+        int eTr=SP_Tr-Tr;
+        #ifndef SCHED_CONTROL_FIXED_POINT
+        int bc=bco+static_cast<int>(krr*eTr-krr*zrr*eTro);
+        #else //FIXED_POINT_MATH
+        //Tr is clamped to 524287, so eTr uses at most 19bits. Considering
+        //the 31bits of a signed int, we have 12bits free.
+        const int fixedKrr=static_cast<int>(krr*2048);
+        const int fixedKrrZrr=static_cast<int>(krr*zrr*1024);
+        int bc=bco+(fixedKrr*eTr)/2048-(fixedKrrZrr*eTro)/1024;
+        #endif //FIXED_POINT_MATH
+        if(allReadyThreadsSaturated)
+        {
+            //If all inner regulators reached upper saturation,
+            //allow only a decrease in the burst correction.
+            if(bc<bco) bco=bc;
+        } else bco=bc;
+
+        bco=min<int>(max(bco,-Tr),bMax*threadListSize);
+        #ifndef SCHED_CONTROL_FIXED_POINT
+        float nextRoundTime=static_cast<float>(Tr+bco);
+        #else //FIXED_POINT_MATH
+        unsigned int nextRoundTime=Tr+bco; //Bounded to 20bits
+        #endif //FIXED_POINT_MATH
+        eTro=eTr;
+        Tr=0;//Reset round time
+        for(Thread *it=threadList;it!=0;it=it->schedData.next)
+        {
+            //Recalculate per thread set point
+            #ifndef SCHED_CONTROL_FIXED_POINT
+            it->schedData.SP_Tp=static_cast<int>(
+                    it->schedData.alfa*nextRoundTime);
+            #else //FIXED_POINT_MATH
+            //nextRoundTime is bounded to 20bits, alfa to 12bits,
+            //so the multiplication fits in 32bits
+            it->schedData.SP_Tp=(it->schedData.alfa*nextRoundTime)/4096;
+            #endif //FIXED_POINT_MATH
+
+            //Run each thread internal regulator
+            int eTp=it->schedData.SP_Tp - it->schedData.Tp;
+            //note: since b and bo contain the real value multiplied by
+            //multFactor, this equals b=bo+eTp/multFactor.
+            int b=it->schedData.bo + eTp;
+            //saturation
+            it->schedData.bo=min(max(b,bMin*multFactor),bMax*multFactor);
+        }
+    #ifdef ENABLE_REGULATOR_REINIT
+    } else {
+        reinitRegulator=false;
+        Tr=0;//Reset round time
+        //Reset state of the external regulator
+        eTro=0;
+        bco=0;
+
+        for(Thread *it=threadList;it!=0;it=it->schedData.next)
+        {
+            //Recalculate per thread set point
+            #ifndef SCHED_CONTROL_FIXED_POINT
+            it->schedData.SP_Tp=static_cast<int>(it->schedData.alfa*SP_Tr);
+            #else //FIXED_POINT_MATH
+            //SP_Tr is bounded to 20bits, alfa to 12bits,
+            //so the multiplication fits in 32bits
+            it->schedData.SP_Tp=(it->schedData.alfa*SP_Tr)/4096;
+            #endif //FIXED_POINT_MATH
+
+            int b=it->schedData.SP_Tp*multFactor;
+            it->schedData.bo=min(max(b,bMin*multFactor),bMax*multFactor);
+        }
+    }
+    #endif //ENABLE_REGULATOR_REINIT
+}
+
 Thread *ControlScheduler::threadList=0;
 unsigned int ControlScheduler::threadListSize=0;
-Thread *ControlScheduler::curInRound=0;
+//Thread *ControlScheduler::curInRound=0;
 Thread *ControlScheduler::idle=0;
 int ControlScheduler::SP_Tr=0;
 int ControlScheduler::Tr=bNominal;
diff --git a/miosix/kernel/scheduler/control/control_scheduler.h b/miosix/kernel/scheduler/control/control_scheduler.h
old mode 100644
new mode 100755
index 851ccd87..79221bd6
--- a/miosix/kernel/scheduler/control/control_scheduler.h
+++ b/miosix/kernel/scheduler/control/control_scheduler.h
@@ -130,12 +130,7 @@ public:
      * its running status. For example when a thread become sleeping, waiting,
      * deleted or if it exits the sleeping or waiting status
      */
-    static void IRQwaitStatusHook()
-    {
-        #ifdef ENABLE_FEEDFORWARD
-        IRQrecalculateAlfa();
-        #endif //ENABLE_FEEDFORWARD
-    }
+    static void IRQwaitStatusHook(Thread* t);
 
     /**
      * \internal
@@ -153,7 +148,7 @@ public:
     static unsigned int IRQfindNextThread();
 
 private:
-
+    
     /**
      * \internal
      * When priorities are modified, this function recalculates alfa for each
@@ -165,94 +160,14 @@ private:
      * Called by IRQfindNextThread(), this function is where the control based
      * scheduling algorithm is run. It is called once per round.
      */
-    static void IRQrunRegulator(bool allReadyThreadsSaturated)
-    {
-        using namespace std;
-        #ifdef SCHED_CONTROL_FIXED_POINT
-        //The fixed point scheduler may overflow if Tr is higher than this
-        Tr=min(Tr,524287);
-        #endif //FIXED_POINT_MATH
-        #ifdef ENABLE_REGULATOR_REINIT
-        if(reinitRegulator==false)
-        {
-        #endif //ENABLE_REGULATOR_REINIT
-            int eTr=SP_Tr-Tr;
-            #ifndef SCHED_CONTROL_FIXED_POINT
-            int bc=bco+static_cast<int>(krr*eTr-krr*zrr*eTro);
-            #else //FIXED_POINT_MATH
-            //Tr is clamped to 524287, so eTr uses at most 19bits. Considering
-            //the 31bits of a signed int, we have 12bits free.
-            const int fixedKrr=static_cast<int>(krr*2048);
-            const int fixedKrrZrr=static_cast<int>(krr*zrr*1024);
-            int bc=bco+(fixedKrr*eTr)/2048-(fixedKrrZrr*eTro)/1024;
-            #endif //FIXED_POINT_MATH
-            if(allReadyThreadsSaturated)
-            {
-                //If all inner regulators reached upper saturation,
-                //allow only a decrease in the burst correction.
-                if(bc<bco) bco=bc;
-            } else bco=bc;
-
-            bco=min<int>(max(bco,-Tr),bMax*threadListSize);
-            #ifndef SCHED_CONTROL_FIXED_POINT
-            float nextRoundTime=static_cast<float>(Tr+bco);
-            #else //FIXED_POINT_MATH
-            unsigned int nextRoundTime=Tr+bco; //Bounded to 20bits
-            #endif //FIXED_POINT_MATH
-            eTro=eTr;
-            Tr=0;//Reset round time
-            for(Thread *it=threadList;it!=0;it=it->schedData.next)
-            {
-                //Recalculate per thread set point
-                #ifndef SCHED_CONTROL_FIXED_POINT
-                it->schedData.SP_Tp=static_cast<int>(
-                        it->schedData.alfa*nextRoundTime);
-                #else //FIXED_POINT_MATH
-                //nextRoundTime is bounded to 20bits, alfa to 12bits,
-                //so the multiplication fits in 32bits
-                it->schedData.SP_Tp=(it->schedData.alfa*nextRoundTime)/4096;
-                #endif //FIXED_POINT_MATH
-
-                //Run each thread internal regulator
-                int eTp=it->schedData.SP_Tp - it->schedData.Tp;
-                //note: since b and bo contain the real value multiplied by
-                //multFactor, this equals b=bo+eTp/multFactor.
-                int b=it->schedData.bo + eTp;
-                //saturation
-                it->schedData.bo=min(max(b,bMin*multFactor),bMax*multFactor);
-            }
-        #ifdef ENABLE_REGULATOR_REINIT
-        } else {
-            reinitRegulator=false;
-            Tr=0;//Reset round time
-            //Reset state of the external regulator
-            eTro=0;
-            bco=0;
-
-            for(Thread *it=threadList;it!=0;it=it->schedData.next)
-            {
-                //Recalculate per thread set point
-                #ifndef SCHED_CONTROL_FIXED_POINT
-                it->schedData.SP_Tp=static_cast<int>(it->schedData.alfa*SP_Tr);
-                #else //FIXED_POINT_MATH
-                //SP_Tr is bounded to 20bits, alfa to 12bits,
-                //so the multiplication fits in 32bits
-                it->schedData.SP_Tp=(it->schedData.alfa*SP_Tr)/4096;
-                #endif //FIXED_POINT_MATH
-
-                int b=it->schedData.SP_Tp*multFactor;
-                it->schedData.bo=min(max(b,bMin*multFactor),bMax*multFactor);
-            }
-        }
-        #endif //ENABLE_REGULATOR_REINIT
-    }
+    static void IRQrunRegulator(bool allReadyThreadsSaturated);
 
     ///\internal Threads (except idle thread) are stored here
     static Thread *threadList;
     static unsigned int threadListSize;
 
-    ///\internal current thread in the round
-    static Thread *curInRound;
+    ///\internal the entry of current thread in the round in the activeThreads list
+    //static IntrusiveList<ThreadsListItem>::iterator curInRound;
 
     ///\internal idle thread
     static Thread *idle;
diff --git a/miosix/kernel/scheduler/control/control_scheduler_types.h b/miosix/kernel/scheduler/control/control_scheduler_types.h
old mode 100644
new mode 100755
index c21a34dd..c1cc1284
--- a/miosix/kernel/scheduler/control/control_scheduler_types.h
+++ b/miosix/kernel/scheduler/control/control_scheduler_types.h
@@ -27,6 +27,7 @@
 
 #include "config/miosix_settings.h"
 #include "parameters.h"
+#include "kernel/intrusive.h"
 
 #ifndef CONTROL_SCHEDULER_TYPES_H
 #define	CONTROL_SCHEDULER_TYPES_H
@@ -37,6 +38,31 @@ namespace miosix {
 
 class Thread; //Forward declaration
 
+/**
+ * Real-time priority definitions 
+ * Applied to realtime field of ControlSchedulerPriority class.
+ * 
+ * When a thread wakes up (due to a prior Thread::sleep or waiting
+ * for a hardware irq or etc.), the actual time the thread will have
+ * its burst remainder will depend on the real-time priority set for it.
+ */
+/**
+ * REALTIME_PRIORITY_IMMEDIATE: The processor control is transfered to the thread
+ * right in the time it wakes up.
+ */
+#define REALTIME_PRIORITY_IMMEDIATE 1
+/**
+ * REALTIME_PRIORITY_NEXT_BURST: The processor control is transfered to the thread
+ * right after the current running thread has consumed its burst time.
+ */
+#define REALTIME_PRIORITY_NEXT_BURST 2
+/**
+ * REALTIME_PRIORITY_NEXT_ROUND: The processor control is transfered to the thread
+ * in the next round and the thread is delayed until all remaining active threads
+ * are run.
+ */
+#define REALTIME_PRIORITY_NEXT_ROUND 3
+
 /**
  * This class models the concept of priority for the control based scheduler.
  * In this scheduler the priority is simply a short int with values ranging
@@ -52,8 +78,11 @@ public:
      * Constructor. Not explicit for backward compatibility.
      * \param priority the desired priority value.
      */
-    ControlSchedulerPriority(short int priority): priority(priority) {}
-
+    ControlSchedulerPriority(short int priority): priority(priority), 
+            realtime(REALTIME_PRIORITY_NEXT_ROUND) {}
+    
+    ControlSchedulerPriority(short int priority, short int realtime):
+            priority(priority),realtime(realtime){}
     /**
      * Default constructor.
      */
@@ -63,6 +92,8 @@ public:
      * \return the priority value
      */
     short int get() const { return priority; }
+    
+    short int getRealtime() const {return realtime; }
 
     /**
      * \return true if this objects represents a valid priority.
@@ -71,16 +102,18 @@ public:
      */
     bool validate() const
     {
-        return this->priority>=0 && this->priority<PRIORITY_MAX;
+        return this->priority>=0 && this->priority<PRIORITY_MAX && 
+                this->realtime >=1 && this->realtime<=3;
     }
 
 private:
     short int priority;///< The priority value
+    short int realtime;///< The realtime priority value
 };
 
 inline bool operator <(ControlSchedulerPriority a, ControlSchedulerPriority b)
 {
-    return a.get() < b.get();
+    return a.getRealtime() < b.getRealtime();
 }
 
 inline bool operator <=(ControlSchedulerPriority a, ControlSchedulerPriority b)
@@ -108,6 +141,12 @@ inline bool operator !=(ControlSchedulerPriority a, ControlSchedulerPriority b)
     return a.get() != b.get();
 }
 
+struct ThreadsListItem : public IntrusiveListItem
+{
+    ThreadsListItem(): t(0) {}
+    Thread *t;
+};
+
 /**
  * \internal
  * An instance of this class is embedded in every Thread class. It contains all
@@ -131,6 +170,8 @@ public:
     int SP_Tp;//Processing time set point
     int Tp;//Real processing time
     Thread *next;//Next thread in list
+    ThreadsListItem atlEntry; //Entry in activeThreads list
+    bool lastReadyStatus;
 };
 
 } //namespace miosix
diff --git a/miosix/kernel/scheduler/edf/edf_scheduler.h b/miosix/kernel/scheduler/edf/edf_scheduler.h
old mode 100644
new mode 100755
index e4921bcb..bdabd031
--- a/miosix/kernel/scheduler/edf/edf_scheduler.h
+++ b/miosix/kernel/scheduler/edf/edf_scheduler.h
@@ -120,7 +120,7 @@ public:
      * its running status. For example when a thread become sleeping, waiting,
      * deleted or if it exits the sleeping or waiting status
      */
-    static void IRQwaitStatusHook() {}
+    static void IRQwaitStatusHook(Thread *t) {}
 
     /**
      * This function is used to develop interrupt driven peripheral drivers.<br>
diff --git a/miosix/kernel/scheduler/priority/priority_scheduler.cpp b/miosix/kernel/scheduler/priority/priority_scheduler.cpp
index e5aed7b5..a07e837c 100644
--- a/miosix/kernel/scheduler/priority/priority_scheduler.cpp
+++ b/miosix/kernel/scheduler/priority/priority_scheduler.cpp
@@ -29,7 +29,6 @@
 #include "kernel/error.h"
 #include "kernel/process.h"
 #include "interfaces/cstimer.h"
-#include "kernel/timeconversion.h"
 #include <limits>
 
 #ifdef SCHED_TYPE_PRIORITY
diff --git a/miosix/kernel/scheduler/priority/priority_scheduler.h b/miosix/kernel/scheduler/priority/priority_scheduler.h
old mode 100644
new mode 100755
index d8e5539e..24b2a3cf
--- a/miosix/kernel/scheduler/priority/priority_scheduler.h
+++ b/miosix/kernel/scheduler/priority/priority_scheduler.h
@@ -122,7 +122,7 @@ public:
      * its running status. For example when a thread become sleeping, waiting,
      * deleted or if it exits the sleeping or waiting status
      */
-    static void IRQwaitStatusHook() {}
+    static void IRQwaitStatusHook(Thread* t) {}
 
     /**
      * \internal
diff --git a/miosix/kernel/scheduler/scheduler.h b/miosix/kernel/scheduler/scheduler.h
old mode 100644
new mode 100755
index f1fbb8ed..047bc49f
--- a/miosix/kernel/scheduler/scheduler.h
+++ b/miosix/kernel/scheduler/scheduler.h
@@ -147,9 +147,9 @@ public:
      * its running status. For example when a thread become sleeping, waiting,
      * deleted or if it exits the sleeping or waiting status
      */
-    static void IRQwaitStatusHook()
+    static void IRQwaitStatusHook(Thread *t)
     {
-        T::IRQwaitStatusHook();
+        T::IRQwaitStatusHook(t);
     }
 
     /**
-- 
GitLab