summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/lib/libbsp/shared/src/irq-generic.c81
-rw-r--r--cpukit/include/rtems/irq-extension.h35
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 0343ccb6cf..ad34b4a4be 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 ff2c6daff4..35eaf1e635 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@embedded-brains.de
+ * Copyright (c) 2008-2014 embedded brains GmbH.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@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))
/**
+ * @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
+ * 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.
+ *
* 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.
*/