changeset 2266:13625e7b9d1f

Implement FIFO variant of scheduling of DSRs and make it the default. This is reworked patch originally suggested by Stefan Sommerfeld <sommerfeld@mikrom.com>. * cdl/interrupts.cdl (CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST): make it cdl_component. * cdl/interrupts.cdl (CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO): new option for CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST. * include/intr.hxx (class Cyg_Interrupt): new static variable dsr_list_tail. * src/intr/intr.cxx (call_pending_DSRs_inner): add CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO variant. (post_dsr): likewise. * tests/intr0.cxx: fix comments to match actual option names. * tests/kintr0.c: likewise.2006-03-27 Marco Cruz <marco@daruma.com.br>
author nickg
date Fri, 11 Aug 2006 09:29:31 +0000
parents b5670f3c40f2
children ce8216bec66a
files packages/hal/sh/arch/current/src/context.S packages/kernel/current/ChangeLog packages/kernel/current/cdl/interrupts.cdl packages/kernel/current/include/intr.hxx packages/kernel/current/src/intr/intr.cxx packages/kernel/current/tests/intr0.cxx packages/kernel/current/tests/kintr0.c
diffstat 7 files changed, 115 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/packages/hal/sh/arch/current/src/context.S
+++ b/packages/hal/sh/arch/current/src/context.S
@@ -240,11 +240,11 @@ FUNC_START(hal_thread_load_context)
         
         lds.l   @r0+,pr                 ! pr
 
-        mov     r3,r15                  ! update stack pointer
-
         mov.l   @r0+,r2                 ! SR
         hal_cpu_int_merge r2,r0,r1      ! restore interrupt state
 
+        mov     r3,r15                  ! update stack pointer
+
         rts                             ! and return
          nop
 
--- a/packages/kernel/current/ChangeLog
+++ b/packages/kernel/current/ChangeLog
@@ -11,6 +11,24 @@ 2006-04-11  Sergei Organov <osv@javad.co
 
 	* doc/kernel.sgml: Fix typo
 
+2006-04-10  Sergei Organov  <osv@javad.com>
+
+	Implement FIFO variant of scheduling of DSRs and make it the
+	default. This is reworked patch originally suggested by Stefan
+	Sommerfeld <sommerfeld@mikrom.com>.
+
+	* cdl/interrupts.cdl (CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST): make it
+	cdl_component.
+	* cdl/interrupts.cdl (CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO):
+	new option for CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST.
+	* include/intr.hxx (class Cyg_Interrupt): new static variable
+	dsr_list_tail.
+	* src/intr/intr.cxx (call_pending_DSRs_inner): add
+	CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO variant.
+	(post_dsr): likewise.
+	* tests/intr0.cxx: fix comments to match actual option names.
+	* tests/kintr0.c: likewise.2006-03-27  Marco Cruz  <marco@daruma.com.br>
+	
 2006-03-27  Marco Cruz  <marco@daruma.com.br>
 
 	* include/thread.hxx: removed extra qualifier of
--- a/packages/kernel/current/cdl/interrupts.cdl
+++ b/packages/kernel/current/cdl/interrupts.cdl
@@ -74,7 +74,7 @@ cdl_component CYGIMP_KERNEL_INTERRUPTS_D
     # NOTE: the choice of list vs table should not be two separate
     # options. There is a single option which must have one of
     # two legal values.
