summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bsps/i386/shared/irq/irq.c8
-rw-r--r--bsps/include/bsp/irq-generic.h214
-rw-r--r--bsps/m68k/genmcf548x/include/bsp/irq.h8
-rw-r--r--bsps/m68k/genmcf548x/irq/irq.c140
-rw-r--r--bsps/shared/irq-default-sources.am3
-rw-r--r--bsps/shared/irq-sources.am3
-rw-r--r--bsps/shared/irq/irq-entry-remove.c115
-rw-r--r--bsps/shared/irq/irq-generic.c486
-rw-r--r--bsps/shared/irq/irq-handler-install.c114
-rw-r--r--bsps/shared/irq/irq-handler-iterate.c21
-rw-r--r--bsps/shared/irq/irq-handler-remove.c80
-rw-r--r--c/src/lib/libbsp/m68k/genmcf548x/Makefile.am10
-rw-r--r--c/src/lib/libbsp/powerpc/ss555/Makefile.am3
-rw-r--r--spec/build/bsps/m68k/genmcf548x/grp.yml2
-rw-r--r--spec/build/bsps/m68k/genmcf548x/obj.yml9
-rw-r--r--spec/build/bsps/objirq.yml3
-rw-r--r--spec/build/bsps/powerpc/ss555/bspss555.yml3
17 files changed, 681 insertions, 541 deletions
diff --git a/bsps/i386/shared/irq/irq.c b/bsps/i386/shared/irq/irq.c
index 3ba1051f8f..e6994d49c7 100644
--- a/bsps/i386/shared/irq/irq.c
+++ b/bsps/i386/shared/irq/irq.c
@@ -353,13 +353,7 @@ rtems_status_code bsp_interrupt_facility_initialize(void)
static bool bsp_interrupt_handler_is_empty(rtems_vector_number vector)
{
- rtems_vector_number index;
- rtems_interrupt_entry *head;
-
- index = bsp_interrupt_handler_index(vector);
- head = &bsp_interrupt_handler_table[index];
-
- return bsp_interrupt_is_empty_handler_entry(head);
+ return bsp_interrupt_entry_load_first(vector) == NULL;
}
/*
diff --git a/bsps/include/bsp/irq-generic.h b/bsps/include/bsp/irq-generic.h
index 12e8f9155b..e27c1b230c 100644
--- a/bsps/include/bsp/irq-generic.h
+++ b/bsps/include/bsp/irq-generic.h
@@ -12,7 +12,7 @@
/*
* Copyright (C) 2016 Chris Johns <chrisj@rtems.org>
*
- * Copyright (C) 2008, 2017 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -70,20 +70,13 @@ extern "C" {
#define BSP_INTERRUPT_HANDLER_TABLE_SIZE BSP_INTERRUPT_VECTOR_COUNT
#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
-
#define bsp_interrupt_assert(e) _Assert(e)
-extern rtems_interrupt_entry bsp_interrupt_handler_table [];
+/**
+ * @brief Each member of this table references the first installed entry at the
+ * corresponding interrupt vector or is NULL.
+ */
+extern rtems_interrupt_entry *bsp_interrupt_handler_table[];
#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
#if BSP_INTERRUPT_HANDLER_TABLE_SIZE < 0x100
@@ -141,6 +134,12 @@ static inline rtems_vector_number bsp_interrupt_handler_index(
* - bsp_interrupt_vector_disable()
* - bsp_interrupt_handler_default()
*
+ * Optionally, the BSP may define the following macros to customize the vector
+ * installation after installing the first entry and the vector removal before
+ * removing the last entry:
+ * - bsp_interrupt_vector_install()
+ * - bsp_interrupt_vector_remove()
+ *
* The following now deprecated functions are provided for backward
* compatibility:
* - BSP_get_current_rtems_irq_handler()
@@ -362,14 +361,114 @@ rtems_status_code bsp_interrupt_raise_on(
*/
rtems_status_code bsp_interrupt_clear( rtems_vector_number vector );
+#if defined(RTEMS_SMP)
+/**
+ * @brief Handles a spurious interrupt.
+ *
+ * @param vector is the vector number.
+ */
+void bsp_interrupt_spurious( rtems_vector_number vector );
+#endif
+
+/**
+ * @brief Loads the interrupt entry with atomic acquire semantic.
+ *
+ * @param ptr is the pointer to an ::rtems_interrupt_entry pointer.
+ *
+ * @return Returns the pointer value.
+ */
+static inline rtems_interrupt_entry *bsp_interrupt_entry_load_acquire(
+ rtems_interrupt_entry * const *ptr
+)
+{
+#if defined(RTEMS_SMP)
+ return (rtems_interrupt_entry *) _Atomic_Load_uintptr(
+ (const Atomic_Uintptr *) ptr,
+ ATOMIC_ORDER_ACQUIRE
+ );
+#else
+ return *ptr;
+#endif
+}
+
+/**
+ * @brief Stores the interrupt entry with atomic release semantic.
+ *
+ * @param[out] ptr is the pointer to an ::rtems_interrupt_entry pointer.
+ *
+ * @param value is the pointer value.
+ */
+static inline void bsp_interrupt_entry_store_release(
+ rtems_interrupt_entry **ptr,
+ rtems_interrupt_entry *value
+)
+{
+#if defined(RTEMS_SMP)
+ _Atomic_Store_uintptr(
+ (Atomic_Uintptr *) ptr,
+ (Atomic_Uintptr) value,
+ ATOMIC_ORDER_RELEASE
+ );
+#else
+ rtems_interrupt_level level;
+
+ rtems_interrupt_local_disable( level );
+ *ptr = value;
+ rtems_interrupt_local_enable( level );
+#endif
+}
+
+/**
+ * @brief Loads the first interrupt entry installed at the interrupt vector.
+ *
+ * @param vector is the vector number.
+ *
+ * @return Returns the first entry or NULL.
+ */
+static inline rtems_interrupt_entry *bsp_interrupt_entry_load_first(
+ rtems_vector_number vector
+)
+{
+ rtems_vector_number index;
+
+ index = bsp_interrupt_handler_index( vector );
+
+ return bsp_interrupt_entry_load_acquire(
+ &bsp_interrupt_handler_table[ index ]
+ );
+}
+
+/**
+ * @brief Sequentially calls all interrupt handlers of the entry its
+ * successors.
+ *
+ * In uniprocessor configurations, you can call this function within every
+ * context which can be disabled via rtems_interrupt_local_disable().
+ *
+ * In SMP configurations, you can call this function in every context.
+ *
+ * @param entry is the first entry.
+ */
+static inline void bsp_interrupt_dispatch_entries(
+ const rtems_interrupt_entry *entry
+)
+{
+ do {
+ ( *entry->handler )( entry->arg );
+ entry = bsp_interrupt_entry_load_acquire( &entry->next );
+ } while ( RTEMS_PREDICT_FALSE( entry != NULL ) );
+}
+
/**
* @brief Sequentially calls all interrupt handlers installed at the vector.
*
* This function does not validate the vector number. If the vector number is
* out of range, then the behaviour is undefined.
*
- * You can call this function within every context which can be disabled via
- * rtems_interrupt_local_disable().
+ * In uniprocessor configurations, you can call this function within every
+ * context which can be disabled via rtems_interrupt_local_disable().
+ *
+ * In SMP configurations, you can call this function in every context.
*
* @param vector is the vector number.
*/
@@ -377,21 +476,19 @@ static inline void bsp_interrupt_handler_dispatch_unchecked(
rtems_vector_number vector
)
{
- const rtems_interrupt_entry *e;
-
- e = &bsp_interrupt_handler_table[ bsp_interrupt_handler_index( vector ) ];
-
- do {
- rtems_interrupt_handler handler;
- void *arg;
+ const rtems_interrupt_entry *entry;
- arg = e->arg;
- bsp_interrupt_fence( ATOMIC_ORDER_ACQUIRE );
- handler = e->handler;
- ( *handler )( arg );
+ entry = bsp_interrupt_entry_load_first( vector );
- e = e->next;
- } while ( e != NULL );
+ if ( RTEMS_PREDICT_TRUE( entry != NULL ) ) {
+ bsp_interrupt_dispatch_entries( entry );
+ } else {
+#if defined(RTEMS_SMP)
+ bsp_interrupt_spurious( vector );
+#else
+ bsp_interrupt_handler_default( vector );
+#endif
+ }
}
/**
@@ -401,8 +498,10 @@ static inline void bsp_interrupt_handler_dispatch_unchecked(
* bsp_interrupt_handler_default() will be called with the vector number as
* argument.
*
- * You can call this function within every context which can be disabled via
- * rtems_interrupt_local_disable().
+ * In uniprocessor configurations, you can call this function within every
+ * context which can be disabled via rtems_interrupt_local_disable().
+ *
+ * In SMP configurations, you can call this function in every context.
*
* @param vector is the vector number.
*/
@@ -457,6 +556,21 @@ rtems_status_code bsp_interrupt_check_and_lock(
rtems_interrupt_handler handler
);
+/* For internal use only */
+rtems_interrupt_entry *bsp_interrupt_entry_find(
+ rtems_vector_number vector,
+ rtems_interrupt_handler routine,
+ void *arg,
+ rtems_interrupt_entry ***previous_next
+);
+
+/* For internal use only */
+void bsp_interrupt_entry_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_entry *entry,
+ rtems_interrupt_entry **previous_next
+);
+
/**
* @brief This table contains a bit map which indicates if an entry is unique
* or shared.
@@ -489,29 +603,39 @@ static inline bool bsp_interrupt_is_handler_unique( rtems_vector_number index )
}
/**
- * @brief Checks if the interrupt support is initialized.
+ * @brief Sets the unique status of the handler entry.
*
- * @return Returns true, if the interrupt support is initialized, otherwise
- * false.
+ * @param index is the handler index.
+ *
+ * @param unique is the unique status to set.
*/
-static inline bool bsp_interrupt_is_initialized( void )
+static inline void bsp_interrupt_set_handler_unique(
+ rtems_vector_number index,
+ bool unique
+)
{
- return bsp_interrupt_is_handler_unique( BSP_INTERRUPT_HANDLER_TABLE_SIZE );
-}
+ rtems_vector_number table_index;
+ uint8_t bit;
-/**
- * @brief This handler routine is used for empty entries.
- */
-void bsp_interrupt_handler_empty( void *arg );
+ table_index = index / 8;
+ bit = (uint8_t) ( 1U << ( index % 8 ) );
+
+ if (unique) {
+ bsp_interrupt_handler_unique_table[ table_index ] |= bit;
+ } else {
+ bsp_interrupt_handler_unique_table[ table_index ] &= ~bit;
+ }
+}
/**
- * @brief Checks if a handler entry is empty.
+ * @brief Checks if the interrupt support is initialized.
+ *
+ * @return Returns true, if the interrupt support is initialized, otherwise
+ * false.
*/
-static inline bool bsp_interrupt_is_empty_handler_entry(
- const rtems_interrupt_entry *entry
-)
+static inline bool bsp_interrupt_is_initialized( void )
{
- return entry->handler == bsp_interrupt_handler_empty;
+ return bsp_interrupt_is_handler_unique( BSP_INTERRUPT_HANDLER_TABLE_SIZE );
}
#ifdef __cplusplus
diff --git a/bsps/m68k/genmcf548x/include/bsp/irq.h b/bsps/m68k/genmcf548x/include/bsp/irq.h
index 4c90c6ad0e..140868f022 100644
--- a/bsps/m68k/genmcf548x/include/bsp/irq.h
+++ b/bsps/m68k/genmcf548x/include/bsp/irq.h
@@ -99,4 +99,12 @@ static inline bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
&& vector < (rtems_vector_number) BSP_INTERRUPT_VECTOR_COUNT;
}
+void mcf548x_interrupt_vector_install(rtems_vector_number vector);
+
+void mcf548x_interrupt_vector_remove(rtems_vector_number vector);
+
+#define bsp_interrupt_vector_install(v) mcf548x_interrupt_vector_install(v)
+
+#define bsp_interrupt_vector_remove(v) mcf548x_interrupt_vector_remove(v)
+
#endif /* LIBBSP_M68K_MCF548X_IRQ_H */
diff --git a/bsps/m68k/genmcf548x/irq/irq.c b/bsps/m68k/genmcf548x/irq/irq.c
index cd38b3e153..4a9fefee33 100644
--- a/bsps/m68k/genmcf548x/irq/irq.c
+++ b/bsps/m68k/genmcf548x/irq/irq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013, 2021 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -20,14 +20,6 @@ void asm_default_interrupt(void);
typedef void (*void_func)(void);
-typedef struct {
- rtems_interrupt_handler handler;
- void *arg;
- const char *info;
-} interrupt_control;
-
-static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_COUNT];
-
static uint32_t vector_to_reg(rtems_vector_number vector)
{
return ((vector + 32U) >> 5) & 0x1;
@@ -131,18 +123,6 @@ rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
return RTEMS_SUCCESSFUL;
}
-static void_func get_exception_handler(rtems_vector_number vector)
-{
- void **vbr;
- void_func *exception_table;
-
- m68k_get_vbr(vbr);
-
- exception_table = (void_func *)vbr;
-
- return exception_table[vector_to_exception_vector(vector)];
-}
-
static void set_exception_handler(rtems_vector_number vector, void_func handler)
{
void **vbr;
@@ -157,119 +137,19 @@ static void set_exception_handler(rtems_vector_number vector, void_func handler)
static void dispatch_handler(rtems_vector_number exception_vector)
{
- const interrupt_control *ic =
- &interrupt_controls[exception_vector_to_vector(exception_vector)];
-
- (*ic->handler)(ic->arg);
+ bsp_interrupt_handler_dispatch_unchecked(
+ exception_vector_to_vector(exception_vector)
+ );
}
-static uint8_t get_intc_icr(rtems_vector_number vector)
+void mcf548x_interrupt_vector_install(rtems_vector_number vector)
{
- volatile uint8_t *icr = &MCF548X_INTC_ICR0;
-
- return icr[vector];
+ _ISR_Vector_table[vector_to_exception_vector(vector)]
+ = dispatch_handler;
+ set_exception_handler(vector, _ISR_Handler);
}
-rtems_status_code rtems_interrupt_handler_install(
- rtems_vector_number vector,
- const char *info,
- rtems_option options,
- rtems_interrupt_handler handler,
- void *arg
-)
+void mcf548x_interrupt_vector_remove(rtems_vector_number vector)
{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
-
- if (bsp_interrupt_is_valid_vector(vector)) {
- rtems_interrupt_level level;
-
- rtems_interrupt_disable(level);
-
- if (
- get_exception_handler(vector) == asm_default_interrupt
- && get_intc_icr(vector) != 0
- ) {
- interrupt_control *ic = &interrupt_controls[vector];
-
- ic->handler = handler;
- ic->arg = arg;
- ic->info = info;
-
- _ISR_Vector_table[vector_to_exception_vector(vector)]
- = dispatch_handler;
- set_exception_handler(vector, _ISR_Handler);
- bsp_interrupt_vector_enable(vector);
- } else {
- sc = RTEMS_RESOURCE_IN_USE;
- }
-
- rtems_interrupt_enable(level);
- } else {
- sc = RTEMS_INVALID_ID;
- }
-
- return sc;
-}
-
-static bool is_occupied_by_us(rtems_vector_number vector)
-{
- return get_exception_handler(vector) == _ISR_Handler
- && _ISR_Vector_table[vector_to_exception_vector(vector)]
- == dispatch_handler;
-}
-
-rtems_status_code rtems_interrupt_handler_remove(
- rtems_vector_number vector,
- rtems_interrupt_handler handler,
- void *arg
-)
-{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
-
- if (bsp_interrupt_is_valid_vector(vector)) {
- rtems_interrupt_level level;
- interrupt_control *ic = &interrupt_controls[vector];
-
- rtems_interrupt_disable(level);
-
- if (
- is_occupied_by_us(vector)
- && ic->handler == handler
- && ic->arg == arg
- ) {
- bsp_interrupt_vector_disable(vector);
- set_exception_handler(vector, asm_default_interrupt);
-
- memset(ic, 0, sizeof(*ic));
- } else {
- sc = RTEMS_UNSATISFIED;
- }
-
- rtems_interrupt_enable(level);
- } else {
- sc = RTEMS_INVALID_ID;
- }
-
- return sc;
-}
-
-rtems_status_code rtems_interrupt_handler_iterate(
- rtems_vector_number vector,
- rtems_interrupt_per_handler_routine routine,
- void *arg
-)
-{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
-
- if (bsp_interrupt_is_valid_vector(vector)) {
- if (is_occupied_by_us(vector)) {
- const interrupt_control *ic = &interrupt_controls[vector];
-
- (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg);
- }
- } else {
- sc = RTEMS_INVALID_ID;
- }
-
- return sc;
+ set_exception_handler(vector, asm_default_interrupt);
}
diff --git a/bsps/shared/irq-default-sources.am b/bsps/shared/irq-default-sources.am
index 41167ee2bc..2c1c18752f 100644
--- a/bsps/shared/irq-default-sources.am
+++ b/bsps/shared/irq-default-sources.am
@@ -3,8 +3,11 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-server.c
diff --git a/bsps/shared/irq-sources.am b/bsps/shared/irq-sources.am
index 97e1f05167..f671c25c20 100644
--- a/bsps/shared/irq-sources.am
+++ b/bsps/shared/irq-sources.am
@@ -1,8 +1,11 @@
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-affinity.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-legacy.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
diff --git a/bsps/shared/irq/irq-entry-remove.c b/bsps/shared/irq/irq-entry-remove.c
new file mode 100644
index 0000000000..3e5fd33fbe
--- /dev/null
+++ b/bsps/shared/irq/irq-entry-remove.c
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief This source file contains the implementation of
+ * rtems_interrupt_entry_remove() and bsp_interrupt_entry_remove().
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/irq-generic.h>
+
+void bsp_interrupt_entry_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_entry *entry,
+ rtems_interrupt_entry **previous_next
+)
+{
+ rtems_vector_number index;
+ rtems_interrupt_entry *first;
+ rtems_interrupt_entry *entry_next;
+
+ index = bsp_interrupt_handler_index( vector );
+ first = bsp_interrupt_handler_table[ index ];
+ entry_next = entry->next;
+
+ if ( entry == first && entry_next == NULL ) {
+ /* We remove the last installed entry */
+ bsp_interrupt_vector_disable( vector );
+#if defined(bsp_interrupt_vector_remove)
+ bsp_interrupt_vector_remove( vector );
+#else
+ bsp_interrupt_vector_disable( vector );
+#endif
+ bsp_interrupt_set_handler_unique( index, false );
+#if defined(BSP_INTERRUPT_USE_INDEX_TABLE)
+ bsp_interrupt_handler_index_table[ vector ] = 0;
+#endif
+ }
+
+ bsp_interrupt_entry_store_release( previous_next, entry_next );
+}
+
+static rtems_status_code bsp_interrupt_entry_do_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_entry *entry
+)
+{
+ rtems_interrupt_entry *installed;
+ rtems_interrupt_entry **previous_next;
+
+ installed = bsp_interrupt_entry_find(
+ vector,
+ entry->handler,
+ entry->arg,
+ &previous_next
+ );
+
+ if ( installed != entry ) {
+ return RTEMS_UNSATISFIED;
+ }
+
+ bsp_interrupt_entry_remove( vector, entry, previous_next );
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_interrupt_entry_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_entry *entry
+)
+{
+ rtems_status_code sc;
+
+ if ( entry == NULL ) {
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ sc = bsp_interrupt_check_and_lock( vector, entry->handler );
+
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ return sc;
+ }
+
+ sc = bsp_interrupt_entry_do_remove( vector, entry );
+ bsp_interrupt_unlock();
+
+ return sc;
+}
diff --git a/bsps/shared/irq/irq-generic.c b/bsps/shared/irq/irq-generic.c
index df57c99ae3..eddb887d15 100644
--- a/bsps/shared/irq/irq-generic.c
+++ b/bsps/shared/irq/irq-generic.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (C) 2008, 2018 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2008, 2021 embedded brains GmbH (http://www.embedded-brains.de)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -46,92 +46,75 @@
[BSP_INTERRUPT_VECTOR_COUNT];
#endif
-rtems_interrupt_entry bsp_interrupt_handler_table
- [BSP_INTERRUPT_HANDLER_TABLE_SIZE];
+rtems_interrupt_entry *
+bsp_interrupt_handler_table[ BSP_INTERRUPT_HANDLER_TABLE_SIZE ];
/* The last entry indicates if everything is initialized */
uint8_t bsp_interrupt_handler_unique_table
[ ( BSP_INTERRUPT_HANDLER_TABLE_SIZE + 7 + 1 ) / 8 ];
-void bsp_interrupt_handler_empty( void *arg )
-{
- rtems_vector_number vector = (rtems_vector_number) (uintptr_t) arg;
-
- bsp_interrupt_handler_default( vector );
-}
-
-#ifdef RTEMS_SMP
- static void bsp_interrupt_handler_do_nothing(void *arg)
- {
- (void) arg;
- }
-#endif
-
-static inline void bsp_interrupt_set_handler_unique(
- rtems_vector_number index,
- bool unique
-)
-{
- rtems_vector_number i = index / 8;
- rtems_vector_number s = index % 8;
- if (unique) {
- bsp_interrupt_handler_unique_table [i] |= (uint8_t) (0x1U << s);
- } else {
- bsp_interrupt_handler_unique_table [i] &= (uint8_t) ~(0x1U << s);
- }
-}
-
static inline void bsp_interrupt_set_initialized(void)
{
bsp_interrupt_set_handler_unique(BSP_INTERRUPT_HANDLER_TABLE_SIZE, true);
}
-static inline void bsp_interrupt_clear_handler_entry(
- rtems_interrupt_entry *e,
+#if defined(BSP_INTERRUPT_USE_INDEX_TABLE)
+static inline rtems_vector_number bsp_interrupt_allocate_handler_index(
rtems_vector_number vector
)
{
- e->handler = bsp_interrupt_handler_empty;
- bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
- e->arg = (void *) (uintptr_t) vector;
- e->info = NULL;
- e->next = NULL;
-}
+ rtems_vector_number i;
-static inline bool bsp_interrupt_allocate_handler_index(
- rtems_vector_number vector,
- rtems_vector_number *index
-)
-{
- #ifdef BSP_INTERRUPT_USE_INDEX_TABLE
- rtems_vector_number i = 0;
-
- /* The first entry will remain empty */
- for (i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
- const rtems_interrupt_entry *e = &bsp_interrupt_handler_table [i];
- if (bsp_interrupt_is_empty_handler_entry(e)) {
- *index = i;
- return true;
- }
+ /* The first entry will remain empty */
+ for ( i = 1; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i ) {
+ if ( bsp_interrupt_handler_table[ i ] == NULL ) {
+ break;
}
+ }
+
+ return i;
+}
+#endif
+
+#if defined(RTEMS_SMP)
+RTEMS_STATIC_ASSERT(
+ sizeof( Atomic_Uintptr ) == sizeof( rtems_interrupt_entry * ),
+ rtems_interrupt_entry_pointer_size
+);
- return false;
- #else
- *index = bsp_interrupt_handler_index(vector);
- return true;
- #endif
+void bsp_interrupt_spurious( rtems_vector_number vector )
+{
+ Atomic_Uintptr *ptr;
+ rtems_interrupt_entry *first;
+
+ /*
+ * In order to get the last written pointer value to the first entry, we have
+ * to carry out an atomic read-modify-write operation.
+ */
+ ptr = (Atomic_Uintptr *) &bsp_interrupt_handler_table[
+ bsp_interrupt_handler_index( vector )
+ ];
+ first = (rtems_interrupt_entry *)
+ _Atomic_Fetch_add_uintptr( ptr, 0, ATOMIC_ORDER_ACQUIRE );
+
+ if ( first == NULL ) {
+ bsp_interrupt_handler_default( vector );
+ } else {
+ bsp_interrupt_dispatch_entries( first );
+ }
}
+#endif
rtems_status_code bsp_interrupt_check_and_lock(
rtems_vector_number vector,
- rtems_interrupt_handler handler
+ rtems_interrupt_handler routine
)
{
if ( !bsp_interrupt_is_initialized() ) {
return RTEMS_INCORRECT_STATE;
}
- if ( handler == NULL ) {
+ if ( routine == NULL ) {
return RTEMS_INVALID_ADDRESS;
}
@@ -148,317 +131,160 @@ rtems_status_code bsp_interrupt_check_and_lock(
return RTEMS_SUCCESSFUL;
}
-void bsp_interrupt_initialize(void)
+rtems_interrupt_entry *bsp_interrupt_entry_find(
+ rtems_vector_number vector,
+ rtems_interrupt_handler routine,
+ void *arg,
+ rtems_interrupt_entry ***previous_next
+)
{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- size_t i = 0;
+ rtems_vector_number index;
+ rtems_interrupt_entry *entry;
- /* Initialize handler table */
- for (i = 0; i < BSP_INTERRUPT_HANDLER_TABLE_SIZE; ++i) {
- bsp_interrupt_handler_table [i].handler = bsp_interrupt_handler_empty;
- bsp_interrupt_handler_table [i].arg = (void *) i;
+ bsp_interrupt_assert( bsp_interrupt_is_valid_vector( vector ) );
+ index = bsp_interrupt_handler_index( vector );
+ *previous_next = &bsp_interrupt_handler_table[ index ];
+ entry = bsp_interrupt_handler_table[ index ];
+
+ while ( entry != NULL ) {
+ if ( entry->handler == routine && entry->arg == arg ) {
+ return entry;
+ }
+
+ *previous_next = &entry->next;
+ entry = entry->next;
}
+ return NULL;
+}
+
+void bsp_interrupt_initialize( void )
+{
+ rtems_status_code sc;
+
sc = bsp_interrupt_facility_initialize();
- if (sc != RTEMS_SUCCESSFUL) {
- bsp_fatal(BSP_FATAL_INTERRUPT_INITIALIZATION);
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ bsp_fatal( BSP_FATAL_INTERRUPT_INITIALIZATION );
}
bsp_interrupt_set_initialized();
}
-/**
- * @brief Installs an interrupt handler.
- *
- * @ingroup bsp_interrupt
- *
- * @return In addition to the standard status codes this function returns:
- * - If the BSP interrupt support is not initialized RTEMS_INTERNAL_ERROR will
- * be returned.
- * - If not enough memory for a new handler is available RTEMS_NO_MEMORY will
- * be returned
- *
- * @see rtems_interrupt_handler_install()
- */
-static rtems_status_code bsp_interrupt_handler_install(
- rtems_vector_number vector,
- const char *info,
- rtems_option options,
- rtems_interrupt_handler handler,
- void *arg
+static rtems_status_code bsp_interrupt_entry_install_first(
+ rtems_vector_number vector,
+ rtems_option options,
+ rtems_interrupt_entry *entry
)
{
- rtems_status_code sc;
- rtems_interrupt_level level;
- rtems_vector_number index = 0;
- rtems_interrupt_entry *head = NULL;
- bool enable_vector = false;
- bool replace = RTEMS_INTERRUPT_IS_REPLACE(options);
+ rtems_vector_number index;
- sc = bsp_interrupt_check_and_lock( vector, handler );
+#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
+ index = bsp_interrupt_allocate_handler_index( vector );
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
+ if ( index == BSP_INTERRUPT_HANDLER_TABLE_SIZE ) {
+ /* Handler table is full */
+ return RTEMS_NO_MEMORY;
}
+#else
+ index = vector;
+#endif
- /* Get handler table index */
- index = bsp_interrupt_handler_index(vector);
+#ifdef BSP_INTERRUPT_USE_INDEX_TABLE
+ bsp_interrupt_handler_index_table[ vector ] = index;
+#endif
+ bsp_interrupt_entry_store_release(
+ &bsp_interrupt_handler_table[ index ],
+ entry
+ );
+
+ bsp_interrupt_set_handler_unique(
+ index,
+ RTEMS_INTERRUPT_IS_UNIQUE( options )
+ );
+#if defined(bsp_interrupt_vector_install)
+ bsp_interrupt_vector_install( vector );
+#else
+ bsp_interrupt_vector_enable( vector );
+#endif
- /* Get head entry of the handler list for current vector */
- head = &bsp_interrupt_handler_table [index];
+ return RTEMS_SUCCESSFUL;
+}
- if (bsp_interrupt_is_empty_handler_entry(head)) {
- if (replace) {
- /* No handler to replace exists */
- bsp_interrupt_unlock();
- return RTEMS_UNSATISFIED;
- }
+static rtems_status_code bsp_interrupt_entry_install(
+ rtems_vector_number vector,
+ rtems_option options,
+ rtems_interrupt_entry *entry
+)
+{
+ rtems_vector_number index;
+ rtems_interrupt_entry *first;
+ rtems_interrupt_entry *other;
+ rtems_interrupt_entry **previous_next;
- /*
- * No real handler installed yet. So allocate a new index in
- * the handler table and fill the entry with life.
- */
- if (bsp_interrupt_allocate_handler_index(vector, &index)) {
- 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
- bsp_interrupt_enable(level);
- bsp_interrupt_handler_table [index].info = info;
- } else {
- /* Handler table is full */
- bsp_interrupt_unlock();
- return RTEMS_NO_MEMORY;
- }
+ if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) {
+ return RTEMS_INVALID_NUMBER;
+ }
- /* This is the first handler so enable the vector later */
- enable_vector = true;
- } else {
- rtems_interrupt_entry *current = head;
- rtems_interrupt_entry *tail = NULL;
- rtems_interrupt_entry *match = NULL;
-
- /* Ensure that a unique handler remains unique */
- if (
- !replace
- && (RTEMS_INTERRUPT_IS_UNIQUE(options)
- || bsp_interrupt_is_handler_unique(index))
- ) {
- /*
- * Tried to install a unique handler on a not empty
- * list or there is already a unique handler installed.
- */
- bsp_interrupt_unlock();
- return RTEMS_RESOURCE_IN_USE;
- }
+ index = bsp_interrupt_handler_index( vector );
+ first = bsp_interrupt_handler_table[ index ];
+
+ if ( first == NULL ) {
+ return bsp_interrupt_entry_install_first( vector, options, entry );
+ }
+ if ( RTEMS_INTERRUPT_IS_UNIQUE( options ) ) {
+ /* Cannot install a unique entry if there is already an entry installed */
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ if ( bsp_interrupt_is_handler_unique( index ) ) {
/*
- * Search for the list tail and check if the handler is already
+ * Cannot install another entry if there is already an unique entry
* installed.
*/
- do {
- if (
- match == NULL
- && (current->handler == handler || replace)
- && current->arg == arg
- ) {
- match = current;
- }
- tail = current;
- current = current->next;
- } while (current != NULL);
-
- if (replace) {
- /* Ensure that a handler to replace exists */
- if (match == NULL) {
- bsp_interrupt_unlock();
- return RTEMS_UNSATISFIED;
- }
-
- /* Use existing entry */
- current = match;
- } else {
- /* Ensure the handler is not already installed */
- if (match != NULL) {
- /* The handler is already installed */
- bsp_interrupt_unlock();
- return RTEMS_TOO_MANY;
- }
-
- /* Allocate a new entry */
- current = rtems_malloc(sizeof(*current));
- if (current == NULL) {
- /* Not enough memory */
- bsp_interrupt_unlock();
- return RTEMS_NO_MEMORY;
- }
- }
-
- /* Update existing entry or set new entry */
- current->handler = handler;
- current->info = info;
-
- if (!replace) {
- /* Set new entry */
- current->arg = arg;
- current->next = NULL;
-
- /* Link to list tail */
- bsp_interrupt_disable(level);
- bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
- tail->next = current;
- bsp_interrupt_enable(level);
- }
+ return RTEMS_RESOURCE_IN_USE;
}
- /* Make the handler unique if necessary */
- bsp_interrupt_set_handler_unique(index, RTEMS_INTERRUPT_IS_UNIQUE(options));
+ other = bsp_interrupt_entry_find(
+ vector,
+ entry->handler,
+ entry->arg,
+ &previous_next
+ );
- /* Enable the vector if necessary */
- if (enable_vector) {
- bsp_interrupt_vector_enable(vector);
+ if ( other != NULL ) {
+ /*
+ * Cannot install an entry which has the same routine and argument as an
+ * already installed entry.
+ */
+ return RTEMS_TOO_MANY;
}
- /* Unlock */
- bsp_interrupt_unlock();
+ bsp_interrupt_entry_store_release( previous_next, entry );
return RTEMS_SUCCESSFUL;
}
-/**
- * @brief Removes an interrupt handler.
- *
- * @ingroup bsp_interrupt
- *
- * @return In addition to the standard status codes this function returns
- * RTEMS_INTERNAL_ERROR if the BSP interrupt support is not initialized.
- *
- * @see rtems_interrupt_handler_remove().
- */
-static rtems_status_code bsp_interrupt_handler_remove(
- rtems_vector_number vector,
- rtems_interrupt_handler handler,
- void *arg
+rtems_status_code rtems_interrupt_entry_install(
+ rtems_vector_number vector,
+ rtems_option options,
+ rtems_interrupt_entry *entry
)
{
rtems_status_code sc;
- rtems_interrupt_level level;
- rtems_vector_number index = 0;
- rtems_interrupt_entry *head = NULL;
- rtems_interrupt_entry *current = NULL;
- rtems_interrupt_entry *previous = NULL;
- rtems_interrupt_entry *match = NULL;
-
- sc = bsp_interrupt_check_and_lock( vector, handler );
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
+ if ( entry == NULL ) {
+ return RTEMS_INVALID_ADDRESS;
}
- /* Get handler table index */
- index = bsp_interrupt_handler_index(vector);
-
- /* Get head entry of the handler list for current vector */
- head = &bsp_interrupt_handler_table [index];
+ sc = bsp_interrupt_check_and_lock( vector, entry->handler );
- /* Search for a matching entry */
- current = head;
- do {
- if (current->handler == handler && current->arg == arg) {
- match = current;
- break;
- }
- previous = current;
- current = current->next;
- } while (current != NULL);
-
- /* Remove the matching entry */
- if (match != NULL) {
- if (match->next != NULL) {
- /*
- * The match has a successor. A successor is always
- * allocated. So replace the match with its successor
- * and free the successor entry.
- */
- current = match->next;
-
- 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);
-
- free(current);
- } else if (match == head) {
- /*
- * The match is the list head and has no successor.
- * The list head is stored in a static table so clear
- * this entry. Since now the list is empty disable the
- * vector.
- */
-
- /* Disable the vector */
- bsp_interrupt_vector_disable(vector);
-
- /* Clear entry */
- 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
- bsp_interrupt_enable(level);
-
- /* Allow shared handlers */
- bsp_interrupt_set_handler_unique(index, false);
- } else {
- /*
- * The match is the list tail and has a predecessor.
- * So terminate the predecessor and free the match.
- */
- bsp_interrupt_disable(level);
- previous->next = NULL;
- bsp_interrupt_fence(ATOMIC_ORDER_RELEASE);
- bsp_interrupt_enable(level);
-
- free(match);
- }
- } else {
- /* No matching entry found */
- bsp_interrupt_unlock();
- return RTEMS_UNSATISFIED;
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ return sc;
}
- /* Unlock */
+ sc = bsp_interrupt_entry_install( vector, options, entry );
bsp_interrupt_unlock();
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_interrupt_handler_install(
- rtems_vector_number vector,
- const char *info,
- rtems_option options,
- rtems_interrupt_handler handler,
- void *arg
-)
-{
- return bsp_interrupt_handler_install(vector, info, options, handler, arg);
-}
-
-rtems_status_code rtems_interrupt_handler_remove(
- rtems_vector_number vector,
- rtems_interrupt_handler handler,
- void *arg
-)
-{
- return bsp_interrupt_handler_remove(vector, handler, arg);
+ return sc;
}
diff --git a/bsps/shared/irq/irq-handler-install.c b/bsps/shared/irq/irq-handler-install.c
new file mode 100644
index 0000000000..2474d792e6
--- /dev/null
+++ b/bsps/shared/irq/irq-handler-install.c
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief This source file contains the rtems_interrupt_handler_install()
+ * implementation.
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/irq-generic.h>
+#include <rtems/malloc.h>
+
+#include <stdlib.h>
+
+static rtems_status_code bsp_interrupt_handler_do_replace(
+ rtems_vector_number vector,
+ const char *info,
+ rtems_interrupt_handler routine,
+ void *arg
+)
+{
+ rtems_interrupt_entry *entry;
+ rtems_interrupt_entry **unused;
+
+ entry = bsp_interrupt_entry_find( vector, routine, arg, &unused );
+
+ if ( entry == NULL ) {
+ return RTEMS_UNSATISFIED;
+ }
+
+ entry->handler = routine;
+ entry->info = info;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code bsp_interrupt_handler_replace(
+ rtems_vector_number vector,
+ const char *info,
+ rtems_interrupt_handler routine,
+ void *arg
+)
+{
+ rtems_status_code sc;
+
+ sc = bsp_interrupt_check_and_lock( vector, routine );
+
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ return sc;
+ }
+
+ sc = bsp_interrupt_handler_do_replace( vector, info, routine, arg );
+ bsp_interrupt_unlock();
+
+ return sc;
+}
+
+rtems_status_code rtems_interrupt_handler_install(
+ rtems_vector_number vector,
+ const char *info,
+ rtems_option options,
+ rtems_interrupt_handler routine,
+ void *arg
+)
+{
+ rtems_interrupt_entry *entry;
+ rtems_status_code sc;
+
+ if ( RTEMS_INTERRUPT_IS_REPLACE( options ) ) {
+ return bsp_interrupt_handler_replace( vector, info, routine, arg );
+ }
+
+ entry = rtems_malloc( sizeof( *entry ) );
+
+ if ( entry == NULL ) {
+ return RTEMS_NO_MEMORY;
+ }
+
+ rtems_interrupt_entry_initialize( entry, routine, arg, info );
+ sc = rtems_interrupt_entry_install( vector, options, entry );
+
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ free( entry );
+ }
+
+ return sc;
+}
diff --git a/bsps/shared/irq/irq-handler-iterate.c b/bsps/shared/irq/irq-handler-iterate.c
index 385cb8db2d..8bb29191fd 100644
--- a/bsps/shared/irq/irq-handler-iterate.c
+++ b/bsps/shared/irq/irq-handler-iterate.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright (C) 2017 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2017, 2021 embedded brains GmbH (http://www.embedded-brains.de)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -45,7 +45,7 @@ rtems_status_code rtems_interrupt_handler_iterate(
rtems_status_code sc;
rtems_vector_number index;
rtems_option options;
- rtems_interrupt_entry *current;
+ rtems_interrupt_entry *entry;
sc = bsp_interrupt_check_and_lock(
vector,
@@ -56,15 +56,14 @@ rtems_status_code rtems_interrupt_handler_iterate(
return sc;
}
- index = bsp_interrupt_handler_index(vector);
- current = &bsp_interrupt_handler_table [index];
- if (!bsp_interrupt_is_empty_handler_entry(current)) {
- do {
- options = bsp_interrupt_is_handler_unique(index) ?
- RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
- routine(arg, current->info, options, current->handler, current->arg);
- current = current->next;
- } while (current != NULL);
+ index = bsp_interrupt_handler_index( vector );
+ options = bsp_interrupt_is_handler_unique( index ) ?
+ RTEMS_INTERRUPT_UNIQUE : RTEMS_INTERRUPT_SHARED;
+ entry = bsp_interrupt_handler_table[ index ];
+
+ while ( entry != NULL ) {
+ ( *routine )( arg, entry->info, options, entry->handler, entry->arg );
+ entry = entry->next;
}
bsp_interrupt_unlock();
diff --git a/bsps/shared/irq/irq-handler-remove.c b/bsps/shared/irq/irq-handler-remove.c
new file mode 100644
index 0000000000..cb32ba3b7c
--- /dev/null
+++ b/bsps/shared/irq/irq-handler-remove.c
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief This source file contains the implementation of
+ * rtems_interrupt_handler_remove().
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/irq-generic.h>
+
+#include <stdlib.h>
+
+static rtems_status_code bsp_interrupt_handler_do_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_handler routine,
+ void *arg
+)
+{
+ rtems_interrupt_entry *entry;
+ rtems_interrupt_entry **previous_next;
+
+ entry = bsp_interrupt_entry_find( vector, routine, arg, &previous_next );
+
+ if ( entry == NULL ) {
+ return RTEMS_UNSATISFIED;
+ }
+
+ bsp_interrupt_entry_remove( vector, entry, previous_next );
+ free( entry );
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_interrupt_handler_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_handler routine,
+ void *arg
+)
+{
+ rtems_status_code sc;
+
+ sc = bsp_interrupt_check_and_lock( vector, routine );
+
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ return sc;
+ }
+
+ sc = bsp_interrupt_handler_do_remove( vector, routine, arg );
+ bsp_interrupt_unlock();
+
+ return sc;
+}
diff --git a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am
index 0f828395af..0ee5eafedf 100644
--- a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am
+++ b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am
@@ -38,16 +38,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/console/console.
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/btimer/btimer.c
# IRQ
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-affinity.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-legacy.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-server.c
-librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-shell.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/irq.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/intc-icr-init-values.c
@@ -59,5 +50,6 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/mcdma/MCD_tasksI
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/mcdma/mcdma_glue.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/start/cache.c
+include $(srcdir)/../../../../../../bsps/shared/irq-sources.am
include $(srcdir)/../../../../../../bsps/shared/shared-sources.am
include $(srcdir)/../../../../../../bsps/m68k/genmcf548x/headers.am
diff --git a/c/src/lib/libbsp/powerpc/ss555/Makefile.am b/c/src/lib/libbsp/powerpc/ss555/Makefile.am
index 185f82dd71..7640be981c 100644
--- a/c/src/lib/libbsp/powerpc/ss555/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/ss555/Makefile.am
@@ -51,8 +51,11 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-raise-clear.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-enable-disable.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-entry-remove.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-generic.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-install.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-iterate.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-handler-remove.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-info.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-lock.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-server.c
diff --git a/spec/build/bsps/m68k/genmcf548x/grp.yml b/spec/build/bsps/m68k/genmcf548x/grp.yml
index 0a3a463513..57bdb23566 100644
--- a/spec/build/bsps/m68k/genmcf548x/grp.yml
+++ b/spec/build/bsps/m68k/genmcf548x/grp.yml
@@ -28,6 +28,8 @@ links:
- role: build-dependency
uid: ../../obj
- role: build-dependency
+ uid: ../../objirq
+- role: build-dependency
uid: ../../optconsolebaud
- role: build-dependency
uid: ../../bspopts
diff --git a/spec/build/bsps/m68k/genmcf548x/obj.yml b/spec/build/bsps/m68k/genmcf548x/obj.yml
index 915f5b613f..e65e0c8934 100644
--- a/spec/build/bsps/m68k/genmcf548x/obj.yml
+++ b/spec/build/bsps/m68k/genmcf548x/obj.yml
@@ -38,16 +38,7 @@ source:
- bsps/m68k/shared/m68kidle.c
- bsps/m68k/shared/memProbe.c
- bsps/shared/dev/getentropy/getentropy-cpucounter.c
-- bsps/shared/irq/irq-affinity.c
-- bsps/shared/irq/irq-raise-clear.c
- bsps/shared/irq/irq-default-handler.c
-- bsps/shared/irq/irq-enable-disable.c
-- bsps/shared/irq/irq-handler-iterate.c
-- bsps/shared/irq/irq-info.c
-- bsps/shared/irq/irq-legacy.c
-- bsps/shared/irq/irq-lock.c
-- bsps/shared/irq/irq-server.c
-- bsps/shared/irq/irq-shell.c
- bsps/shared/start/bspfatal-default.c
- bsps/shared/start/bspgetworkarea-default.c
- bsps/shared/start/bspreset-loop.c
diff --git a/spec/build/bsps/objirq.yml b/spec/build/bsps/objirq.yml
index 467d0789ba..0766c1ea58 100644
--- a/spec/build/bsps/objirq.yml
+++ b/spec/build/bsps/objirq.yml
@@ -13,8 +13,11 @@ source:
- bsps/shared/irq/irq-affinity.c
- bsps/shared/irq/irq-raise-clear.c
- bsps/shared/irq/irq-enable-disable.c
+- bsps/shared/irq/irq-entry-remove.c
- bsps/shared/irq/irq-generic.c
+- bsps/shared/irq/irq-handler-install.c
- bsps/shared/irq/irq-handler-iterate.c
+- bsps/shared/irq/irq-handler-remove.c
- bsps/shared/irq/irq-info.c
- bsps/shared/irq/irq-legacy.c
- bsps/shared/irq/irq-lock.c
diff --git a/spec/build/bsps/powerpc/ss555/bspss555.yml b/spec/build/bsps/powerpc/ss555/bspss555.yml
index 2eabfa5d28..bc367a64ea 100644
--- a/spec/build/bsps/powerpc/ss555/bspss555.yml
+++ b/spec/build/bsps/powerpc/ss555/bspss555.yml
@@ -72,8 +72,11 @@ source:
- bsps/shared/irq/irq-default-handler.c
- bsps/shared/irq/irq-default.c
- bsps/shared/irq/irq-enable-disable.c
+- bsps/shared/irq/irq-entry-remove.c
- bsps/shared/irq/irq-generic.c
+- bsps/shared/irq/irq-handler-install.c
- bsps/shared/irq/irq-handler-iterate.c
+- bsps/shared/irq/irq-handler-remove.c
- bsps/shared/irq/irq-info.c
- bsps/shared/irq/irq-lock.c
- bsps/shared/irq/irq-server.c