summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-03-03 09:49:12 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-03-06 09:43:58 +0100
commite0609ac745bac77504a5d1fc6ce15e79eacd3c1e (patch)
tree053b5eb24cc221ec8a20806d8db52b563d3ffe47
parentscore: Add _Atomic_Fence() (diff)
downloadrtems-e0609ac745bac77504a5d1fc6ce15e79eacd3c1e.tar.bz2
bsps: SMP support for generic interrupt support
-rw-r--r--c/src/lib/libbsp/shared/include/irq-generic.h30
-rw-r--r--c/src/lib/libbsp/shared/src/irq-generic.c47
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 82267f4ef5..0bb4e4410e 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@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 610fe40d8e..0343ccb6cf 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@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);
}