[rtems commit] rtems: Add rtems_message_queue_construct()

Sebastian Huber sebh at rtems.org
Mon Sep 28 05:17:52 UTC 2020


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Sep 23 16:47:58 2020 +0200

rtems: Add rtems_message_queue_construct()

In contrast to message queues created by rtems_message_queue_create(), the
message queues constructed by this directive use a user-provided message buffer
storage area.

Add RTEMS_MESSAGE_QUEUE_BUFFER() to define a message buffer type for message
buffer storage areas.

Update #4007.

---

 cpukit/Makefile.am                       |   2 +
 cpukit/include/rtems/rtems/message.h     | 131 +++++++++++++++++++++
 cpukit/include/rtems/rtems/messageimpl.h |  17 +++
 cpukit/include/rtems/score/coremsg.h     |  10 ++
 cpukit/include/rtems/score/coremsgimpl.h |  67 ++++++++++-
 cpukit/posix/src/mqueueopen.c            |   4 +-
 cpukit/rtems/src/msgqconstruct.c         | 189 +++++++++++++++++++++++++++++++
 cpukit/rtems/src/msgqcreate.c            | 178 +++++++----------------------
 cpukit/score/src/coremsg.c               |  17 +--
 cpukit/score/src/coremsgclose.c          |   7 +-
 cpukit/score/src/coremsgwkspace.c        |  53 +++++++++
 spec/build/cpukit/librtemscpu.yml        |   2 +
 testsuites/mptests/mp09/initimpl.h       |  26 ++++-
 testsuites/mptests/mp09/system.h         |  17 +--
 testsuites/mptests/mp09/task1.c          |  16 +++
 testsuites/sptests/sp13/init.c           |  21 ++--
 testsuites/sptests/sp13/system.h         |   2 +-
 17 files changed, 590 insertions(+), 169 deletions(-)

diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index e2bed4b..2c35354 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -706,6 +706,7 @@ librtemscpu_a_SOURCES += rtems/src/intrcatch.c
 librtemscpu_a_SOURCES += rtems/src/modes.c
 librtemscpu_a_SOURCES += rtems/src/msg.c
 librtemscpu_a_SOURCES += rtems/src/msgqbroadcast.c
+librtemscpu_a_SOURCES += rtems/src/msgqconstruct.c
 librtemscpu_a_SOURCES += rtems/src/msgqcreate.c
 librtemscpu_a_SOURCES += rtems/src/msgqdelete.c
 librtemscpu_a_SOURCES += rtems/src/msgqflush.c
@@ -839,6 +840,7 @@ librtemscpu_a_SOURCES += score/src/coremsgflushwait.c
 librtemscpu_a_SOURCES += score/src/coremsginsert.c
 librtemscpu_a_SOURCES += score/src/coremsgseize.c
 librtemscpu_a_SOURCES += score/src/coremsgsubmit.c
+librtemscpu_a_SOURCES += score/src/coremsgwkspace.c
 librtemscpu_a_SOURCES += score/src/coremutexseize.c
 librtemscpu_a_SOURCES += score/src/percpu.c
 librtemscpu_a_SOURCES += score/src/percpuasm.c
diff --git a/cpukit/include/rtems/rtems/message.h b/cpukit/include/rtems/rtems/message.h
index 675cd98..14083b8 100644
--- a/cpukit/include/rtems/rtems/message.h
+++ b/cpukit/include/rtems/rtems/message.h
@@ -21,6 +21,7 @@
 #include <rtems/rtems/options.h>
 #include <rtems/rtems/status.h>
 #include <rtems/rtems/types.h>
