summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/shared/src/irq-generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/shared/src/irq-generic.c')
-rw-r--r--c/src/lib/libbsp/shared/src/irq-generic.c81
1 files changed, 54 insertions, 27 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 */