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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel