[rtems commit] Add rtems_interrupt_server_request_submit()

Sebastian Huber sebh at rtems.org
Thu Feb 23 07:55:05 UTC 2017


Module:    rtems
Branch:    master
Commit:    33986022af8f5389370cb012ba0e73e032774cab
Changeset: http://git.rtems.org/rtems/commit/?id=33986022af8f5389370cb012ba0e73e032774cab

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Feb 21 15:25:03 2017 +0100

Add rtems_interrupt_server_request_submit()

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 | 148 +++++++++++++++++++------
 cpukit/include/rtems/irq-extension.h     | 182 ++++++++++++++++++++++++++++++-
 2 files changed, 297 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..905c261 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_MANAGEMENT_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_MANAGEMENT_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,97 @@ rtems_status_code rtems_interrupt_server_initialize(
 
   return RTEMS_SUCCESSFUL;
 }
+
+static void bsp_interrupt_server_entry_initialize(
+  rtems_interrupt_server_entry *entry
+)
+{
+  rtems_chain_set_off_chain(&entry->node);
+  entry->vector = BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR;
+  entry->actions = NULL;
+}
+
+static void bsp_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;
+}
+
+void rtems_interrupt_server_entry_initialize(
+  rtems_interrupt_server_entry *entry
+)
+{
+  bsp_interrupt_server_entry_initialize(entry);
+}
+
+void rtems_interrupt_server_action_prepend(
+  rtems_interrupt_server_entry  *entry,
+  rtems_interrupt_server_action *action,
+  rtems_interrupt_handler        handler,
+  void                          *arg
+)
+{
+  bsp_interrupt_server_action_prepend(entry, action, handler, arg);
+}
+
+void rtems_interrupt_server_entry_submit(
+  rtems_id                      server,
+  rtems_interrupt_server_entry *entry
+)
+{
+  bsp_interrupt_server_trigger(entry);
+}
+
+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_id                      server,
+  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_chain_set_off_chain(&entry->node);
+  }
+
+  rtems_interrupt_lock_release(&bsp_interrupt_server_lock, &lock_context);
+
+  bsp_interrupt_server_call_helper(
+    BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
+    0,
+    NULL,
+    NULL,
+    bsp_interrupt_server_entry_destroy_helper
+  );
+}
+
+void rtems_interrupt_server_request_initialize(
+  rtems_interrupt_server_request *request,
+  rtems_interrupt_handler         handler,
+  void                           *arg
+)
+{
+  bsp_interrupt_server_entry_initialize(&request->entry);
+  bsp_interrupt_server_action_prepend(
+    &request->entry,
+    &request->action,
+    handler,
+    arg
+  );
+}
diff --git a/cpukit/include/rtems/irq-extension.h b/cpukit/include/rtems/irq-extension.h
index fc8c125..71ff800 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" {
@@ -203,6 +204,52 @@ rtems_status_code rtems_interrupt_handler_iterate(
 );
 
 /**
+ * @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(),
+ *   rtems_interrupt_server_action_prepend(),
+ *   rtems_interrupt_server_entry_submit(), 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 An interrupt server request.
+ *
+ * This structure must be treated as an opaque data type.  Members must not be
+ * accessed directly.
+ *
+ * @see rtems_interrupt_server_request_initialize(),
+ *   rtems_interrupt_server_request_submit(), and
+ *   rtems_interrupt_server_request_destroy().
+ */
+typedef struct {
+  rtems_interrupt_server_entry  entry;
+  rtems_interrupt_server_action action;
+} rtems_interrupt_server_request;
+
+/**
  * @brief Initializes an interrupt server task.
  *
  * The task will have the priority @a priority, the stack size @a stack_size,
@@ -285,6 +332,139 @@ rtems_status_code rtems_interrupt_server_handler_remove(
   void *arg
 );
 
+/**
+ * @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 Submits the specified interrupt server entry so that its interrupt
+ * server actions can be invoked by the specified interrupt server.
+ *
+ * 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_entry_submit(
+  rtems_id                      server,
+  rtems_interrupt_server_entry *entry
+);
+
+/**
+ * @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] server The server identifier.  Use @c RTEMS_ID_NONE to specify
+ *   the default server.
+ * @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_id                      server,
+  rtems_interrupt_server_entry *entry
+);
+
+/**
+ * @brief Initializes the specified interrupt server request.
+ *
+ * No error checking is performed.
+ *
+ * @param[in] request The interrupt server request to initialize.
+ * @param[in] handler The interrupt handler for the request action.
+ * @param[in] arg The interrupt handler argument for the request action.
+ */
+void rtems_interrupt_server_request_initialize(
+  rtems_interrupt_server_request *request,
+  rtems_interrupt_handler         handler,
+  void                           *arg
+);
+
+/**
+ * @brief Submits the specified interrupt server request so that its interrupt
+ * server action can be invoked by the specified interrupt server.
+ *
+ * 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] request The interrupt server request must be initialized before the
+ *   first call to this function via
+ *   rtems_interrupt_server_request_initialize().  The request must not be
+ *   modified between calls to this function.  Use
+ *   rtems_interrupt_server_request_destroy() to destroy a request in use.
+ */
+RTEMS_INLINE_ROUTINE void rtems_interrupt_server_request_submit(
+  rtems_id                        server,
+  rtems_interrupt_server_request *request
+)
+{
+  rtems_interrupt_server_entry_submit( server, &request->entry );
+}
+
+/**
+ * @brief Destroys the specified interrupt server request.
+ *
+ * This function must be called from thread context.  It may block.  No error
+ * checking is performed.
+ *
+ * @param[in] server The server identifier.  Use @c RTEMS_ID_NONE to specify
+ *   the default server.
+ * @param[in] request The interrupt server request to destroy.  It must have
+ *   been initialized via rtems_interrupt_server_request_initialize().
+ */
+RTEMS_INLINE_ROUTINE void rtems_interrupt_server_request_destroy(
+  rtems_id                        server,
+  rtems_interrupt_server_request *request
+)
+{
+  rtems_interrupt_server_entry_destroy( server, &request->entry );
+}
+
 /** @} */
 
 #ifdef __cplusplus



More information about the vc mailing list