[PATCH 2/3] bsps: SMP support for generic interrupt support

Sebastian Huber sebastian.huber at embedded-brains.de
Mon Mar 3 15:29:17 UTC 2014


---
 c/src/lib/libbsp/shared/include/irq-generic.h |   30 ++++++++++++++--
 c/src/lib/libbsp/shared/src/irq-generic.c     |   47 +++++++++++++++++-------
 2 files changed, 59 insertions(+), 18 deletions(-)

diff --git a/c/src/lib/libbsp/shared/include/irq-generic.h b/c/src/lib/libbsp/shared/include/irq-generic.h
index 82267f4..0bb4e44 100644
--- a/c/src/lib/libbsp/shared/include/irq-generic.h
+++ b/c/src/lib/libbsp/shared/include/irq-generic.h
@@ -9,10 +9,10 @@
 /*
  * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
  *
- * Copyright (c) 2008-2012 embedded brains GmbH.
+ * Copyright (c) 2008-2014 embedded brains GmbH.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -29,6 +29,10 @@
 
 #include <rtems/irq-extension.h>
 
+#ifdef RTEMS_SMP
+  #include <rtems/score/atomic.h>
+#endif
+
 #include <bsp/irq.h>
 
 #ifdef __cplusplus
@@ -54,6 +58,17 @@ extern "C" {
   #define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_NUMBER
 #endif
 
+/* Internal macros for SMP support, do not use externally */
+#ifdef RTEMS_SMP
+  #define bsp_interrupt_disable(level) do { (void) level; } while (0)
+  #define bsp_interrupt_enable(level) do { } while (0)
+  #define bsp_interrupt_fence(order) _Atomic_Fence(order)
+#else
+  #define bsp_interrupt_disable(level) rtems_interrupt_disable(level)
+  #define bsp_interrupt_enable(level) rtems_interrupt_enable(level)
+  #define bsp_interrupt_fence(order) do { } while (0)
+#endif
+
 struct bsp_interrupt_handler_entry {
   rtems_interrupt_handler handler;
   void *arg;
@@ -238,11 +253,18 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector);
 static inline void bsp_interrupt_handler_dispatch(rtems_vector_number vector)
 {
   if (bsp_interrupt_is_valid_vector(vector)) {
-    bsp_interrupt_handler_entry *e =
+    const bsp_interrupt_handler_entry *e =
       &bsp_interrupt_handler_table [bsp_interrupt_handler_index(vector)];
 
     do {
-      (*e->handler)(e->arg);
+      rtems_interrupt_handler handler;
+      void *arg;
+
+      arg = e->arg;
+      bsp_interrupt_fence(ATOMIC_ORDER_ACQUIRE);
+      handler = e->handler;
+      (*handler)(arg);
+
       e = e->next;
     } while (e != NULL);
   } else {
diff --git a/c/src/lib/libbsp/shared/src/irq-generic.c b/c/src/lib/libbsp/shared/src/irq-generic.c
index 610fe40..0343ccb 100644
--- a/c/src/lib/libbsp/shared/src/irq-generic.c
+++ b/c/src/lib/libbsp/shared/src/irq-generic.c
@@ -9,10 +9,10 @@
 /*
  * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
  *
- * Copyright (c) 2008-2012 embedded brains GmbH.
+ * Copyright (c) 2008-2014 embedded brains GmbH.
  *
  *  embedded brains GmbH
- *  Obere Lagerstr. 30
+ *  Dornierstr. 4
  *  82178 Puchheim
  *  Germany
  *  <rtems at embedded-brains.de>
@@ -49,6 +49,13 @@ static void bsp_interrupt_handler_empty(void *arg)
   bsp_interrupt_handler_default(vector);
 }
 
+#ifdef RTEMS_SMP
+  static void bsp_interrupt_handler_do_nothing(void *arg)
+  {
+    (void) arg;
+  }
+#endif
+
 static inline bool bsp_interrupt_is_handler_unique(rtems_vector_number index)
 {
   rtems_vector_number i = index / 8;
@@ -93,6 +100,7 @@ static inline void bsp_interrupt_clear_handler_entry(
 )
 {
   e->handler = bsp_interrupt_handler_empty;
+  bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
   e->arg = (void *) vector;
   e->info = NULL;
   e->next = NULL;
@@ -234,13 +242,14 @@ static rtems_status_code bsp_interrupt_handler_install(
      * the handler table and fill the entry with life.
      */
     if (bsp_interrupt_allocate_handler_index(vector, &index)) {
-      rtems_interrupt_disable(level);
-      bsp_interrupt_handler_table [index].handler = handler;
+      bsp_interrupt_disable(level);
       bsp_interrupt_handler_table [index].arg = arg;
+      bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
+      bsp_interrupt_handler_table [index].handler = handler;
       #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
         bsp_interrupt_handler_index_table [vector] = index;
       #endif
-      rtems_interrupt_enable(level);
+      bsp_interrupt_enable(level);
       bsp_interrupt_handler_table [index].info = info;
     } else {
       /* Handler table is full */
@@ -299,9 +308,10 @@ static rtems_status_code bsp_interrupt_handler_install(
     current->next = NULL;
 
     /* Link to list tail */
-    rtems_interrupt_disable(level);
+    bsp_interrupt_disable(level);
+    bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
     tail->next = current;
-    rtems_interrupt_enable(level);
+    bsp_interrupt_enable(level);
   }
 
   /* Make the handler unique if necessary */
@@ -387,9 +397,17 @@ static rtems_status_code bsp_interrupt_handler_remove(
        */
       current = match->next;
 
-      rtems_interrupt_disable(level);
-      *match = *current;
-      rtems_interrupt_enable(level);
+      bsp_interrupt_disable(level);
+      #ifdef RTEMS_SMP
+        match->handler = bsp_interrupt_handler_do_nothing;
+        bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
+      #endif
+      match->arg = current->arg;
+      bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
+      match->handler = current->handler;
+      match->info = current->info;
+      match->next = current->next;
+      bsp_interrupt_enable(level);
 
       bsp_interrupt_free_handler_entry(current);
     } else if (match == head) {
@@ -404,12 +422,12 @@ static rtems_status_code bsp_interrupt_handler_remove(
       sc = bsp_interrupt_vector_disable(vector);
 
       /* Clear entry */
-      rtems_interrupt_disable(level);
+      bsp_interrupt_disable(level);
       bsp_interrupt_clear_handler_entry(head, vector);
       #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
         bsp_interrupt_handler_index_table [vector] = 0;
       #endif
-      rtems_interrupt_enable(level);
+      bsp_interrupt_enable(level);
 
       /* Allow shared handlers */
       bsp_interrupt_set_handler_unique(index, false);
@@ -424,9 +442,10 @@ static rtems_status_code bsp_interrupt_handler_remove(
        * The match is the list tail and has a predecessor.
        * So terminate the predecessor and free the match.
        */
-      rtems_interrupt_disable(level);
+      bsp_interrupt_disable(level);
       previous->next = NULL;
-      rtems_interrupt_enable(level);
+      bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
+      bsp_interrupt_enable(level);
 
       bsp_interrupt_free_handler_entry(match);
     }
-- 
1.7.7




More information about the devel mailing list