On Mon, Jul 12, 2021 at 6:51 AM Sebastian Huber <sebastian.hu...@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 <chr...@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@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel