[En-Nut-Discussion] Patch proposed: Catch more NutEventPostFromIRQ events in time

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Mon Mar 9 19:50:16 CET 2015


Hello,

there is quite some window of our timeslice, where NutEventPostFromIRQ()
might go unnoticed until the next timer event(window of ignorance). Also we
have work to do, NutOS sleeps until the next timer interrupt.

This windows opens when in the idle thread the thread now signaled has
already been checked by NutThreadResume(). To counteract, I proposed to keep
track of all posted and sent irq events in a global variable and deny
sleeping as long as this variable is not zero. For AVR8, the size of the
variable needs to be considered, for most other arch "int" should fit fine.

Appended patch proposes a solution, with the actual denial of sleep only
done for CM3. The window of ignorance now is much smaller.
This brings down some SPI workload from about 140 ms to 100
ms with no gaps seen.

Feedback welcome!

-- 
Uwe Bonnes                bon at elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
diff --git a/nut/arch/cm3/os/nutinit.c b/nut/arch/cm3/os/nutinit.c
index 77143a1..96b2af7 100644
--- a/nut/arch/cm3/os/nutinit.c
+++ b/nut/arch/cm3/os/nutinit.c
@@ -227,7 +227,8 @@ THREAD(ATTRIBUTE_NUTINIT_SECTION NutIdle, arg)
         /* Sleep Mode*/
 #endif
         HEARTBEAT_IDLE();
-        __WFI();
+        if(0 == total_pending)
+            __WFI();
         HEARTBEAT_ACTIVE();
     }
 }
diff --git a/nut/include/sys/event.h b/nut/include/sys/event.h
index 471407c..9db6f46 100644
--- a/nut/include/sys/event.h
+++ b/nut/include/sys/event.h
@@ -95,6 +95,7 @@
  */
 
 #include <sys/thread.h>
+#include <sys/atom.h>
 
 /*!
  * \file sys/event.h
@@ -151,7 +152,10 @@
     }                               \
     else if (*qp != SIGNALED) {     \
         NUTTHREADINFO *tp = (NUTTHREADINFO *)(*qp);    \
+        NutEnterCritical();\
         tp->td_qpec++;              \
+        total_pending++;\
+        NutExitCritical();\
     }                               \
 }
 
diff --git a/nut/include/sys/thread.h b/nut/include/sys/thread.h
index 21e1846..76edbce 100644
--- a/nut/include/sys/thread.h
+++ b/nut/include/sys/thread.h
@@ -245,6 +245,8 @@ extern NUTTHREADINFO *nutThreadList;
  */
 extern NUTTHREADINFO *runQueue;
 
+extern volatile int16_t total_pending;
+
 #ifndef __NUT_EMULATION__
 /*!
  * \private
diff --git a/nut/os/thread.c b/nut/os/thread.c
index 850ae4c..98595bb 100644
--- a/nut/os/thread.c
+++ b/nut/os/thread.c
@@ -105,6 +105,8 @@ NUTTHREADINFO * nutThreadList;
 
 NUTTHREADINFO * runQueue;
 
+volatile int16_t total_pending;
+
 void NutThreadAddPriQueue(NUTTHREADINFO * td, NUTTHREADINFO * volatile *tqpp)
 {
     NUTTHREADINFO *tqp;
@@ -125,6 +127,7 @@ void NutThreadAddPriQueue(NUTTHREADINFO * td, NUTTHREADINFO * volatile *tqpp)
     if (tqp == SIGNALED) {
         tqp = 0;
         td->td_qpec++;          // transfer the signaled state
+        total_pending ++;
     } else if (tqp) {
         NutExitCritical();      // there are other threads in queue
                         // so its save to leave critical.
@@ -199,6 +202,7 @@ void NutThreadResume(void)
             qhp = (NUTTHREADINFO **)(td->td_queue);
             NutEnterCritical();
             td->td_qpec--;
+            total_pending--;
             tqp = *qhp;
             NutExitCritical();
             if (tqp != SIGNALED) {


More information about the En-Nut-Discussion mailing list