[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