mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-26 14:18:20 +00:00
rtems: Add rtems_message_queue_construct()
In contrast to message queues created by rtems_message_queue_create(), the message queues constructed by this directive use a user-provided message buffer storage area. Add RTEMS_MESSAGE_QUEUE_BUFFER() to define a message buffer type for message buffer storage areas. Update #4007.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
189
cpukit/rtems/src/msgqconstruct.c
Normal file
189
cpukit/rtems/src/msgqconstruct.c
Normal file
@@ -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
|
||||
);
|
||||
@@ -1,17 +1,37 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
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
|
||||
);
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
53
cpukit/score/src/coremsgwkspace.c
Normal file
53
cpukit/score/src/coremsgwkspace.c
Normal file
@@ -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 );
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -26,6 +26,23 @@
|
||||
#define CONFIGURE_INIT
|
||||
#include "system.h"
|
||||
|
||||
#if CONFIGURE_MP_NODE_NUMBER == 1
|
||||
|
||||
#define MESSAGE_SIZE 1
|
||||
|
||||
static RTEMS_MESSAGE_QUEUE_BUFFER( MESSAGE_SIZE ) buffers[ 1 ];
|
||||
|
||||
static const rtems_message_queue_config config = {
|
||||
.name = rtems_build_name( 'M', 'S', 'G', '2' ),
|
||||
.maximum_pending_messages = RTEMS_ARRAY_SIZE( buffers ),
|
||||
.maximum_message_size = MESSAGE_SIZE,
|
||||
.storage_area = buffers,
|
||||
.storage_size = sizeof( buffers ),
|
||||
.attributes = RTEMS_GLOBAL
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
rtems_task Init(
|
||||
rtems_task_argument argument
|
||||
)
|
||||
@@ -40,10 +57,17 @@ rtems_task Init(
|
||||
Task_name[ 1 ] = rtems_build_name( '1', '1', '1', ' ' );
|
||||
Task_name[ 2 ] = rtems_build_name( '2', '2', '2', ' ' );
|
||||
|
||||
Queue_name[ 1 ] = rtems_build_name( 'M', 'S', 'G', ' ' );
|
||||
Queue_name[ 1 ] = rtems_build_name( 'M', 'S', 'G', '1' );
|
||||
Queue_name[ 2 ] = rtems_build_name( 'M', 'S', 'G', '2' );
|
||||
|
||||
if ( rtems_object_get_local_node() == 1 ) {
|
||||
puts( "Creating Message Queue (Global)" );
|
||||
|
||||
#if CONFIGURE_MP_NODE_NUMBER == 1
|
||||
status = rtems_message_queue_construct( &config, &Queue_id[ 2 ] );
|
||||
directive_failed( status, "rtems_message_queue_construct" );
|
||||
#endif
|
||||
|
||||
status = rtems_message_queue_create(
|
||||
Queue_name[ 1 ],
|
||||
3,
|
||||
|
||||
@@ -34,11 +34,14 @@ void Send_messages( void );
|
||||
#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
#define CONFIGURE_MAXIMUM_TIMERS 1
|
||||
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 1
|
||||
#define CONFIGURE_MESSAGE_BUFFER_MEMORY \
|
||||
CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 3, 16 )
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
#define CONFIGURE_MAXIMUM_TIMER 1
|
||||
|
||||
#if CONFIGURE_MP_NODE_NUMBER == 1
|
||||
#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 2
|
||||
#define CONFIGURE_MESSAGE_BUFFER_MEMORY \
|
||||
CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE( 3, 16 )
|
||||
#endif
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
@@ -49,8 +52,8 @@ void Send_messages( void );
|
||||
TEST_EXTERN rtems_id Task_id[ 4 ]; /* array of task ids */
|
||||
TEST_EXTERN rtems_name Task_name[ 4 ]; /* array of task names */
|
||||
|
||||
TEST_EXTERN rtems_id Queue_id[ 2 ]; /* array of message queue ids */
|
||||
TEST_EXTERN rtems_name Queue_name[ 2 ]; /* array of message queue names */
|
||||
TEST_EXTERN rtems_id Queue_id[ 3 ]; /* array of message queue ids */
|
||||
TEST_EXTERN rtems_name Queue_name[ 3 ]; /* array of message queue names */
|
||||
|
||||
extern char buffer1[16];
|
||||
extern char buffer2[16];
|
||||
|
||||
@@ -49,7 +49,20 @@ rtems_task Test_task(
|
||||
);
|
||||
} while ( !rtems_is_status_successful( status ) );
|
||||
|
||||
status = rtems_message_queue_ident(
|
||||
Queue_name[ 2 ],
|
||||
RTEMS_SEARCH_ALL_NODES,
|
||||
&Queue_id[ 2 ]
|
||||
);
|
||||
directive_failed( status, "rtems_message_queue_ident" );
|
||||
|
||||
if ( rtems_object_get_local_node() == 2 ) {
|
||||
status = rtems_message_queue_delete( Queue_id[ 2 ] );
|
||||
fatal_directive_status(
|
||||
status,
|
||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT,
|
||||
"rtems_message_queue_delete"
|
||||
);
|
||||
status = rtems_message_queue_delete( Queue_id[ 1 ] );
|
||||
fatal_directive_status(
|
||||
status,
|
||||
@@ -103,6 +116,9 @@ rtems_task Test_task(
|
||||
puts( "Deleting Message queue" );
|
||||
status = rtems_message_queue_delete( Queue_id[ 1 ] );
|
||||
directive_failed( status, "rtems_message_queue_delete" );
|
||||
|
||||
status = rtems_message_queue_delete( Queue_id[ 2 ] );
|
||||
directive_failed( status, "rtems_message_queue_delete" );
|
||||
}
|
||||
|
||||
puts( "*** END OF TEST 9 ***" );
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
|
||||
|
||||
Reference in New Issue
Block a user