[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