+#include <rtems/score/coremsgbuffer.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,6 +38,136 @@ extern "C" {
 /**@{*/
 
 /**
+ * @brief This structure defines the configuration of a message queue
+ *   constructed by rtems_message_queue_construct().
+ */
+typedef struct {
+  /**
+   * @brief This member defines the name of the message queue.
+   */
+  rtems_name name;
+
+  /**
+   * @brief This member defines the maximum number of pending messages supported
+   *   by the message queue.
+   */
+  uint32_t maximum_pending_messages;
+
+  /**
+   * @brief This member defines the maximum message size supported by the message
+   *   queue.
+   */
+  size_t maximum_message_size;
+
+  /**
+   * @brief This member shall point to the message buffer storage area begin.
+   *
+   * The message buffer storage area for the message queue shall be an array of
+   * the type defined by RTEMS_MESSAGE_QUEUE_BUFFER() with a maximum message size
+   * equal to the maximum message size of this configuration.
+   */
+  void *storage_area;
+
+  /**
+   * @brief This member defines size of the message buffer storage area in bytes.
+   */
+  size_t storage_size;
+
+  /**
+   * @brief This member defines the optional handler to free the message buffer
+   *   storage area.
+   *
+   * It is called when the message queue is deleted.  It is called from task
+   * context under protection of the object allocator lock.  It is allowed to
+   * call free() in this handler.  If handler is NULL, then no action will be
+   * performed.
+   */
+  void ( *storage_free )( void * );
+
+  /**
+   * @brief This member defines the attributes of the message queue.
+   */
+  rtems_attribute attributes;
+} rtems_message_queue_config;
+
+/**
+ * @brief Defines a structure which can be used as a message queue buffer for
+ *   messages of the specified maximum size.
+ *
+ * Use this macro to define the message buffer storage area for
+ * rtems_message_queue_construct().
+ *
+ * @param _maximum_message_size is the maximum message size in bytes.
+ */
+#define RTEMS_MESSAGE_QUEUE_BUFFER( _maximum_message_size ) \
+  struct { \
+    CORE_message_queue_Buffer _buffer; \
+    char _message[ _maximum_message_size ]; \
+  }
+
+/**
+ * @brief Constructs a message queue from the specified the message queue
+ *   configuration.
+ *
+ * In contrast to message queues created by rtems_message_queue_create(), the
+ * message queues constructed by this directive use a user-provided message
+ * buffer storage area.
+ *
+ * This directive is intended for applications which do not want to use the
+ * RTEMS Workspace and instead statically allocate all operating system
+ * resources.  An application based solely on static allocation can avoid any
+ * runtime memory allocators.  This can simplify the application architecture
+ * as well as any analysis that may be required.
+ *
+ * The value for #CONFIGURE_MESSAGE_BUFFER_MEMORY should not include memory for
+ * message queues constructed by rtems_message_queue_construct().
+ *
+ * @param config is the message queue configuration.
+ *
+ * @param[out] id is the pointer to an object identifier variable.  The
+ *   identifier of the constructed message queue object will be stored in this
+ *   variable, in case of a successful operation.
+ *
+ * @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
+ *
+ * @retval ::RTEMS_INVALID_ADDRESS The id parameter was NULL.
+ *
+ * @retval ::RTEMS_INVALID_NAME The message queue name in the configuration was
+ *   invalid.
+ *
+ * @retval ::RTEMS_INVALID_NUMBER The maximum number of pending messages in the
+ *   configuration was zero.
+ *
+ * @retval ::RTEMS_INVALID_SIZE The maximum message size in the configuration
+ *   was zero.
+ *
+ * @retval ::RTEMS_TOO_MANY There was no inactive message queue object
+ *   available to construct a message queue.
+ *
+ * @retval ::RTEMS_TOO_MANY In multiprocessing configurations, there was no
+ *   inactive global object available to construct a global message queue.
+ *
+ * @retval ::RTEMS_INVALID_SIZE The maximum message size in the configuration
+ *   was too big and resulted in integer overflows in calculations carried out
+ *   to determine the size of the message buffer area.
+ *
+ * @retval ::RTEMS_INVALID_NUMBER The maximum number of pending messages in the
+ *   configuration was too big and resulted in integer overflows in
+ *   calculations carried out to determine the size of the message buffer area.
+ *
+ * @retval ::RTEMS_UNSATISFIED The message queue storage area begin pointer in
+ *   the configuration was NULL.
+ *
+ * @retval ::RTEMS_UNSATISFIED The message queue storage area size in the
+ *   configuration was not equal to the size calculated from the maximum number
+ *   of pending messages and the maximum message size.
+ */
+rtems_status_code rtems_message_queue_construct(
+  const rtems_message_queue_config *config,
+  rtems_id                         *id
+);
+
+/**
  * @brief RTEMS Create Message Queue
  *
  * This routine implements the rtems_message_queue_create directive. The
diff --git a/cpukit/include/rtems/rtems/messageimpl.h b/cpukit/include/rtems/rtems/messageimpl.h
index e317244..c90ac97 100644
--- a/cpukit/include/rtems/rtems/messageimpl.h
+++ b/cpukit/include/rtems/rtems/messageimpl.h
@@ -101,6 +101,23 @@ RTEMS_INLINE_ROUTINE Message_queue_Control *_Message_queue_Allocate( void )
     _Objects_Allocate( &_Message_queue_Information );
 }
 
+/**
+ * @brief Creates a message queue.
+ *
+ * @param config is the message queue configuration.
+ *
+ * @param[out] id contains the object identifier if the operation was
+ *   successful.
+ *
+ * @param allocate_buffers is the message buffer storage area allocation
+ *   handler.
+ */
+rtems_status_code _Message_queue_Create(
+  const rtems_message_queue_config    *config,
+  rtems_id                            *id,
+  CORE_message_queue_Allocate_buffers  allocate_buffers
+);
+
 /**@}*/
 
 #ifdef __cplusplus
