[PATCH 3/3] rtems: Add RTEMS_INTERRUPT_REPLACE
Gedare Bloom
gedare at rtems.org
Mon Mar 3 16:44:01 UTC 2014
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.huber at 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
> - * rtems at embedded-brains.de
> + * Copyright (c) 2008-2014 embedded brains GmbH.
> + *
> + * embedded brains GmbH
> + * Dornierstr. 4
> + * 82178 Puchheim
> + * Germany
> + * <rtems at 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 at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-devel
More information about the devel
mailing list