[PATCH v2 8/9] rtems: Add rtems_message_queue_construct()
Sebastian Huber
sebastian.huber at embedded-brains.de
Fri Sep 25 09:51:31 UTC 2020
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/sptests/sp13/init.c | 21 ++-
testsuites/sptests/sp13/system.h | 2 +-
14 files changed, 539 insertions(+), 161 deletions(-)
create mode 100644 cpukit/rtems/src/msgqconstruct.c
create mode 100644 cpukit/score/src/coremsgwkspace.c
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index e2bed4b844..2c35354e66 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 675cd98acc..14083b8cd0 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" {
@@ -36,6 +37,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
*
diff --git a/cpukit/include/rtems/rtems/messageimpl.h b/cpukit/include/rtems/rtems/messageimpl.h
index e317244025..c90ac97da9 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 220c9839a5..51c638bcc3 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 cb84bfb207..0bf5fa52d0 100644
--- a/cpukit/include/rtems/score/coremsgimpl.h
+++ b/cpukit/include/rtems/score/coremsgimpl.h
@@ -68,6 +68,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.
*
@@ -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 af8abebea8..af50dc2754 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 0000000000..61d0472e7c
--- /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 20787f00a6..7469f10509 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 f7caca1ebf..967ce2355a 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 18b49b096c..98032dd3ad 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 0000000000..8441701813
--- /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 2baf8ef01c..21dc239b1b 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/sptests/sp13/init.c b/testsuites/sptests/sp13/init.c
index a23d369001..f8ffd55426 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 7a495963f6..1abfc96b1d 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 )
--
2.26.2
More information about the devel
mailing list