[PATCH 1/3] Add rtems_interrupt_server_request()
Sebastian Huber
sebastian.huber at embedded-brains.de
Wed Feb 22 15:24:39 UTC 2017
This function may be used to do a two-step interrupt processing. The
first step is done in interrupt context which calls this function. The
second step is then done in the context of the interrupt server.
---
c/src/lib/libbsp/shared/src/irq-server.c | 114 ++++++++++++++++++++++---------
cpukit/include/rtems/irq-extension.h | 102 ++++++++++++++++++++++++++-
2 files changed, 183 insertions(+), 33 deletions(-)
diff --git a/c/src/lib/libbsp/shared/src/irq-server.c b/c/src/lib/libbsp/shared/src/irq-server.c
index 4f127af..7640f27 100644
--- a/c/src/lib/libbsp/shared/src/irq-server.c
+++ b/c/src/lib/libbsp/shared/src/irq-server.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (c) 2009, 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2009, 2017 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -28,24 +28,14 @@
#include <bsp/irq-generic.h>
+#define BSP_INTERRUPT_SERVER_MANAGMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
+
RTEMS_INTERRUPT_LOCK_DEFINE(
static,
bsp_interrupt_server_lock,
"Interrupt Server"
)
-typedef struct bsp_interrupt_server_action {
- struct bsp_interrupt_server_action *next;
- rtems_interrupt_handler handler;
- void *arg;
-} bsp_interrupt_server_action;
-
-typedef struct {
- rtems_chain_node node;
- rtems_vector_number vector;
- bsp_interrupt_server_action *actions;
-} bsp_interrupt_server_entry;
-
static rtems_id bsp_interrupt_server_id = RTEMS_ID_NONE;
static RTEMS_CHAIN_DEFINE_EMPTY(bsp_interrupt_server_chain);
@@ -64,7 +54,7 @@ static unsigned bsp_interrupt_server_errors;
static void bsp_interrupt_server_trigger(void *arg)
{
rtems_interrupt_lock_context lock_context;
- bsp_interrupt_server_entry *e = arg;
+ rtems_interrupt_server_entry *e = arg;
bsp_interrupt_vector_disable(e->vector);
@@ -82,7 +72,7 @@ static void bsp_interrupt_server_trigger(void *arg)
}
typedef struct {
- bsp_interrupt_server_entry *entry;
+ rtems_interrupt_server_entry *entry;
rtems_option *options;
} bsp_interrupt_server_iterate_entry;
@@ -102,7 +92,7 @@ static void bsp_interrupt_server_per_handler_routine(
}
}
-static bsp_interrupt_server_entry *bsp_interrupt_server_query_entry(
+static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
rtems_vector_number vector,
rtems_option *trigger_options
)
@@ -134,8 +124,8 @@ 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_interrupt_server_entry *e;
+ rtems_interrupt_server_action *a;
rtems_option trigger_options;
a = calloc(1, sizeof(*a));
@@ -176,8 +166,8 @@ static void bsp_interrupt_server_install_helper(void *arg)
) {
sc = RTEMS_RESOURCE_IN_USE;
} else {
- bsp_interrupt_server_action **link = &e->actions;
- bsp_interrupt_server_action *c;
+ rtems_interrupt_server_action **link = &e->actions;
+ rtems_interrupt_server_action *c;
sc = RTEMS_SUCCESSFUL;
@@ -209,15 +199,15 @@ 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_interrupt_server_entry *e;
rtems_option trigger_options;
bsp_interrupt_lock();
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;
+ rtems_interrupt_server_action **link = &e->actions;
+ rtems_interrupt_server_action *c;
while ((c = *link) != NULL) {
if (c->handler == hd->handler && c->arg == hd->arg) {
@@ -274,12 +264,12 @@ static rtems_status_code bsp_interrupt_server_call_helper(
.arg = arg,
.task = rtems_task_self()
};
- bsp_interrupt_server_action a = {
+ rtems_interrupt_server_action a = {
.handler = helper,
.arg = &hd
};
- bsp_interrupt_server_entry e = {
- .vector = BSP_INTERRUPT_VECTOR_MAX + 1,
+ rtems_interrupt_server_entry e = {
+ .vector = BSP_INTERRUPT_SERVER_MANAGMENT_VECTOR,
.actions = &a
};
@@ -289,17 +279,17 @@ static rtems_status_code bsp_interrupt_server_call_helper(
return hd.sc;
}
-static bsp_interrupt_server_entry *bsp_interrupt_server_get_entry(void)
+static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(void)
{
rtems_interrupt_lock_context lock_context;
- bsp_interrupt_server_entry *e;
+ rtems_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 *)
+ e = (rtems_interrupt_server_entry *)
rtems_chain_get_first_unprotected(chain);
rtems_chain_set_off_chain(&e->node);
} else {
@@ -315,7 +305,7 @@ static void bsp_interrupt_server_task(rtems_task_argument arg)
{
while (true) {
rtems_event_set events;
- bsp_interrupt_server_entry *e;
+ rtems_interrupt_server_entry *e;
rtems_event_system_receive(
RTEMS_EVENT_SYSTEM_SERVER,
@@ -325,11 +315,11 @@ static void bsp_interrupt_server_task(rtems_task_argument arg)
);
while ((e = bsp_interrupt_server_get_entry()) != NULL) {
- bsp_interrupt_server_action *action = e->actions;
+ rtems_interrupt_server_action *action = e->actions;
rtems_vector_number vector = e->vector;
do {
- bsp_interrupt_server_action *current = action;
+ rtems_interrupt_server_action *current = action;
action = action->next;
(*current->handler)(current->arg);
} while (action != NULL);
@@ -430,3 +420,63 @@ rtems_status_code rtems_interrupt_server_initialize(
return RTEMS_SUCCESSFUL;
}
+
+void rtems_interrupt_server_entry_initialize(
+ rtems_interrupt_server_entry *entry
+)
+{
+ rtems_chain_set_off_chain(&entry->node);
+ entry->vector = BSP_INTERRUPT_SERVER_MANAGMENT_VECTOR;
+ entry->actions = NULL;
+}
+
+void rtems_interrupt_server_action_prepend(
+ rtems_interrupt_server_entry *entry,
+ rtems_interrupt_server_action *action,
+ rtems_interrupt_handler handler,
+ void *arg
+)
+{
+ action->handler = handler;
+ action->arg = arg;
+ action->next = entry->actions;
+ entry->actions = action;
+}
+
+static void bsp_interrupt_server_entry_destroy_helper(void *arg)
+{
+ bsp_interrupt_server_helper_data *hd = arg;
+
+ rtems_event_transient_send(hd->task);
+}
+
+void rtems_interrupt_server_entry_destroy(
+ rtems_interrupt_server_entry *entry
+)
+{
+ rtems_interrupt_lock_context lock_context;
+
+ rtems_interrupt_lock_acquire(&bsp_interrupt_server_lock, &lock_context);
+
+ if (!rtems_chain_is_node_off_chain(&entry->node)) {
+ rtems_chain_extract_unprotected(&entry->node);
+ }
+
+ rtems_interrupt_lock_release(&bsp_interrupt_server_lock, &lock_context);
+
+ bsp_interrupt_server_call_helper(
+ BSP_INTERRUPT_SERVER_MANAGMENT_VECTOR,
+ 0,
+ NULL,
+ NULL,
+ bsp_interrupt_server_entry_destroy_helper
+ );
+}
+
+void rtems_interrupt_server_request(
+ rtems_id server,
+ rtems_interrupt_server_entry *entry
+)
+{
+ bsp_interrupt_server_trigger(entry);
+}
diff --git a/cpukit/include/rtems/irq-extension.h b/cpukit/include/rtems/irq-extension.h
index fc8c125..84e305f 100644
--- a/cpukit/include/rtems/irq-extension.h
+++ b/cpukit/include/rtems/irq-extension.h
@@ -9,7 +9,7 @@
/*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
*
- * Copyright (c) 2008, 2016 embedded brains GmbH.
+ * Copyright (c) 2008, 2017 embedded brains GmbH.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -26,6 +26,7 @@
#define RTEMS_IRQ_EXTENSION_H
#include <rtems.h>
+#include <rtems/chain.h>
#ifdef __cplusplus
extern "C" {
@@ -285,6 +286,105 @@ rtems_status_code rtems_interrupt_server_handler_remove(
void *arg
);
+/**
+ * @brief An interrupt server action.
+ *
+ * This structure must be treated as an opaque data type. Members must not be
+ * accessed directly.
+ *
+ * @see rtems_interrupt_server_action_prepend().
+ */
+typedef struct rtems_interrupt_server_action {
+ struct rtems_interrupt_server_action *next;
+ rtems_interrupt_handler handler;
+ void *arg;
+} rtems_interrupt_server_action;
+
+/**
+ * @brief An interrupt server entry.
+ *
+ * This structure must be treated as an opaque data type. Members must not be
+ * accessed directly.
+ *
+ * @see rtems_interrupt_server_entry_initialize() and
+ * rtems_interrupt_server_entry_destroy().
+ */
+typedef struct {
+ rtems_chain_node node;
+ rtems_vector_number vector;
+ rtems_interrupt_server_action *actions;
+} rtems_interrupt_server_entry;
+
+/**
+ * @brief Initializes the specified interrupt server entry.
+ *
+ * @param[in] entry The interrupt server entry to initialize.
+ *
+ * @see rtems_interrupt_server_action_prepend().
+ */
+void rtems_interrupt_server_entry_initialize(
+ rtems_interrupt_server_entry *entry
+);
+
+/**
+ * @brief Prepends the specified interrupt server action to the list of actions
+ * of the specified interrupt server entry.
+ *
+ * No error checking is performed.
+ *
+ * @param[in] entry The interrupt server entry to prepend the interrupt server
+ * action. It must have been initialized via
+ * rtems_interrupt_server_entry_initialize().
+ * @param[in] action The interrupt server action to prepend the list of actions
+ * of the entry.
+ * @param[in] handler The interrupt handler for the action.
+ * @param[in] arg The interrupt handler argument for the action.
+ */
+void rtems_interrupt_server_action_prepend(
+ rtems_interrupt_server_entry *entry,
+ rtems_interrupt_server_action *action,
+ rtems_interrupt_handler handler,
+ void *arg
+);
+
+/**
+ * @brief Destroys the specified interrupt server entry.
+ *
+ * This function must be called from thread context. It may block.
+ * No error checking is performed.
+ *
+ * @param[in] entry The interrupt server entry to destroy. It must have been
+ * initialized via rtems_interrupt_server_entry_initialize().
+ */
+void rtems_interrupt_server_entry_destroy(
+ rtems_interrupt_server_entry *entry
+);
+
+/**
+ * @brief Requests the specified interrupt server to perform the interrupt
+ * server actions contained in the specified interrupt server entry.
+ *
+ * This function may be used to do a two-step interrupt processing. The first
+ * step is done in interrupt context which calls this function. The second
+ * step is then done in the context of the interrupt server.
+ *
+ * This function may be called from thread or interrupt context. It does not
+ * block. No error checking is performed.
+ *
+ * @param[in] server The server identifier. Use @c RTEMS_ID_NONE to specify
+ * the default server.
+ *
+ * @param[in] entry The interrupt server entry must be initialized before the
+ * first call to this function via rtems_interrupt_server_entry_initialize()
+ * and rtems_interrupt_server_action_prepend(). The entry and its actions
+ * must not be modified between calls to this function. Use
+ * rtems_interrupt_server_entry_destroy() to destroy an entry in use.
+ */
+void rtems_interrupt_server_request(
+ rtems_id server,
+ rtems_interrupt_server_entry *entry
+);
+
/** @} */
#ifdef __cplusplus
--
1.8.4.5
More information about the devel
mailing list