[PATCH 08/19] score: Move message notification

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Apr 29 09:13:08 UTC 2016


Move message notification to end of critical section and delegate the
message queue release to the notification handler.  It may do more
complex notification actions out of the critical section.

Update #2555.
---
 cpukit/posix/src/mqueuenotify.c                | 23 +++++++++++++++--------
 cpukit/score/include/rtems/score/coremsg.h     | 14 +++++++++-----
 cpukit/score/include/rtems/score/coremsgimpl.h | 10 ++++------
 cpukit/score/src/coremsg.c                     |  2 +-
 cpukit/score/src/coremsginsert.c               | 17 -----------------
 cpukit/score/src/coremsgsubmit.c               | 21 +++++++++++++++++++++
 6 files changed, 50 insertions(+), 37 deletions(-)

diff --git a/cpukit/posix/src/mqueuenotify.c b/cpukit/posix/src/mqueuenotify.c
index 8100976..d31a8e6 100644
--- a/cpukit/posix/src/mqueuenotify.c
+++ b/cpukit/posix/src/mqueuenotify.c
@@ -39,16 +39,24 @@
  */
 
 static void _POSIX_Message_queue_Notify_handler(
-  void    *user_data
+  CORE_message_queue_Control *the_message_queue,
+  ISR_lock_Context           *lock_context
 )
 {
   POSIX_Message_queue_Control *the_mq;
+  int                          signo;
 
-  the_mq = user_data;
+  the_mq = RTEMS_CONTAINER_OF(
+    the_message_queue,
+    POSIX_Message_queue_Control,
+    Message_queue
+  );
 
-  kill( getpid(), the_mq->notification.sigev_signo );
+  signo = the_mq->notification.sigev_signo;
+  _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL );
+  _CORE_message_queue_Release( &the_mq->Message_queue, lock_context );
 
-  _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
+  kill( getpid(), signo );
 }
 
 int mq_notify(
@@ -72,18 +80,17 @@ int mq_notify(
           rtems_set_errno_and_return_minus_one( EBUSY );
         }
 
-        _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
+        _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL );
 
         the_mq->notification = *notification;
 
         _CORE_message_queue_Set_notify(
           &the_mq->Message_queue,
-          _POSIX_Message_queue_Notify_handler,
-          the_mq
+          _POSIX_Message_queue_Notify_handler
         );
       } else {
 
-        _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
+        _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL );
 
       }
 
diff --git a/cpukit/score/include/rtems/score/coremsg.h b/cpukit/score/include/rtems/score/coremsg.h
index 2744346..af42e7d 100644
--- a/cpukit/score/include/rtems/score/coremsg.h
+++ b/cpukit/score/include/rtems/score/coremsg.h
@@ -20,6 +20,7 @@
 #define _RTEMS_SCORE_COREMSG_H
 
 #include <rtems/score/chain.h>
+#include <rtems/score/isrlock.h>
 #include <rtems/score/threadq.h>
 #include <rtems/score/watchdog.h>
 
@@ -63,6 +64,8 @@ extern "C" {
   #define RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND
 #endif
 
+typedef struct CORE_message_queue_Control CORE_message_queue_Control;
+
 /**
  *  @brief Data types needed to manipulate the contents of message buffers.
  *
@@ -117,7 +120,10 @@ typedef enum {
    *  notification handler is invoked when the message queue makes a
    *  0->1 transition on pending messages.
    */
-  typedef void (*CORE_message_queue_Notify_Handler)( void * );
+  typedef void (*CORE_message_queue_Notify_Handler)(
+    CORE_message_queue_Control *,
+    ISR_lock_Context *
+  );
 #endif
 
 /**
@@ -126,7 +132,7 @@ typedef enum {
  *  The following defines the control block used to manage each
  *  Message Queue.
  */
-typedef struct {
+struct CORE_message_queue_Control {
   /** This field is the Waiting Queue used to manage the set of tasks
    *  which are blocked waiting to receive a message from this queue.
    */
@@ -162,14 +168,12 @@ typedef struct {
      *  from zero (0) messages pending to one (1) message pending.
      */
     CORE_message_queue_Notify_Handler  notify_handler;
-    /** This field is the argument passed to the @ref notify_argument. */
-    void                              *notify_argument;
   #endif
   /** This chain is the set of inactive messages.  A message is inactive
    *  when it does not contain a pending message.
    */
   Chain_Control                      Inactive_messages;
-}   CORE_message_queue_Control;
+};
 
 /**@}*/
 
diff --git a/cpukit/score/include/rtems/score/coremsgimpl.h b/cpukit/score/include/rtems/score/coremsgimpl.h
index b610397..e3f0153 100644
--- a/cpukit/score/include/rtems/score/coremsgimpl.h
+++ b/cpukit/score/include/rtems/score/coremsgimpl.h
@@ -612,17 +612,15 @@ RTEMS_INLINE_ROUTINE
 #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
   RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
     CORE_message_queue_Control        *the_message_queue,
-    CORE_message_queue_Notify_Handler  the_handler,
-    void                              *the_argument
+    CORE_message_queue_Notify_Handler  the_handler
   )
   {
-    the_message_queue->notify_handler  = the_handler;
-    the_message_queue->notify_argument = the_argument;
+    the_message_queue->notify_handler = the_handler;
   }
 #else
   /* turn it into nothing if not enabled */
-  #define _CORE_message_queue_Set_notify( \
-           the_message_queue, the_handler, the_argument )
+  #define _CORE_message_queue_Set_notify( the_message_queue, the_handler ) \
+    do { } while ( 0 )
 #endif
 
 RTEMS_INLINE_ROUTINE Thread_Control *_CORE_message_queue_Do_dequeue_receiver(
diff --git a/cpukit/score/src/coremsg.c b/cpukit/score/src/coremsg.c
index b184585..03c0587 100644
--- a/cpukit/score/src/coremsg.c
+++ b/cpukit/score/src/coremsg.c
@@ -55,7 +55,7 @@ bool _CORE_message_queue_Initialize(
   the_message_queue->maximum_pending_messages   = maximum_pending_messages;
   the_message_queue->number_of_pending_messages = 0;
   the_message_queue->maximum_message_size       = maximum_message_size;
-  _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL );
+  _CORE_message_queue_Set_notify( the_message_queue, NULL );
 
   allocated_message_size = maximum_message_size;
 
diff --git a/cpukit/score/src/coremsginsert.c b/cpukit/score/src/coremsginsert.c
index 8baea360..4613f50 100644
--- a/cpukit/score/src/coremsginsert.c
+++ b/cpukit/score/src/coremsginsert.c
@@ -46,9 +46,6 @@ void _CORE_message_queue_Insert_message(
 )
 {
   Chain_Control *pending_messages;
-#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
-  bool           notify;
-#endif
 
   the_message->Contents.size = content_size;
 
@@ -63,10 +60,6 @@ void _CORE_message_queue_Insert_message(
 #endif
 
   pending_messages = &the_message_queue->Pending_messages;
-
-#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
-  notify = ( the_message_queue->number_of_pending_messages == 0 );
-#endif
   ++the_message_queue->number_of_pending_messages;
 
   if ( submit_type == CORE_MESSAGE_QUEUE_SEND_REQUEST ) {
@@ -82,14 +75,4 @@ void _CORE_message_queue_Insert_message(
   } else {
     _Chain_Prepend_unprotected( pending_messages, &the_message->Node );
   }
-
-  #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
-    /*
-     *  According to POSIX, does this happen before or after the message
-     *  is actually enqueued.  It is logical to think afterwards, because
-     *  the message is actually in the queue at this point.
-     */
-    if ( notify && the_message_queue->notify_handler )
-      (*the_message_queue->notify_handler)(the_message_queue->notify_argument);
-  #endif
 }
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
index 1d6d298..7e589e7 100644
--- a/cpukit/score/src/coremsgsubmit.c
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -79,7 +79,28 @@ CORE_message_queue_Status _CORE_message_queue_Do_submit(
       size,
       submit_type
     );
+
+#if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
+    /*
+     *  According to POSIX, does this happen before or after the message
+     *  is actually enqueued.  It is logical to think afterwards, because
+     *  the message is actually in the queue at this point.
+     */
+    if (
+      the_message_queue->number_of_pending_messages == 1
+        && the_message_queue->notify_handler != NULL
+    ) {
+      ( *the_message_queue->notify_handler )(
+        the_message_queue,
+        lock_context
+      );
+    } else {
+      _CORE_message_queue_Release( the_message_queue, lock_context );
+    }
+#else
     _CORE_message_queue_Release( the_message_queue, lock_context );
+#endif
+
     return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
   }
 
-- 
1.8.4.5



More information about the devel mailing list