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

Gedare Bloom gedare at rtems.org
Wed Jul 21 18:51:27 UTC 2021


On Mon, Jul 12, 2021 at 6:51 AM Sebastian Huber
<sebastian.huber at embedded-brains.de> wrote:
>
> 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 d0004698e7..25f8fb69b0 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 3b2998f533..6e2f5ed464 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_cause_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 ) ];
> +  const rtems_interrupt_entry *entry;
>
> -  do {
> -    rtems_interrupt_handler handler;
> -    void *arg;
> -
> -    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.
>   */
> @@ -448,6 +547,21 @@ rtems_status_code bsp_interrupt_check_and_lock(
>    rtems_interrupt_handler handler
>  );
>
> +/* For internal use only */
Need an impl file? not sure what this comment means/implies.

> +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.
> @@ -480,29 +594,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;

Is this clearing the unique bit for the vector, if !unique? This
functionality is not clear from the comments above.

> +  }
> +}
>
>  /**
> - * @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 9d483918e4..bcac012723 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);
>  }
Are these genmcf548x changes tested, or compile-only? I'm mostly just
curious on that point. If you can't test, it may be worth trying to
find someone who may be willing.

> diff --git a/bsps/shared/irq-default-sources.am b/bsps/shared/irq-default-sources.am
> index c739be5f97..fb25c90ae5 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-cause-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 fddb47599c..b0bdea3d3a 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-cause-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 2c8c75f6d6..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-cause-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 ec16b492ee..ca25aa1d65 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-cause-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 07e3760ad9..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-cause-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 4dda48d465..46afb79b08 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-cause-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 a3bc8a6226..3257706a3f 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
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel


More information about the devel mailing list