diff --git a/cpukit/include/rtems/score/coremsg.h b/cpukit/include/rtems/score/coremsg.h
index 220c983..51c638b 100644
--- a/cpukit/include/rtems/score/coremsg.h
+++ b/cpukit/include/rtems/score/coremsg.h
@@ -124,6 +124,16 @@ struct CORE_message_queue_Control {
    *  as part of destroying it.
    */
   CORE_message_queue_Buffer         *message_buffers;
+
+  /**
+   * @brief This member contains the optional message buffer storage area free
+   * handler.
+   *
+   * It may be NULL.  In this case no action is performed to free the message
+   * buffer storage area.
+   */
+  void                            ( *free_message_buffers )( void * );
+
   #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
     /** This is the routine invoked when the message queue transitions
      *  from zero (0) messages pending to one (1) message pending.
diff --git a/cpukit/include/rtems/score/coremsgimpl.h b/cpukit/include/rtems/score/coremsgimpl.h
index cb84bfb..0bf5fa5 100644
--- a/cpukit/include/rtems/score/coremsgimpl.h
+++ b/cpukit/include/rtems/score/coremsgimpl.h
@@ -69,6 +69,54 @@ extern "C" {
 typedef int CORE_message_queue_Submit_types;
 
 /**
+ * @brief This handler shall allocate the message buffer storage area for a
+ *   message queue.
+ *
+ * The handler shall set the CORE_message_queue_Control::free_message_buffers
+ * member.
+ *
+ * @param[out] the_message_queue is the message queue control.
+ *
+ * @param size is the message buffer storage area size to allocate.
+ *
+ * @param arg is the handler argument.
+ *
+ * @retval NULL The allocation failed.
+ *
+ * @return Otherwise the pointer to the allocated message buffer storage area
+ *   begin shall be returned.
+ */
+typedef void *( *CORE_message_queue_Allocate_buffers )(
+  CORE_message_queue_Control *the_message_queue,
+  size_t                      size,
+  const void                 *arg
+);
+
+/**
+ * @brief This handler allocates the message buffer storage area for a message
+ *   queue from the RTEMS Workspace.
+ *
+ * The handler sets the CORE_message_queue_Control::free_message_buffers
+ * to _Workspace_Free().
+ *
+ * @param[out] the_message_queue is the message queue control.
+ *
+ * @param size is the message buffer storage area size to allocate.
+ *
+ * @param arg is the unused handler argument.
+ *
+ * @retval NULL The allocation failed.
+ *
+ * @return Otherwise the pointer to the allocated message buffer storage area
+ *   begin is returned.
+ */
+void *_CORE_message_queue_Workspace_allocate(
+  CORE_message_queue_Control *the_message_queue,
+  size_t                      size,
+  const void                 *arg
+);
+
+/**
  * @brief Initializes a message queue.
  *
  * @param[out] the_message_queue is the message queue to initialize.
@@ -81,19 +129,26 @@ typedef int CORE_message_queue_Submit_types;
  * @param maximum_message_size is the size of the largest message that may be
  *   sent to this message queue instance.
  *
+ * @param allocate_buffers is the message buffer storage area allocation
+ *   handler.
+ *
+ * @param arg is the message buffer storage area allocation handler argument.
+ *
  * @retval STATUS_SUCCESSFUL The message queue was initialized.
  *
  * @retval STATUS_MESSAGE_QUEUE_INVALID_SIZE Calculations with the maximum
  *   pending messages or maximum message size produced an integer overflow.
  *
- * @retval STATUS_MESSAGE_QUEUE_NO_MEMORY There was not enough memory to
- *   allocate the message buffers.
+ * @retval STATUS_MESSAGE_QUEUE_NO_MEMORY The message buffer storage area
+ *   allocation failed.
  */
 Status_Control _CORE_message_queue_Initialize(
-  CORE_message_queue_Control     *the_message_queue,
-  CORE_message_queue_Disciplines  discipline,
-  uint32_t                        maximum_pending_messages,
-  size_t                          maximum_message_size
+  CORE_message_queue_Control          *the_message_queue,
+  CORE_message_queue_Disciplines       discipline,
+  uint32_t                             maximum_pending_messages,
+  size_t                               maximum_message_size,
+  CORE_message_queue_Allocate_buffers  allocate_buffers,
+  const void                          *arg
 );
 
 /**
diff --git a/cpukit/posix/src/mqueueopen.c b/cpukit/posix/src/mqueueopen.c
index af8abeb..af50dc2 100644
--- a/cpukit/posix/src/mqueueopen.c
+++ b/cpukit/posix/src/mqueueopen.c
@@ -102,7 +102,9 @@ static mqd_t _POSIX_Message_queue_Create(
     &the_mq->Message_queue,
     CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO,
     attr->mq_maxmsg,
-    attr->mq_msgsize
+    attr->mq_msgsize,
+    _CORE_message_queue_Workspace_allocate,
+    NULL
   );
 
   if ( status != STATUS_SUCCESSFUL ) {
diff --git a/cpukit/rtems/src/msgqconstruct.c b/cpukit/rtems/src/msgqconstruct.c
new file mode 100644
index 0000000..61d0472
--- /dev/null
+++ b/cpukit/rtems/src/msgqconstruct.c
@@ -0,0 +1,189 @@
+/**
+ *  @file
+ *
+ *  @brief RTEMS Create Message Queue
+ *  @ingroup ClassicMessageQueue
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2014.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/rtems/messageimpl.h>
+#include <rtems/rtems/attrimpl.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/coremsgimpl.h>
+#include <rtems/sysinit.h>
+
+static void *_Message_queue_Get_buffers(
+  CORE_message_queue_Control *the_message_queue,
+  size_t                      size,
+  const void                 *arg
+)
+{
+  const rtems_message_queue_config *config;
+
+  config = arg;
+
+  if ( config->storage_size != size ) {
+    return NULL;
+  }
+
+  the_message_queue->free_message_buffers = config->storage_free;
+  return config->storage_area;
+}
+
+rtems_status_code rtems_message_queue_construct(
+  const rtems_message_queue_config *config,
+  rtems_id                         *id
+)
+{
+  return _Message_queue_Create( config, id, _Message_queue_Get_buffers );
+}
+
+rtems_status_code _Message_queue_Create(
+  const rtems_message_queue_config    *config,
+  rtems_id                            *id,
+  CORE_message_queue_Allocate_buffers  allocate_buffers
+)
+{
+  Message_queue_Control          *the_message_queue;
+  CORE_message_queue_Disciplines  discipline;
+  Status_Control                  status;
+#if defined(RTEMS_MULTIPROCESSING)
+  bool                            is_global;
+#endif
+
+  if ( id == NULL ) {
+    return RTEMS_INVALID_ADDRESS;
+  }
+
+  if ( !rtems_is_name_valid( config->name ) ) {
+    return RTEMS_INVALID_NAME;
+  }
+
+  if ( config->maximum_pending_messages == 0 ) {
+    return RTEMS_INVALID_NUMBER;
+  }
+
+  if ( config->maximum_message_size == 0 ) {
+    return RTEMS_INVALID_SIZE;
+  }
+
+#if defined(RTEMS_MULTIPROCESSING)
+  if ( _System_state_Is_multiprocessing ) {
+    is_global = _Attributes_Is_global( config->attributes );
+  } else {
+    is_global = false;
+  }
+
+#if 1
+  /*
+   * I am not 100% sure this should be an error.
+   * It seems reasonable to create a que with a large max size,
+   * and then just send smaller msgs from remote (or all) nodes.
+   */
+  if ( is_global ) {
+    size_t max_packet_payload_size = _MPCI_table->maximum_packet_size
+      - MESSAGE_QUEUE_MP_PACKET_SIZE;
+
+    if ( config->maximum_message_size > max_packet_payload_size ) {
+      return RTEMS_INVALID_SIZE;
+    }
+  }
+#endif
+#endif
+
+  the_message_queue = _Message_queue_Allocate();
+
+  if ( !the_message_queue ) {
+    _Objects_Allocator_unlock();
+    return RTEMS_TOO_MANY;
+  }
+
+#if defined(RTEMS_MULTIPROCESSING)
+  if (
+    is_global
+      && !_Objects_MP_Allocate_and_open(
+            &_Message_queue_Information,
+            config->name,
+            the_message_queue->Object.id,
+            false
+          )
+  ) {
+    _Message_queue_Free( the_message_queue );
+    _Objects_Allocator_unlock();
+    return RTEMS_TOO_MANY;
+  }
+
+  the_message_queue->is_global = is_global;
+#endif
+
+  if ( _Attributes_Is_priority( config->attributes ) ) {
+    discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY;
+  } else {
+    discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
+  }
+
+  status = _CORE_message_queue_Initialize(
+    &the_message_queue->message_queue,
+    discipline,
+    config->maximum_pending_messages,
+    config->maximum_message_size,
+    allocate_buffers,
+    config
+  );
+
+  if ( status != STATUS_SUCCESSFUL ) {
+#if defined(RTEMS_MULTIPROCESSING)
+    if ( is_global )
+        _Objects_MP_Close(
+          &_Message_queue_Information, the_message_queue->Object.id);
+#endif
+
+    _Message_queue_Free( the_message_queue );
+    _Objects_Allocator_unlock();
+    return STATUS_GET_CLASSIC( status );
+  }
+
+  _Objects_Open(
+    &_Message_queue_Information,
+    &the_message_queue->Object,
+    (Objects_Name) config->name
+  );
+
+  *id = the_message_queue->Object.id;
+
+#if defined(RTEMS_MULTIPROCESSING)
+  if ( is_global )
+    _Message_queue_MP_Send_process_packet(
+      MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,
+      the_message_queue->Object.id,
+      config->name,
+      0
+    );
+#endif
+
+  _Objects_Allocator_unlock();
+  return RTEMS_SUCCESSFUL;
+}
+
+static void _Message_queue_Manager_initialization( void )
+{
+  _Objects_Initialize_information( &_Message_queue_Information);
+}
+
+RTEMS_SYSINIT_ITEM(
+  _Message_queue_Manager_initialization,
+  RTEMS_SYSINIT_CLASSIC_MESSAGE_QUEUE,
+  RTEMS_SYSINIT_ORDER_MIDDLE
+);
diff --git a/cpukit/rtems/src/msgqcreate.c b/cpukit/rtems/src/msgqcreate.c
index 20787f0..7469f10 100644
--- a/cpukit/rtems/src/msgqcreate.c
+++ b/cpukit/rtems/src/msgqcreate.c
@@ -1,17 +1,37 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
 /**
- *  @file
+ * @file
+ *
+ * @ingroup ClassicMessageQueueImpl
  *
- *  @brief RTEMS Create Message Queue
- *  @ingroup ClassicMessageQueue
+ * @brief This source file contains the implementation of
+ *   rtems_message_queue_create().
  */
 
 /*
- *  COPYRIGHT (c) 1989-2014.
- *  On-Line Applications Research Corporation (OAR).
+ * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- *  The license and distribution terms for this file may be
- *  found in the file LICENSE in this distribution or at
- *  http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -19,17 +39,9 @@
 #endif
 
 #include <rtems/rtems/messageimpl.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/attrimpl.h>
-#include <rtems/rtems/options.h>
-#include <rtems/rtems/support.h>
-#include <rtems/score/sysstate.h>
-#include <rtems/score/chain.h>
-#include <rtems/score/isr.h>
 #include <rtems/score/coremsgimpl.h>
-#include <rtems/score/thread.h>
-#include <rtems/score/wkspace.h>
-#include <rtems/sysinit.h>
+
+#include <string.h>
 
 rtems_status_code rtems_message_queue_create(
   rtems_name       name,
@@ -39,123 +51,17 @@ rtems_status_code rtems_message_queue_create(
   rtems_id        *id
 )
 {
-  Message_queue_Control          *the_message_queue;
-  CORE_message_queue_Disciplines  discipline;
-  Status_Control                  status;
-#if defined(RTEMS_MULTIPROCESSING)
-  bool                            is_global;
-#endif
-
-  if ( !rtems_is_name_valid( name ) )
-    return RTEMS_INVALID_NAME;
-
-  if ( !id )
-    return RTEMS_INVALID_ADDRESS;
-
-#if defined(RTEMS_MULTIPROCESSING)
-  if ( _System_state_Is_multiprocessing ) {
-    is_global = _Attributes_Is_global( attribute_set );
-  } else {
-    is_global = false;
-  }
-#endif
-
-  if ( count == 0 )
-      return RTEMS_INVALID_NUMBER;
-
-  if ( max_message_size == 0 )
-      return RTEMS_INVALID_SIZE;
-
-#if defined(RTEMS_MULTIPROCESSING)
-#if 1
-  /*
-   * I am not 100% sure this should be an error.
-   * It seems reasonable to create a que with a large max size,
-   * and then just send smaller msgs from remote (or all) nodes.
-   */
-  if ( is_global ) {
-    size_t max_packet_payload_size = _MPCI_table->maximum_packet_size
-      - MESSAGE_QUEUE_MP_PACKET_SIZE;
-
-    if ( max_message_size > max_packet_payload_size ) {
-      return RTEMS_INVALID_SIZE;
-    }
-  }
-#endif
-#endif
-
-  the_message_queue = _Message_queue_Allocate();
-
-  if ( !the_message_queue ) {
-    _Objects_Allocator_unlock();
-    return RTEMS_TOO_MANY;
-  }
-
-#if defined(RTEMS_MULTIPROCESSING)
-  if ( is_global &&
-    !( _Objects_MP_Allocate_and_open( &_Message_queue_Information,
-                              name, the_message_queue->Object.id, false ) ) ) {
-    _Message_queue_Free( the_message_queue );
-    _Objects_Allocator_unlock();
-    return RTEMS_TOO_MANY;
-  }
-
-  the_message_queue->is_global = is_global;
-#endif
-
-  if (_Attributes_Is_priority( attribute_set ) )
-    discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY;
-  else
-    discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
-
-  status = _CORE_message_queue_Initialize(
-    &the_message_queue->message_queue,
-    discipline,
-    count,
-    max_message_size
-  );
-
-  if ( status != STATUS_SUCCESSFUL ) {
-#if defined(RTEMS_MULTIPROCESSING)
-    if ( is_global )
-        _Objects_MP_Close(
-          &_Message_queue_Information, the_message_queue->Object.id);
-#endif
-
-    _Message_queue_Free( the_message_queue );
-    _Objects_Allocator_unlock();
-    return STATUS_GET_CLASSIC( status );
-  }
-
-  _Objects_Open(
-    &_Message_queue_Information,
-    &the_message_queue->Object,
-    (Objects_Name) name
+  rtems_message_queue_config config;
+
+  memset( &config, 0, sizeof( config ) );
+  config.name = name;
+  config.maximum_pending_messages = count;
+  config.maximum_message_size = max_message_size;
+  config.attributes = attribute_set;
+
+  return _Message_queue_Create(
+    &config,
+    id,
+    _CORE_message_queue_Workspace_allocate
   );
-
-  *id = the_message_queue->Object.id;
-
-#if defined(RTEMS_MULTIPROCESSING)
-  if ( is_global )
-    _Message_queue_MP_Send_process_packet(
-      MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,
-      the_message_queue->Object.id,
-      name,
-      0
-    );
-#endif
-
-  _Objects_Allocator_unlock();
-  return RTEMS_SUCCESSFUL;
 }
