From 9c690222486361b7b14a824ee88c18fa7df39e0a Mon Sep 17 00:00:00 2001
From: Sasan Golchin <ahmad.golchin@mail.polimi.it>
Date: Thu, 26 May 2016 17:29:13 +0200
Subject: [PATCH] Context Switch time optimization (reduced by 0.6 us)

---
 miosix/kernel/intrusive.h | 198 +++++++++++++++++---------------------
 miosix/kernel/kernel.cpp  |  30 ++++--
 2 files changed, 114 insertions(+), 114 deletions(-)

diff --git a/miosix/kernel/intrusive.h b/miosix/kernel/intrusive.h
index 18c26560..1031d57f 100644
--- a/miosix/kernel/intrusive.h
+++ b/miosix/kernel/intrusive.h
@@ -694,30 +694,114 @@ public:
         emptyListItem.prev = &emptyListItem;
     }
     
-    void push_back(T *item);
+    void push_back(T *item)
+    {
+        item->next = &emptyListItem;
+        item->prev = tail;
+        tail = item;
+        emptyListItem.prev = item;
+        if(head==&emptyListItem)
+        {
+            head = tail;
+            emptyListItem.next = head;
+        } else item->prev->next = item;
+    }
     
     /**
      * Removes the last element in the list.
      */
-    void pop_back();
+    void pop_back()
+    {
+        if(tail == head)
+        {
+            //Note: this is safe also in the case of pop_back of an empty list
+            //by mistake
+            removeLastItem();
+        } else {
+            tail->prev->next = &emptyListItem;
+            emptyListItem.prev = tail->prev;
+            tail->prev = nullptr;
+            tail->next = nullptr;
+            tail = static_cast<T*>(emptyListItem.prev);
+        }   
+    }
     
-    void push_front(T *item);
+    void push_front(T *item)
+    {
+        item->prev = &emptyListItem;
+        if(head != &emptyListItem)
+        {
+            item->next = head;
+            item->next->prev = item;
+            emptyListItem.next = item;
+        } else {
+            item->next = &emptyListItem;
+            tail = item;
+            emptyListItem.prev = item;
+            emptyListItem.next = item;
+        }
+        head = item;
+    }
     
     /**
      * Removes the first item (head) of the list.
      */
-    void pop_front();
+    void pop_front()
+    {
+        if(tail == head)
+        {
+            //Note: this is safe also in the case of pop_back of an empty list
+            //by mistake
+            removeLastItem();
+        } else {
+            head->next->prev = &emptyListItem;
+            head->prev = nullptr;
+            emptyListItem.next = head->next;
+            head->next = nullptr;
+            head = static_cast<T*>(emptyListItem.next);
+        }   
+    }
     
     /**
      * Inserts the given item before the position indicated by the iterator
      */
-    void insert(iterator position, T *item);
+    void insert(iterator position, T *item)
+    {
+        if(head==&emptyListItem)
+        {
+            head = item;
+            tail = item;
+            item->next = &emptyListItem;
+            item->prev = &emptyListItem;
+            emptyListItem.next = item;
+            emptyListItem.prev = item;
+            return;
+        }
+        item->next = static_cast<IntrusiveListItem *>(*position); //FIXME: do we need this upcast?
+        item->prev = static_cast<IntrusiveListItem *>(*position)->prev;
+        item->prev->next = item;
+        (*position)->prev = item;
+        if(item->prev == &emptyListItem) head = item;
+        if(item->next == &emptyListItem) tail = item;
+    }
     
     /**
      * Removes the specified item from the list.
      * @param an iterator to the next item
      */
-    iterator erase(iterator it);
+    iterator erase(iterator it)
+    {
+        if((*it)==&emptyListItem) return it;
+        iterator result = it;
+        result++;
+        (*it)->next->prev = (*it)->prev;
+        (*it)->prev->next = (*it)->next;
+        (*it)->next = nullptr;
+        (*it)->prev = nullptr;
+        head = static_cast<T*>(emptyListItem.next);
+        tail = static_cast<T*>(emptyListItem.prev);
+        return result;
+    }
     
     iterator begin()
     {
@@ -760,108 +844,6 @@ private:
     T emptyListItem;
 };
 
-template<typename T>
-void IntrusiveList<T>::push_back(T *item)
-{
-    item->next = &emptyListItem;
-    item->prev = tail;
-    tail = item;
-    emptyListItem.prev = item;
-    if(head==&emptyListItem)
-    {
-        head = tail;
-        emptyListItem.next = head;
-    } else item->prev->next = item;
-}
-
-template<typename T>
-void IntrusiveList<T>::pop_back()
-{
-    if(tail == head)
-    {
-        //Note: this is safe also in the case of pop_back of an empty list
-        //by mistake
-        removeLastItem();
-    } else {
-        tail->prev->next = &emptyListItem;
-        emptyListItem.prev = tail->prev;
-        tail->prev = nullptr;
-        tail->next = nullptr;
-        tail = static_cast<T*>(emptyListItem.prev);
-    }   
-}
-
-template<typename T>
-void IntrusiveList<T>::push_front(T *item)
-{
-    item->prev = &emptyListItem;
-    if(head != &emptyListItem)
-    {
-        item->next = head;
-        item->next->prev = item;
-        emptyListItem.next = item;
-    } else {
-        item->next = &emptyListItem;
-        tail = item;
-        emptyListItem.prev = item;
-        emptyListItem.next = item;
-    }
-    head = item;
-}
-
-template<typename T>
-void IntrusiveList<T>::pop_front()
-{
-    if(tail == head)
-    {
-        //Note: this is safe also in the case of pop_back of an empty list
-        //by mistake
-        removeLastItem();
-    } else {
-        head->next->prev = &emptyListItem;
-        head->prev = nullptr;
-        emptyListItem.next = head->next;
-        head->next = nullptr;
-        head = static_cast<T*>(emptyListItem.next);
-    }   
-}
-
-template<typename T>
-void IntrusiveList<T>::insert(iterator position, T *item)
-{
-    if(head==&emptyListItem)
-    {
-        head = item;
-        tail = item;
-        item->next = &emptyListItem;
-        item->prev = &emptyListItem;
-        emptyListItem.next = item;
-        emptyListItem.prev = item;
-        return;
-    }
-    item->next = static_cast<IntrusiveListItem *>(*position); //FIXME: do we need this upcast?
-    item->prev = static_cast<IntrusiveListItem *>(*position)->prev;
-    item->prev->next = item;
-    (*position)->prev = item;
-    if(item->prev == &emptyListItem) head = item;
-    if(item->next == &emptyListItem) tail = item;
-}
-
-template<typename T>
-typename IntrusiveList<T>::iterator IntrusiveList<T>::erase(iterator it)
-{
-    if((*it)==&emptyListItem) return it;
-    iterator result = it;
-    result++;
-    (*it)->next->prev = (*it)->prev;
-    (*it)->prev->next = (*it)->next;
-    (*it)->next = nullptr;
-    (*it)->prev = nullptr;
-    head = static_cast<T*>(emptyListItem.next);
-    tail = static_cast<T*>(emptyListItem.prev);
-    return result;
-}
-
 } //namespace miosix
 
 #endif //INTRUSIVE_H
diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp
index 81fae38d..6a940657 100644
--- a/miosix/kernel/kernel.cpp
+++ b/miosix/kernel/kernel.cpp
@@ -67,6 +67,8 @@ static volatile bool exist_deleted=false;
 
 static IntrusiveList<SleepData> *sleepingList=nullptr;///list of sleeping threads
 
+static ContextSwitchTimer *timer = nullptr; // FIXME please
+
 #ifndef USE_CSTIMER
 static volatile long long tick=0;///<\internal Kernel tick
 #endif //USE_CSTIMER
@@ -175,6 +177,7 @@ bool areInterruptsEnabled()
 
 void startKernel()
 {
+    timer = &ContextSwitchTimer::instance();
     sleepingList = new(std::nothrow) IntrusiveList<SleepData>;
     csRecord = new(std::nothrow) SleepData;
     if(sleepingList==nullptr || csRecord==nullptr)
@@ -219,10 +222,10 @@ void startKernel()
     // Dispatch the task to the architecture-specific function
     #ifdef USE_CSTIMER
     // Set the first checkpoint interrupt
-    csRecord->p = 0;
+    csRecord->p = nullptr;
     csRecord->wakeup_time = CSQUANTUM;
     sleepingList->push_front(csRecord);
-    miosix::ContextSwitchTimer::instance().IRQsetNextInterrupt(CSQUANTUM);
+    timer->IRQsetNextInterrupt(CSQUANTUM);
     #endif //USE_CSTIMER
     miosix_private::IRQportableStartKernel();
     kernel_started=true;
@@ -251,7 +254,7 @@ long long getTick()
         if(a==b) return a;
     }
     #else //USE_CSTIMER
-    return ContextSwitchTimer::instance().getCurrentTick();
+    return timer->getCurrentTick();
     #endif //USE_CSTIMER
 }
 
@@ -279,7 +282,7 @@ void IRQaddToSleepingList(SleepData *x)
     //Upon any change to the sleepingList the ContextSwitchTimer should have
     //its interrupt set to the head of the list in order to keep it sync with
     //the list
-    ContextSwitchTimer::instance().IRQsetNextInterrupt(sleepingList->front()->wakeup_time);
+    timer->IRQsetNextInterrupt(sleepingList->front()->wakeup_time);
 #endif
 }
 
@@ -289,12 +292,27 @@ void IRQaddToSleepingList(SleepData *x)
  */
 void IRQsetNextPreemption(long long preemptionTime)
 {
+#ifdef USE_CSTIMER
     // Remove all the preemption points from the list
     IntrusiveList<SleepData>::iterator it(csRecord);
     sleepingList->erase(it);
-    //
+    
+    //This piece of code is a duplication of IRQaddToSleepingList
+    //that is in-lined for performance issues
     csRecord->wakeup_time = preemptionTime;
-    IRQaddToSleepingList(csRecord); //It would also set the next timer interrupt
+    if(sleepingList->empty() || sleepingList->front()->wakeup_time >= preemptionTime)
+    {
+        sleepingList->push_front(csRecord);
+    } else {
+        auto it = sleepingList->begin();
+        while (it != sleepingList->end() && (*it)->wakeup_time < preemptionTime ) ++it;
+        sleepingList->insert(it,csRecord);
+    }
+    //Upon any change to the sleepingList the ContextSwitchTimer should have
+    //its interrupt set to the head of the list in order to keep it sync with
+    //the list
+    timer->IRQsetNextInterrupt(sleepingList->front()->wakeup_time);
+#endif
 }
 /**
  * \internal
-- 
GitLab