[PATCH v3 25/42] bsps/irq: Add rtems_interrupt_entry_install()

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Jul 23 13:56:33 UTC 2021


Add rtems_interrupt_entry_remove().  Split up irq-generic.c into several files.
In particular, place all functions which use dynamic memory into their own
file.

Add optional macros to let the BSP 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()

Use these new customization options in the m68k/genmcf548x BSP so re-use the
generic interrupt controller support.

Update #3269.
---
 bsps/i386/shared/irq/irq.c                   |   8 +-
 bsps/include/bsp/irq-generic.h               | 214 ++++++--
 bsps/m68k/genmcf548x/include/bsp/irq.h       |   8 +
 bsps/m68k/genmcf548x/irq/irq.c               | 140 +-----
 bsps/shared/irq-default-sources.am           |   3 +
 bsps/shared/irq-sources.am                   |   3 +
 bsps/shared/irq/irq-entry-remove.c           | 115 +++++
 bsps/shared/irq/irq-generic.c                | 486 ++++++-------------
 bsps/shared/irq/irq-handler-install.c        | 114 +++++
 bsps/shared/irq/irq-handler-iterate.c        |  21 +-
 bsps/shared/irq/irq-handler-remove.c         |  80 +++
 c/src/lib/libbsp/m68k/genmcf548x/Makefile.am |  10 +-
 c/src/lib/libbsp/powerpc/ss555/Makefile.am   |   3 +
 spec/build/bsps/m68k/genmcf548x/grp.yml      |   2 +
 spec/build/bsps/m68k/genmcf548x/obj.yml      |   9 -
 spec/build/bsps/objirq.yml                   |   3 +
 spec/build/bsps/powerpc/ss555/bspss555.yml   |   3 +
 17 files changed, 681 insertions(+), 541 deletions(-)
 create mode 100644 bsps/shared/irq/irq-entry-remove.c
 create mode 100644 bsps/shared/irq/irq-handler-install.c
 create mode 100644 bsps/shared/irq/irq-handler-remove.c

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 at 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
@@ -27,6 +27,8 @@ links:
   uid: ../grp
 - role: build-dependency
   uid: ../../obj
+- role: build-dependency
+  uid: ../../objirq
 - role: build-dependency
   uid: ../../optconsolebaud
 - role: build-dependency
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
-- 
2.26.2



More information about the devel mailing list