-    cdl_option CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST {
+    cdl_component CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST {
         display       "Use linked lists for DSRs"
         default_value 1
         implements    CYGINT_KERNEL_INTERRUPTS_DSRS
@@ -85,6 +85,22 @@ cdl_component CYGIMP_KERNEL_INTERRUPTS_D
             requires that the kernel disable interrupts for a very short
             period of time outside interrupt handlers, but there is no
             possibility of a table overflow occurring."
+
+        cdl_option CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO {
+            display       "Schedule DSRs in FIFO order"
+            flavor        bool
+            default_value 1
+            description   "When this option is set, DSRs are scheduled
+                in the natural FIFO (first in, first out) order,
+                otherwise they are scheduled in LIFO (last in, first
+                out) order. Applications should not rely on any
+                particular order of scheduling of DSRs. LIFO
+                scheduling is kept for backward compatibility only and
+                is not recommended as it may lead to high (up to 2
+                times higher then FIFO) IRQ-to-DSR latencies at some
+                (typically rare) conditions. If unsure, leave this set."
+        }
+
     }
 
     cdl_component CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE {
--- a/packages/kernel/current/include/intr.hxx
+++ b/packages/kernel/current/include/intr.hxx
@@ -195,11 +195,17 @@ class Cyg_Interrupt
     // next DSR in list
     Cyg_Interrupt* volatile next_dsr CYGBLD_ANNOTATE_VARIABLE_INTR; 
 
-    // static list of pending DSRs
+    // head of static list of pending DSRs
     static Cyg_Interrupt* volatile dsr_list[CYGNUM_KERNEL_CPU_MAX]
                                            CYGBLD_ANNOTATE_VARIABLE_INTR;
-    
-#endif
+
+#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+    // tail of static list of pending DSRs
+    static Cyg_Interrupt* volatile dsr_list_tail[CYGNUM_KERNEL_CPU_MAX]
+                                           CYGBLD_ANNOTATE_VARIABLE_INTR;
+#  endif
+
+#endif  // defined  CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
 
 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
 
--- a/packages/kernel/current/src/intr/intr.cxx
+++ b/packages/kernel/current/src/intr/intr.cxx
@@ -137,6 +137,10 @@ volatile cyg_ucount32 Cyg_Interrupt::dsr
 
 Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list[CYGNUM_KERNEL_CPU_MAX];
 
+#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list_tail[CYGNUM_KERNEL_CPU_MAX];
+#  endif
+
 #endif
 
 // -------------------------------------------------------------------------
@@ -170,6 +174,35 @@ Cyg_Interrupt::call_pending_DSRs_inner(v
 
 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
 
+#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+
+    cyg_uint32 old_intr;
+    HAL_DISABLE_INTERRUPTS(old_intr);
+    Cyg_Interrupt* intr = dsr_list[cpu];
+    CYG_ASSERT(intr != 0, "No DSRs are pended");
+    dsr_list[cpu] = 0;
+    dsr_list_tail[cpu] = 0;
+    while(true)
+    {
+        cyg_count32 count = intr->dsr_count;
+        Cyg_Interrupt* next = intr->next_dsr;
+        intr->dsr_count = 0;
+        intr->next_dsr = 0;
+        HAL_RESTORE_INTERRUPTS(old_intr);
+
+        CYG_ASSERT(intr->dsr != 0, "No DSR defined");
+        CYG_ASSERT(count > 0, "DSR posted but post count is zero");
+        intr->dsr(intr->vector, count, (CYG_ADDRWORD)intr->data);
+
+        if (!next)
+            break;
+
+        intr = next;
+        HAL_DISABLE_INTERRUPTS(old_intr);
+    }
+
+#  else // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+    
     while( dsr_list[cpu] != NULL )
     {
         Cyg_Interrupt* intr;
@@ -191,8 +224,10 @@ Cyg_Interrupt::call_pending_DSRs_inner(v
         
     }
     
-#endif
-    
+#  endif  // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+
+#endif  // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
+
 };
 
 externC void
@@ -245,17 +280,39 @@ Cyg_Interrupt::post_dsr(void)
 
     // Only add the interrupt to the dsr list if this is
     // the first DSR call.
-    // At present DSRs are pushed onto the list and will be
-    // called in reverse order. We do not define the order
-    // in which DSRs are called, so this is acceptable.
-    
     if( dsr_count++ == 0 )
     {
+#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+
+        // Add to the tail of the list.
+        Cyg_Interrupt* tail = dsr_list_tail[cpu];
+        dsr_list_tail[cpu] = this;
+        if( tail )
+        {
+            CYG_ASSERT( 0 != dsr_list[cpu] ,
+              "DSR list is not empty but its head is 0");
+            tail->next_dsr = this;
+        }
+        else
+        {
+            CYG_ASSERT( 0 == dsr_list[cpu] ,
+              "DSR list tail is 0 but its head is not");
+            dsr_list[cpu] = this;
+        }
+
+#  else   // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+
+        // At present DSRs are pushed onto the list and will be called
+        // in reverse order. We do not define the order in which DSRs
+        // are called, so this is acceptable.
         next_dsr = dsr_list[cpu];
         dsr_list[cpu] = this;
+
+#  endif  // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
+
     }
-    
-#endif
+
+#endif  // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
     
     HAL_RESTORE_INTERRUPTS(old_intr);    
 };
--- a/packages/kernel/current/tests/intr0.cxx
+++ b/packages/kernel/current/tests/intr0.cxx
@@ -46,8 +46,9 @@
 // Description:   Very basic test of interrupt objects
 // Options:
 //     CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
-//     CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE
+//     CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE
 //     CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
+//     CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
 //####DESCRIPTIONEND####
 
 #include <pkgconf/kernel.h>
--- a/packages/kernel/current/tests/kintr0.c
+++ b/packages/kernel/current/tests/kintr0.c
@@ -46,8 +46,9 @@
 // Description:   Very basic test of interrupt objects
 // Options:
 //     CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
-//     CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE_MAX
+//     CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE
 //     CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
+//     CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
 //####DESCRIPTIONEND####
 */