-
-static void _Message_queue_Manager_initialization( void )
-{
-  _Objects_Initialize_information( &_Message_queue_Information);
-}
-
-RTEMS_SYSINIT_ITEM(
-  _Message_queue_Manager_initialization,
-  RTEMS_SYSINIT_CLASSIC_MESSAGE_QUEUE,
-  RTEMS_SYSINIT_ORDER_MIDDLE
-);
diff --git a/cpukit/score/src/coremsg.c b/cpukit/score/src/coremsg.c
index f7caca1e..967ce23 100644
--- a/cpukit/score/src/coremsg.c
+++ b/cpukit/score/src/coremsg.c
@@ -20,7 +20,6 @@
 
 #include <rtems/score/coremsgimpl.h>
 #include <rtems/score/assert.h>
-#include <rtems/score/wkspace.h>
 
 #define MESSAGE_SIZE_LIMIT \
   ( SIZE_MAX - sizeof( uintptr_t ) + 1 - sizeof( CORE_message_queue_Buffer ) )
@@ -32,10 +31,12 @@ RTEMS_STATIC_ASSERT(
 );
 
 Status_Control _CORE_message_queue_Initialize(
-  CORE_message_queue_Control     *the_message_queue,
-  CORE_message_queue_Disciplines  discipline,
-  uint32_t                        maximum_pending_messages,
-  size_t                          maximum_message_size
+  CORE_message_queue_Control          *the_message_queue,
+  CORE_message_queue_Disciplines       discipline,
+  uint32_t                             maximum_pending_messages,
+  size_t                               maximum_message_size,
+  CORE_message_queue_Allocate_buffers  allocate_buffers,
+  const void                          *arg
 )
 {
   size_t buffer_size;
@@ -56,8 +57,10 @@ Status_Control _CORE_message_queue_Initialize(
     return STATUS_MESSAGE_QUEUE_INVALID_NUMBER;
   }
 
-  the_message_queue->message_buffers = _Workspace_Allocate(
-    (size_t) maximum_pending_messages * buffer_size
+  the_message_queue->message_buffers = ( *allocate_buffers )(
+    the_message_queue,
+    (size_t) maximum_pending_messages * buffer_size,
+    arg
   );
 
   if ( the_message_queue->message_buffers == NULL ) {
diff --git a/cpukit/score/src/coremsgclose.c b/cpukit/score/src/coremsgclose.c
index 18b49b0..98032dd 100644
--- a/cpukit/score/src/coremsgclose.c
+++ b/cpukit/score/src/coremsgclose.c
@@ -19,7 +19,6 @@
 #endif
 
 #include <rtems/score/coremsgimpl.h>
-#include <rtems/score/wkspace.h>
 
 static Thread_Control *_CORE_message_queue_Was_deleted(
   Thread_Control       *the_thread,
@@ -50,7 +49,11 @@ void _CORE_message_queue_Close(
     queue_context
   );
 
-  (void) _Workspace_Free( the_message_queue->message_buffers );
+  if ( the_message_queue->free_message_buffers != NULL ) {
+    ( *the_message_queue->free_message_buffers )(
+      the_message_queue->message_buffers
+    );
+  }
 
   _Thread_queue_Destroy( &the_message_queue->Wait_queue );
 }
diff --git a/cpukit/score/src/coremsgwkspace.c b/cpukit/score/src/coremsgwkspace.c
new file mode 100644
index 0000000..8441701
--- /dev/null
+++ b/cpukit/score/src/coremsgwkspace.c
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreMessageQueue
+ *
+ * @brief This source file contains the implementation of
+ *   _CORE_message_queue_Workspace_allocate().
+ */
+
+/*
+ * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/coremsgimpl.h>
+#include <rtems/score/wkspace.h>
+
+void *_CORE_message_queue_Workspace_allocate(
+  CORE_message_queue_Control *the_message_queue,
+  size_t                      size,
+  const void                 *arg
+)
+{
+  (void) arg;
+  the_message_queue->free_message_buffers = _Workspace_Free;
+  return _Workspace_Allocate( size );
+}
diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml
index 2baf8ef..21dc239 100644
--- a/spec/build/cpukit/librtemscpu.yml
+++ b/spec/build/cpukit/librtemscpu.yml
@@ -1198,6 +1198,7 @@ source:
 - cpukit/rtems/src/modes.c
 - cpukit/rtems/src/msg.c
 - cpukit/rtems/src/msgqbroadcast.c
+- cpukit/rtems/src/msgqconstruct.c
 - cpukit/rtems/src/msgqcreate.c
 - cpukit/rtems/src/msgqdelete.c
 - cpukit/rtems/src/msgqflush.c
@@ -1376,6 +1377,7 @@ source:
 - cpukit/score/src/coremsginsert.c
 - cpukit/score/src/coremsgseize.c
 - cpukit/score/src/coremsgsubmit.c
+- cpukit/score/src/coremsgwkspace.c
 - cpukit/score/src/coremutexseize.c
 - cpukit/score/src/corerwlock.c
 - cpukit/score/src/corerwlockobtainread.c
diff --git a/testsuites/mptests/mp09/initimpl.h b/testsuites/mptests/mp09/initimpl.h
index ff18c51..c7377f3 100644
--- a/testsuites/mptests/mp09/initimpl.h
+++ b/testsuites/mptests/mp09/initimpl.h
@@ -26,6 +26,23 @@
 #define CONFIGURE_INIT
 #include "system.h"
 
+#if CONFIGURE_MP_NODE_NUMBER == 1
+
+#define MESSAGE_SIZE 1
+
+static RTEMS_MESSAGE_QUEUE_BUFFER( MESSAGE_SIZE ) buffers[ 1 ];
+
+static const rtems_message_queue_config config = {
+  .name = rtems_build_name( 'M', 'S', 'G', '2' ),
+  .maximum_pending_messages = RTEMS_ARRAY_SIZE( buffers ),
+  .maximum_message_size = MESSAGE_SIZE,
+  .storage_area = buffers,
+  .storage_size = sizeof( buffers ),
+  .attributes = RTEMS_GLOBAL
+};
+
+#endif
+
 rtems_task Init(
   rtems_task_argument argument
 )
@@ -40,10 +57,17 @@ rtems_task Init(
   Task_name[ 1 ] = rtems_build_name( '1', '1', '1', ' ' );
   Task_name[ 2 ] = rtems_build_name( '2', '2', '2', ' ' );
 
-  Queue_name[ 1 ] = rtems_build_name( 'M', 'S', 'G', ' ' );
+  Queue_name[ 1 ] = rtems_build_name( 'M', 'S', 'G', '1' );
+  Queue_name[ 2 ] = rtems_build_name( 'M', 'S', 'G', '2' );
 
   if ( rtems_object_get_local_node() == 1 ) {
     puts( "Creating Message Queue (Global)" );
+
+#if CONFIGURE_MP_NODE_NUMBER == 1
+    status = rtems_message_queue_construct( &config, &Queue_id[ 2 ] );
+    directive_failed( status, "rtems_message_queue_construct" );
+#endif
+
     status = rtems_message_queue_create(
       Queue_name[ 1 ],
       3,
diff --git a/testsuites/mptests/mp09/system.h b/testsuites/mptests/mp09/system.h
index 4fdddc4..9ecea2d 100644
--- a/testsuites/mptests/mp09/system.h
+++ b/testsuites/mptests/mp09/system.h
@@ -34,11 +34,14 @@ void Send_messages( void );
 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 
-#define CONFIGURE_MAXIMUM_TASKS               2
-#define CONFIGURE_MAXIMUM_TIMERS              1
-#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES      1
-#define CONFIGURE_MESSAGE_BUFFER_MEMORY \
-  CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 3, 16 )
+#define CONFIGURE_MAXIMUM_TASKS 2
+#define CONFIGURE_MAXIMUM_TIMER 1
+
+#if CONFIGURE_MP_NODE_NUMBER == 1
+  #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 2
+  #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
+    CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 3, 16 )
+#endif
 
 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
 
@@ -49,8 +52,8 @@ void Send_messages( void );
 TEST_EXTERN rtems_id   Task_id[ 4 ];     /* array of task ids */
 TEST_EXTERN rtems_name Task_name[ 4 ];   /* array of task names */
 
-TEST_EXTERN rtems_id   Queue_id[ 2 ];    /* array of message queue ids */
-TEST_EXTERN rtems_name Queue_name[ 2 ];  /* array of message queue names */
+TEST_EXTERN rtems_id   Queue_id[ 3 ];    /* array of message queue ids */
+TEST_EXTERN rtems_name Queue_name[ 3 ];  /* array of message queue names */
 
 extern char buffer1[16];
 extern char buffer2[16];
diff --git a/testsuites/mptests/mp09/task1.c b/testsuites/mptests/mp09/task1.c
index dc78552..b929a6e 100644
--- a/testsuites/mptests/mp09/task1.c
+++ b/testsuites/mptests/mp09/task1.c
@@ -49,7 +49,20 @@ rtems_task Test_task(
     );
   } while ( !rtems_is_status_successful( status ) );
 
+  status = rtems_message_queue_ident(
+    Queue_name[ 2 ],
+    RTEMS_SEARCH_ALL_NODES,
+    &Queue_id[ 2 ]
+  );
+  directive_failed( status, "rtems_message_queue_ident" );
+
   if ( rtems_object_get_local_node() == 2 ) {
+    status = rtems_message_queue_delete( Queue_id[ 2 ] );
+    fatal_directive_status(
+      status,
+      RTEMS_ILLEGAL_ON_REMOTE_OBJECT,
+      "rtems_message_queue_delete"
+    );
     status = rtems_message_queue_delete( Queue_id[ 1 ] );
     fatal_directive_status(
       status,
@@ -103,6 +116,9 @@ rtems_task Test_task(
     puts( "Deleting Message queue" );
     status = rtems_message_queue_delete( Queue_id[ 1 ] );
     directive_failed( status, "rtems_message_queue_delete" );
+
+    status = rtems_message_queue_delete( Queue_id[ 2 ] );
+    directive_failed( status, "rtems_message_queue_delete" );
   }
 
   puts( "*** END OF TEST 9 ***" );
diff --git a/testsuites/sptests/sp13/init.c b/testsuites/sptests/sp13/init.c
index a23d369..f8ffd55 100644
--- a/testsuites/sptests/sp13/init.c
+++ b/testsuites/sptests/sp13/init.c
@@ -28,6 +28,17 @@
 
 const char rtems_test_name[] = "SP 13";
 
+static RTEMS_MESSAGE_QUEUE_BUFFER( MESSAGE_SIZE ) Queue_3_buffers[ 100 ];
+
+static const rtems_message_queue_config Queue_3_config = {
+  .name = rtems_build_name( 'Q', '3', ' ', ' ' ),
+  .maximum_pending_messages = RTEMS_ARRAY_SIZE( Queue_3_buffers ),
+  .maximum_message_size = MESSAGE_SIZE,
+  .storage_area = Queue_3_buffers,
+  .storage_size = sizeof( Queue_3_buffers ),
+  .attributes = RTEMS_GLOBAL
+};
+
 rtems_task Init(
   rtems_task_argument argument
 )
@@ -101,14 +112,8 @@ rtems_task Init(
   );
   directive_failed( status, "rtems_message_queue_create of Q2" );
 
-  status = rtems_message_queue_create(
-    Queue_name[ 3 ],
-    100,
-    MESSAGE_SIZE,
-    RTEMS_GLOBAL,
-    &Queue_id[ 3 ]
-  );
-  directive_failed( status, "rtems_message_queue_create of Q3" );
+  status = rtems_message_queue_construct( &Queue_3_config, &Queue_id[ 3 ] );
+  directive_failed( status, "rtems_message_queue_construct of Q3" );
 
   rtems_task_exit();
 }
diff --git a/testsuites/sptests/sp13/system.h b/testsuites/sptests/sp13/system.h
index 7a49596..1abfc96 100644
--- a/testsuites/sptests/sp13/system.h
+++ b/testsuites/sptests/sp13/system.h
@@ -91,7 +91,7 @@ TEST_EXTERN rtems_name Queue_name[ 4 ];      /* array of queue names */
 #define CONFIGURE_MESSAGE_BUFFER_MEMORY \
    /* Q1 */ CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 100, MESSAGE_SIZE ) + \
    /* Q2 */ CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 10, MESSAGE_SIZE ) + \
-   /* Q3 */ CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 100, MESSAGE_SIZE ) + \
+   /* Q3 is statically allocated */ \
    /* Q1 */ CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 100, 20 ) + \
    /* Q1 */ CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 2,  1030 )
 



More information about the vc mailing list