From e0609ac745bac77504a5d1fc6ce15e79eacd3c1e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 3 Mar 2014 09:49:12 +0100 Subject: bsps: SMP support for generic interrupt support --- 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 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 * @@ -29,6 +29,10 @@ #include +#ifdef RTEMS_SMP + #include +#endif + #include #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 * @@ -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); } -- cgit v1.2.3