Summary: A new option RTEMS_INTERRUPT_REPLACE is introduced that permits updating the 'first' interrupt handler for the registered interrupt vector and matching argument. If no match is found, the install function fails with RTEMS_UNSATISFIED.
On Mon, Mar 3, 2014 at 10:29 AM, Sebastian Huber <sebastian.hu...@embedded-brains.de> wrote: > The Interrupt Manager Extension offers interrupt handlers with an > argument pointer. It is impossible to update two words (handler and > argument) atomically on most architectures. In order to avoid an SMP > lock in bsp_interrupt_handler_dispatch() which would degrade the > interrupt response time an alternative must be provided that makes it > possible to tear-down interrupt sources without an SMP lock. > > Add RTEMS_INTERRUPT_REPLACE option to Interrupt Manager Extension. This > enables a clean tear-down of interrupt soures on SMP configurations. s/soures/sources > Instead of an interrupt handler removal a replacement handler can be > installed to silence an interrupt source. This can be used in contexts > that allow no sophisticated synchronization (e.g. in atexit() or fatal > handlers). > --- > c/src/lib/libbsp/shared/src/irq-generic.c | 81 > +++++++++++++++++++---------- > cpukit/include/rtems/irq-extension.h | 35 ++++++++++-- > 2 files changed, 83 insertions(+), 33 deletions(-) > > diff --git a/c/src/lib/libbsp/shared/src/irq-generic.c > b/c/src/lib/libbsp/shared/src/irq-generic.c > index 0343ccb..ad34b4a 100644 > --- a/c/src/lib/libbsp/shared/src/irq-generic.c > +++ b/c/src/lib/libbsp/shared/src/irq-generic.c > @@ -211,10 +211,8 @@ static rtems_status_code bsp_interrupt_handler_install( > rtems_interrupt_level level; > rtems_vector_number index = 0; > bsp_interrupt_handler_entry *head = NULL; > - bsp_interrupt_handler_entry *tail = NULL; > - bsp_interrupt_handler_entry *current = NULL; > - bsp_interrupt_handler_entry *match = NULL; > bool enable_vector = false; > + bool replace = RTEMS_INTERRUPT_IS_REPLACE(options); > > /* Check parameters and system state */ > if (!bsp_interrupt_is_initialized()) { > @@ -237,6 +235,12 @@ static rtems_status_code bsp_interrupt_handler_install( > head = &bsp_interrupt_handler_table [index]; > > if (bsp_interrupt_is_empty_handler_entry(head)) { > + if (replace) { > + /* No handler to replace exists */ > + bsp_interrupt_unlock(); > + return RTEMS_UNSATISFIED; > + } > + > /* > * No real handler installed yet. So allocate a new index in > * the handler table and fill the entry with life. > @@ -260,10 +264,15 @@ static rtems_status_code bsp_interrupt_handler_install( > /* This is the first handler so enable the vector later */ > enable_vector = true; > } else { > + bsp_interrupt_handler_entry *current = head; > + bsp_interrupt_handler_entry *tail = NULL; > + bsp_interrupt_handler_entry *match = NULL; > + > /* Ensure that a unique handler remains unique */ > if ( > - RTEMS_INTERRUPT_IS_UNIQUE(options) > - || bsp_interrupt_is_handler_unique(index) > + !replace > + && (RTEMS_INTERRUPT_IS_UNIQUE(options) > + || bsp_interrupt_is_handler_unique(index)) > ) { > /* > * Tried to install a unique handler on a not empty > @@ -277,41 +286,59 @@ static rtems_status_code bsp_interrupt_handler_install( > * Search for the list tail and check if the handler is already > * installed. > */ > - current = head; > do { > - if (current->handler == handler && current->arg == arg) { > + if ( > + match == NULL > + && (current->handler == handler || replace) > + && current->arg == arg > + ) { > match = current; > } > tail = current; > current = current->next; > } while (current != NULL); > > - /* Ensure the handler is not already installed */ > - if (match != NULL) { > - /* The handler is already installed */ > - bsp_interrupt_unlock(); > - return RTEMS_TOO_MANY; > - } > + if (replace) { > + /* Ensure that a handler to replace exists */ > + if (match == NULL) { > + bsp_interrupt_unlock(); > + return RTEMS_UNSATISFIED; > + } > > - /* Allocate a new entry */ > - current = bsp_interrupt_allocate_handler_entry(); > - if (current == NULL) { > - /* Not enough memory */ > - bsp_interrupt_unlock(); > - return RTEMS_NO_MEMORY; > + /* 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 = bsp_interrupt_allocate_handler_entry(); > + if (current == NULL) { > + /* Not enough memory */ > + bsp_interrupt_unlock(); > + return RTEMS_NO_MEMORY; > + } > } > > - /* Set entry */ > + /* Update existing entry or set new entry */ > current->handler = handler; > - current->arg = arg; > current->info = info; > - current->next = NULL; > > - /* Link to list tail */ > - bsp_interrupt_disable(level); > - bsp_interrupt_fence(ATOMIC_ORDER_RELEASE); > - tail->next = current; > - bsp_interrupt_enable(level); > + 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); > + } > } > > /* Make the handler unique if necessary */ > diff --git a/cpukit/include/rtems/irq-extension.h > b/cpukit/include/rtems/irq-extension.h > index ff2c6da..35eaf1e 100644 > --- a/cpukit/include/rtems/irq-extension.h > +++ b/cpukit/include/rtems/irq-extension.h > @@ -9,12 +9,13 @@ > /* > * Based on concepts of Pavel Pisa, Till Straumann and Eric Valette. > * > - * Copyright (c) 2008 > - * Embedded Brains GmbH > - * Obere Lagerstr. 30 > - * D-82178 Puchheim > - * Germany > - * rt...@embedded-brains.de > + * Copyright (c) 2008-2014 embedded brains GmbH. > + * > + * embedded brains GmbH > + * Dornierstr. 4 > + * 82178 Puchheim > + * Germany > + * <rt...@embedded-brains.de> > * > * The license and distribution terms for this file may be > * found in the file LICENSE in this distribution or at > @@ -54,6 +55,12 @@ extern "C" { > #define RTEMS_INTERRUPT_SHARED ((rtems_option) 0x00000000) > > /** > + * @brief Forces that this interrupt handler replaces the first handler with > + * the same argument. > + */ > +#define RTEMS_INTERRUPT_REPLACE ((rtems_option) 0x00000002) > + > +/** > * @brief Returns true if the interrupt handler unique option is set. > */ > #define RTEMS_INTERRUPT_IS_UNIQUE( options) \ > @@ -66,6 +73,12 @@ extern "C" { > (!RTEMS_INTERRUPT_IS_UNIQUE( options)) > Is RTEMS_INTERRUPT_IS_SHARED() macro correctly implemented? > /** > + * @brief Returns true if the interrupt handler replace option is set. > + */ > +#define RTEMS_INTERRUPT_IS_REPLACE( options) \ > + ((options) & RTEMS_INTERRUPT_REPLACE) > + > +/** > * @brief Interrupt handler routine type. > */ > typedef void (*rtems_interrupt_handler)(void *); > @@ -78,6 +91,7 @@ typedef void (*rtems_interrupt_handler)(void *); > * > * - @ref RTEMS_INTERRUPT_UNIQUE > * - @ref RTEMS_INTERRUPT_SHARED > + * - @ref RTEMS_INTERRUPT_REPLACE > * > * with the @a options parameter for the interrupt handler. > * > @@ -88,6 +102,13 @@ typedef void (*rtems_interrupt_handler)(void *); > * If the option @ref RTEMS_INTERRUPT_UNIQUE is set then it shall be ensured > * that this handler will be the only one for this vector. > * > + * If the option @ref RTEMS_INTERRUPT_REPLACE is set then it shall be ensured > + * that this handler will replace the first handler with the same argument > for The existing documentation for shared interrupt vectors indicates the order of processing is bsp-dependent, so replacing the 'first' handler may not give the intended result on all BSPs. > + * this vector if it exists, otherwise an error status shall be returned. A > + * second handler with the same argument for this vector shall remain > + * unchanged. The new handler will inherit the unique or shared option from > + * the replaced handler. > + * It should be noted that REPLACE enables changing a handler previously installed with the UNIQUE option. > * You can provide an informative description @a info. This may be used for > * system debugging and status tools. The string has to be persistent during > * the handler life time. > @@ -108,6 +129,8 @@ typedef void (*rtems_interrupt_handler)(void *); > * installed and there is already a handler installed this shall be returned. > * @retval RTEMS_TOO_MANY If a handler with this argument is already > installed > * for the vector this shall be returned. > + * @retval RTEMS_UNSATISFIED If no handler exists to replace with the > specified > + * argument and vector this shall be returned. > * @retval RTEMS_IO_ERROR Reserved for board support package specific error > * conditions. > */ > -- > 1.7.7 > > _______________________________________________ > rtems-devel mailing list > rtems-devel@rtems.org > http://www.rtems.org/mailman/listinfo/rtems-devel _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel