summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/lib/libbsp/shared/src/irq-server.c308
1 files changed, 173 insertions, 135 deletions
diff --git a/c/src/lib/libbsp/shared/src/irq-server.c b/c/src/lib/libbsp/shared/src/irq-server.c
index 6d0d0d33af..4f127af7ba 100644
--- a/c/src/lib/libbsp/shared/src/irq-server.c
+++ b/c/src/lib/libbsp/shared/src/irq-server.c
@@ -82,93 +82,6 @@ static void bsp_interrupt_server_trigger(void *arg)
}
typedef struct {
- bsp_interrupt_server_action *action;
- bsp_interrupt_server_action **link;
- rtems_id task;
-} bsp_interrupt_server_helper_data;
-
-static void bsp_interrupt_server_helper(void *arg)
-{
- bsp_interrupt_server_helper_data *hd = arg;
-
- *hd->link = hd->action;
- rtems_event_transient_send(hd->task);
-}
-
-static void bsp_interrupt_server_call_helper(
- bsp_interrupt_server_action *action,
- bsp_interrupt_server_action **link
-)
-{
- bsp_interrupt_server_helper_data hd = {
- .action = action,
- .link = link,
- .task = rtems_task_self()
- };
- bsp_interrupt_server_action a = {
- .handler = bsp_interrupt_server_helper,
- .arg = &hd
- };
- bsp_interrupt_server_entry e = {
- .vector = BSP_INTERRUPT_VECTOR_MAX + 1,
- .actions = &a
- };
-
- bsp_interrupt_server_trigger(&e);
- rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
-}
-
-static bsp_interrupt_server_entry *bsp_interrupt_server_get_entry(void)
-{
- rtems_interrupt_lock_context lock_context;
- bsp_interrupt_server_entry *e;
- rtems_chain_control *chain;
-
- rtems_interrupt_lock_acquire(&bsp_interrupt_server_lock, &lock_context);
- chain = &bsp_interrupt_server_chain;
-
- if (!rtems_chain_is_empty(chain)) {
- e = (bsp_interrupt_server_entry *)
- rtems_chain_get_first_unprotected(chain);
- rtems_chain_set_off_chain(&e->node);
- } else {
- e = NULL;
- }
-
- rtems_interrupt_lock_release(&bsp_interrupt_server_lock, &lock_context);
-
- return e;
-}
-
-static void bsp_interrupt_server_task(rtems_task_argument arg)
-{
- while (true) {
- rtems_event_set events;
- bsp_interrupt_server_entry *e;
-
- rtems_event_system_receive(
- RTEMS_EVENT_SYSTEM_SERVER,
- RTEMS_EVENT_ALL | RTEMS_WAIT,
- RTEMS_NO_TIMEOUT,
- &events
- );
-
- while ((e = bsp_interrupt_server_get_entry()) != NULL) {
- bsp_interrupt_server_action *action = e->actions;
- rtems_vector_number vector = e->vector;
-
- do {
- bsp_interrupt_server_action *current = action;
- action = action->next;
- (*current->handler)(current->arg);
- } while (action != NULL);
-
- bsp_interrupt_vector_enable(vector);
- }
- }
-}
-
-typedef struct {
bsp_interrupt_server_entry *entry;
rtems_option *options;
} bsp_interrupt_server_iterate_entry;
@@ -208,50 +121,46 @@ static bsp_interrupt_server_entry *bsp_interrupt_server_query_entry(
return ie.entry;
}
-rtems_status_code rtems_interrupt_server_handler_install(
- rtems_id server,
- rtems_vector_number vector,
- const char *info,
- rtems_option options,
- rtems_interrupt_handler handler,
- void *arg
-)
+typedef struct {
+ rtems_vector_number vector;
+ rtems_option options;
+ rtems_interrupt_handler handler;
+ void *arg;
+ rtems_id task;
+ rtems_status_code sc;
+} bsp_interrupt_server_helper_data;
+
+static void bsp_interrupt_server_install_helper(void *arg)
{
+ bsp_interrupt_server_helper_data *hd = arg;
rtems_status_code sc;
bsp_interrupt_server_entry *e;
bsp_interrupt_server_action *a;
rtems_option trigger_options;
- sc = bsp_interrupt_server_is_initialized();
- if (sc != RTEMS_SUCCESSFUL) {
- return sc;
- }
-
- if (server != RTEMS_ID_NONE) {
- return RTEMS_NOT_IMPLEMENTED;
- }
-
a = calloc(1, sizeof(*a));
if (a == NULL) {
- return RTEMS_NO_MEMORY;
+ hd->sc = RTEMS_NO_MEMORY;
+ rtems_event_transient_send(hd->task);
+ return;
}
- a->handler = handler;
- a->arg = arg;
+ a->handler = hd->handler;
+ a->arg = hd->arg;
bsp_interrupt_lock();
- e = bsp_interrupt_server_query_entry(vector, &trigger_options);
+ e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
if (e == NULL) {
e = calloc(1, sizeof(*e));
if (e != NULL) {
- e->vector = vector;
+ e->vector = hd->vector;
e->actions = a;
sc = rtems_interrupt_handler_install(
- vector,
+ hd->vector,
"IRQS",
- options & RTEMS_INTERRUPT_UNIQUE,
+ hd->options & RTEMS_INTERRUPT_UNIQUE,
bsp_interrupt_server_trigger,
e
);
@@ -262,7 +171,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
sc = RTEMS_NO_MEMORY;
}
} else if (
- RTEMS_INTERRUPT_IS_UNIQUE(options)
+ RTEMS_INTERRUPT_IS_UNIQUE(hd->options)
|| RTEMS_INTERRUPT_IS_UNIQUE(trigger_options)
) {
sc = RTEMS_RESOURCE_IN_USE;
@@ -270,8 +179,10 @@ rtems_status_code rtems_interrupt_server_handler_install(
bsp_interrupt_server_action **link = &e->actions;
bsp_interrupt_server_action *c;
+ sc = RTEMS_SUCCESSFUL;
+
while ((c = *link) != NULL) {
- if (c->handler == handler && c->arg == arg) {
+ if (c->handler == hd->handler && c->arg == hd->arg) {
sc = RTEMS_TOO_MANY;
break;
}
@@ -280,7 +191,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
}
if (sc == RTEMS_SUCCESSFUL) {
- bsp_interrupt_server_call_helper(a, link);
+ *link = a;
}
}
@@ -290,38 +201,26 @@ rtems_status_code rtems_interrupt_server_handler_install(
free(a);
}
- return sc;
+ hd->sc = sc;
+ rtems_event_transient_send(hd->task);
}
-rtems_status_code rtems_interrupt_server_handler_remove(
- rtems_id server,
- rtems_vector_number vector,
- rtems_interrupt_handler handler,
- void *arg
-)
+static void bsp_interrupt_server_remove_helper(void *arg)
{
+ bsp_interrupt_server_helper_data *hd = arg;
rtems_status_code sc;
bsp_interrupt_server_entry *e;
rtems_option trigger_options;
- sc = bsp_interrupt_server_is_initialized();
- if (sc != RTEMS_SUCCESSFUL) {
- return sc;
- }
-
- if (server != RTEMS_ID_NONE) {
- return RTEMS_NOT_IMPLEMENTED;
- }
-
bsp_interrupt_lock();
- e = bsp_interrupt_server_query_entry(vector, &trigger_options);
+ e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
if (e != NULL) {
bsp_interrupt_server_action **link = &e->actions;
bsp_interrupt_server_action *c;
while ((c = *link) != NULL) {
- if (c->handler == handler && c->arg == arg) {
+ if (c->handler == hd->handler && c->arg == hd->arg) {
break;
}
@@ -333,18 +232,20 @@ rtems_status_code rtems_interrupt_server_handler_remove(
if (remove_last) {
rtems_interrupt_handler_remove(
- vector,
+ hd->vector,
bsp_interrupt_server_trigger,
e
);
}
- bsp_interrupt_server_call_helper(c->next, link);
+ *link = c->next;
free(c);
if (remove_last) {
free(e);
}
+
+ sc = RTEMS_SUCCESSFUL;
} else {
sc = RTEMS_UNSATISFIED;
}
@@ -354,7 +255,144 @@ rtems_status_code rtems_interrupt_server_handler_remove(
bsp_interrupt_unlock();
- return sc;
+ hd->sc = sc;
+ rtems_event_transient_send(hd->task);
+}
+
+static rtems_status_code bsp_interrupt_server_call_helper(
+ rtems_vector_number vector,
+ rtems_option options,
+ rtems_interrupt_handler handler,
+ void *arg,
+ void (*helper)(void *)
+)
+{
+ bsp_interrupt_server_helper_data hd = {
+ .vector = vector,
+ .options = options,
+ .handler = handler,
+ .arg = arg,
+ .task = rtems_task_self()
+ };
+ bsp_interrupt_server_action a = {
+ .handler = helper,
+ .arg = &hd
+ };
+ bsp_interrupt_server_entry e = {
+ .vector = BSP_INTERRUPT_VECTOR_MAX + 1,
+ .actions = &a
+ };
+
+ bsp_interrupt_server_trigger(&e);
+ rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+
+ return hd.sc;
+}
+
+static bsp_interrupt_server_entry *bsp_interrupt_server_get_entry(void)
+{
+ rtems_interrupt_lock_context lock_context;
+ bsp_interrupt_server_entry *e;
+ rtems_chain_control *chain;
+
+ rtems_interrupt_lock_acquire(&bsp_interrupt_server_lock, &lock_context);
+ chain = &bsp_interrupt_server_chain;
+
+ if (!rtems_chain_is_empty(chain)) {
+ e = (bsp_interrupt_server_entry *)
+ rtems_chain_get_first_unprotected(chain);
+ rtems_chain_set_off_chain(&e->node);
+ } else {
+ e = NULL;
+ }
+
+ rtems_interrupt_lock_release(&bsp_interrupt_server_lock, &lock_context);
+
+ return e;
+}
+
+static void bsp_interrupt_server_task(rtems_task_argument arg)
+{
+ while (true) {
+ rtems_event_set events;
+ bsp_interrupt_server_entry *e;
+
+ rtems_event_system_receive(
+ RTEMS_EVENT_SYSTEM_SERVER,
+ RTEMS_EVENT_ALL | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &events
+ );
+
+ while ((e = bsp_interrupt_server_get_entry()) != NULL) {
+ bsp_interrupt_server_action *action = e->actions;
+ rtems_vector_number vector = e->vector;
+
+ do {
+ bsp_interrupt_server_action *current = action;
+ action = action->next;
+ (*current->handler)(current->arg);
+ } while (action != NULL);
+
+ bsp_interrupt_vector_enable(vector);
+ }
+ }
+}
+
+rtems_status_code rtems_interrupt_server_handler_install(
+ rtems_id server,
+ rtems_vector_number vector,
+ const char *info,
+ rtems_option options,
+ rtems_interrupt_handler handler,
+ void *arg
+)
+{
+ rtems_status_code sc;
+
+ sc = bsp_interrupt_server_is_initialized();
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+
+ if (server != RTEMS_ID_NONE) {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+
+ return bsp_interrupt_server_call_helper(
+ vector,
+ options,
+ handler,
+ arg,
+ bsp_interrupt_server_install_helper
+ );
+}
+
+rtems_status_code rtems_interrupt_server_handler_remove(
+ rtems_id server,
+ rtems_vector_number vector,
+ rtems_interrupt_handler handler,
+ void *arg
+)
+{
+ rtems_status_code sc;
+
+ sc = bsp_interrupt_server_is_initialized();
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+
+ if (server != RTEMS_ID_NONE) {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+
+ return bsp_interrupt_server_call_helper(
+ vector,
+ 0,
+ handler,
+ arg,
+ bsp_interrupt_server_remove_helper
+ );
}
rtems_status_code rtems_interrupt_server_initialize(