[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