Index: cpukit/Makefile.am
===================================================================
--- cpukit/Makefile.am	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/Makefile.am	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -707,4 +707,5 @@
 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
@@ -840,4 +841,5 @@
 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
Index: cpukit/include/rtems/rtems/message.h
===================================================================
--- cpukit/include/rtems/rtems/message.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/include/rtems/rtems/message.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -22,4 +22,5 @@
 #include <rtems/rtems/status.h>
 #include <rtems/rtems/types.h>
+#include <rtems/score/coremsgbuffer.h>
 
 #ifdef __cplusplus
@@ -36,4 +37,134 @@
  */
 /**@{*/
+
+/**
+ * @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
+);
 
 /**
Index: cpukit/include/rtems/rtems/messageimpl.h
===================================================================
--- cpukit/include/rtems/rtems/messageimpl.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/include/rtems/rtems/messageimpl.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -102,4 +102,21 @@
 }
 
+/**
+ * @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
+);
+
 /**@}*/
 
Index: cpukit/include/rtems/score/coremsg.h
===================================================================
--- cpukit/include/rtems/score/coremsg.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/include/rtems/score/coremsg.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -125,4 +125,14 @@
    */
   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
Index: cpukit/include/rtems/score/coremsgimpl.h
===================================================================
--- cpukit/include/rtems/score/coremsgimpl.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/include/rtems/score/coremsgimpl.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -70,4 +70,52 @@
 
 /**
+ * @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.
  *
@@ -82,4 +130,9 @@
  *   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.
  *
@@ -87,12 +140,14 @@
  *   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
 );
 
Index: cpukit/posix/src/mqueueopen.c
===================================================================
--- cpukit/posix/src/mqueueopen.c	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/posix/src/mqueueopen.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -103,5 +103,7 @@
     CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO,
     attr->mq_maxmsg,
-    attr->mq_msgsize
+    attr->mq_msgsize,
+    _CORE_message_queue_Workspace_allocate,
+    NULL
   );
 
Index: cpukit/rtems/src/msgqconstruct.c
===================================================================
--- cpukit/rtems/src/msgqconstruct.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
+++ cpukit/rtems/src/msgqconstruct.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -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
+);
Index: cpukit/rtems/src/msgqcreate.c
===================================================================
--- cpukit/rtems/src/msgqcreate.c	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/rtems/src/msgqcreate.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -1,16 +1,36 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
 /**
- *  @file
+ * @file
  *
- *  @brief RTEMS Create Message Queue
- *  @ingroup ClassicMessageQueue
+ * @ingroup ClassicMessageQueueImpl
+ *
+ * @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)
  *
- *  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.
+ * 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.
  */
 
@@ -20,15 +40,7 @@
 
 #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(
@@ -40,122 +52,16 @@
 )
 {
-  Message_queue_Control          *the_message_queue;
-  CORE_message_queue_Disciplines  discipline;
-  Status_Control                  status;
-#if defined(RTEMS_MULTIPROCESSING)
-  bool                            is_global;
-#endif
+  rtems_message_queue_config config;
 
-  if ( !rtems_is_name_valid( name ) )
-    return RTEMS_INVALID_NAME;
+  memset( &config, 0, sizeof( config ) );
+  config.name = name;
+  config.maximum_pending_messages = count;
+  config.maximum_message_size = max_message_size;
+  config.attributes = attribute_set;
 
-  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
+  return _Message_queue_Create(
+    &config,
+    id,
+    _CORE_message_queue_Workspace_allocate
   );
-
-  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
-  );
-
-  *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
-);
Index: cpukit/score/src/coremsg.c
===================================================================
--- cpukit/score/src/coremsg.c	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/score/src/coremsg.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -21,5 +21,4 @@
 #include <rtems/score/coremsgimpl.h>
 #include <rtems/score/assert.h>
-#include <rtems/score/wkspace.h>
 
 #define MESSAGE_SIZE_LIMIT \
@@ -33,8 +32,10 @@
 
 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
 )
 {
@@ -57,6 +58,8 @@
   }
 
-  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
   );
 
Index: cpukit/score/src/coremsgclose.c
===================================================================
--- cpukit/score/src/coremsgclose.c	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ cpukit/score/src/coremsgclose.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -20,5 +20,4 @@
 
 #include <rtems/score/coremsgimpl.h>
-#include <rtems/score/wkspace.h>
 
 static Thread_Control *_CORE_message_queue_Was_deleted(
@@ -51,5 +50,9 @@
   );
 
-  (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 );
Index: cpukit/score/src/coremsgwkspace.c
===================================================================
--- cpukit/score/src/coremsgwkspace.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
+++ cpukit/score/src/coremsgwkspace.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -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 );
+}
Index: spec/build/cpukit/librtemscpu.yml
===================================================================
--- spec/build/cpukit/librtemscpu.yml	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ spec/build/cpukit/librtemscpu.yml	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -1199,4 +1199,5 @@
 - 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
@@ -1377,4 +1378,5 @@
 - 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
Index: testsuites/mptests/mp09/initimpl.h
===================================================================
--- testsuites/mptests/mp09/initimpl.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ testsuites/mptests/mp09/initimpl.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -27,4 +27,21 @@
 #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
@@ -41,8 +58,15 @@
   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 ],
Index: testsuites/mptests/mp09/system.h
===================================================================
--- testsuites/mptests/mp09/system.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ testsuites/mptests/mp09/system.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -35,9 +35,12 @@
 #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
@@ -50,6 +53,6 @@
 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];
Index: testsuites/mptests/mp09/task1.c
===================================================================
--- testsuites/mptests/mp09/task1.c	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ testsuites/mptests/mp09/task1.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -50,5 +50,18 @@
   } 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(
@@ -104,4 +117,7 @@
     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" );
   }
 
Index: testsuites/sptests/sp13/init.c
===================================================================
--- testsuites/sptests/sp13/init.c	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ testsuites/sptests/sp13/init.c	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -28,4 +28,15 @@
 
 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(
@@ -102,12 +113,6 @@
   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();
Index: testsuites/sptests/sp13/system.h
===================================================================
--- testsuites/sptests/sp13/system.h	(revision 24ea1cebeb5e64ba2371c8e740ebe3c81d565ca2)
+++ testsuites/sptests/sp13/system.h	(revision 4a4f41ed642cd5d9f4056b12d86bbf80e8da983a)
@@ -92,5 +92,5 @@
    /* 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 )
