Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:21

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup POSIXAPI
0007  *
0008  * @brief Creates a new POSIX Message Queue or Opens an Existing Queue 
0009  */
0010 
0011 /*
0012  *  NOTE:  The structure of the routines is identical to that of POSIX
0013  *         Message_queues to leave the option of having unnamed message
0014  *         queues at a future date.  They are currently not part of the
0015  *         POSIX standard but unnamed message_queues are.  This is also
0016  *         the reason for the apparently unnecessary tracking of
0017  *         the process_shared attribute.  [In addition to the fact that
0018  *         it would be trivial to add pshared to the mq_attr structure
0019  *         and have process private message queues.]
0020  *
0021  *         This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
0022  *         time.
0023  *
0024  *  COPYRIGHT (c) 1989-2009.
0025  *  On-Line Applications Research Corporation (OAR).
0026  *
0027  * Redistribution and use in source and binary forms, with or without
0028  * modification, are permitted provided that the following conditions
0029  * are met:
0030  * 1. Redistributions of source code must retain the above copyright
0031  *    notice, this list of conditions and the following disclaimer.
0032  * 2. Redistributions in binary form must reproduce the above copyright
0033  *    notice, this list of conditions and the following disclaimer in the
0034  *    documentation and/or other materials provided with the distribution.
0035  *
0036  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0037  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0038  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0039  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0040  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0041  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0042  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0043  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0044  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0045  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0046  * POSSIBILITY OF SUCH DAMAGE.
0047  */
0048 
0049 #ifdef HAVE_CONFIG_H
0050 #include "config.h"
0051 #endif
0052 
0053 #include <rtems/posix/mqueueimpl.h>
0054 #include <rtems/score/wkspace.h>
0055 #include <rtems/sysinit.h>
0056 
0057 #include <stdarg.h>
0058 #include <fcntl.h>
0059 
0060 #define MQ_OPEN_FAILED ((mqd_t) -1)
0061 
0062 /*
0063  *  There is no real basis for the default values.  They will work
0064  *  but were not compared against any existing implementation for
0065  *  compatibility.  See README.mqueue for an example program we
0066  *  think will print out the defaults.  Report anything you find with it.
0067  */
0068 static const struct mq_attr _POSIX_Message_queue_Default_attributes = {
0069   .mq_maxmsg = 10,
0070   .mq_msgsize = 16
0071 };
0072 
0073 static mqd_t _POSIX_Message_queue_Create(
0074   const char           *name_arg,
0075   size_t                name_len,
0076   int                   oflag,
0077   const struct mq_attr *attr
0078 )
0079 {
0080   POSIX_Message_queue_Control  *the_mq;
0081   char                         *name;
0082   Status_Control                status;
0083 
0084   /* length of name has already been validated */
0085 
0086   if ( attr->mq_maxmsg <= 0 ){
0087     rtems_set_errno_and_return_value( EINVAL, MQ_OPEN_FAILED );
0088   }
0089 
0090   if ( attr->mq_msgsize <= 0 ){
0091     rtems_set_errno_and_return_value( EINVAL, MQ_OPEN_FAILED );
0092   }
0093 
0094   the_mq = _POSIX_Message_queue_Allocate_unprotected();
0095   if ( !the_mq ) {
0096     rtems_set_errno_and_return_value( ENFILE, MQ_OPEN_FAILED );
0097   }
0098 
0099   /*
0100    * Make a copy of the user's string for name just in case it was
0101    * dynamically constructed.
0102    */
0103   name = _Workspace_String_duplicate( name_arg, name_len );
0104   if ( !name ) {
0105     _POSIX_Message_queue_Free( the_mq );
0106     rtems_set_errno_and_return_value( ENOMEM, MQ_OPEN_FAILED );
0107   }
0108 
0109   the_mq->open_count = 1;
0110   the_mq->linked = true;
0111   the_mq->oflag = oflag;
0112 
0113   /*
0114    *  NOTE: That thread blocking discipline should be based on the
0115    *  current scheduling policy.
0116    *
0117    *  Joel: Cite POSIX or OpenGroup on above statement so we can determine
0118    *        if it is a real requirement.
0119    */
0120   status = _CORE_message_queue_Initialize(
0121     &the_mq->Message_queue,
0122     CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO,
0123     attr->mq_maxmsg,
0124     attr->mq_msgsize,
0125     _CORE_message_queue_Workspace_allocate,
0126     NULL
0127   );
0128 
0129   if ( status != STATUS_SUCCESSFUL ) {
0130     _POSIX_Message_queue_Free( the_mq );
0131     _Workspace_Free( name );
0132     rtems_set_errno_and_return_value( ENOSPC, MQ_OPEN_FAILED );
0133   }
0134 
0135   _Objects_Open_string(
0136     &_POSIX_Message_queue_Information,
0137     &the_mq->Object,
0138     name
0139   );
0140   return the_mq->Object.id;
0141 }
0142 
0143 /*
0144  *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
0145  */
0146 mqd_t mq_open(
0147   const char *name,
0148   int         oflag,
0149   ...
0150   /* mode_t mode, */
0151   /* struct mq_attr  attr */
0152 )
0153 {
0154   POSIX_Message_queue_Control *the_mq;
0155   size_t                       name_len;
0156   Objects_Get_by_name_error    error;
0157   mqd_t                        status;
0158 
0159   _Objects_Allocator_lock();
0160   the_mq = _POSIX_Message_queue_Get_by_name( name, &name_len, &error );
0161 
0162   /*
0163    *  If the name to id translation worked, then the message queue exists
0164    *  and we can just return a pointer to the id.  Otherwise we may
0165    *  need to check to see if this is a "message queue does not exist"
0166    *  or some other miscellaneous error on the name.
0167    */
0168   if ( the_mq == NULL ) {
0169     va_list               ap;
0170     const struct mq_attr *attr;
0171 
0172     /*
0173      * Unless provided a valid name that did not already exist
0174      * and we are willing to create then it is an error.
0175      */
0176 
0177     if ( error != OBJECTS_GET_BY_NAME_NO_OBJECT || ( oflag & O_CREAT ) == 0 ) {
0178       _Objects_Allocator_unlock();
0179       rtems_set_errno_and_return_value(
0180         _POSIX_Get_by_name_error( error ),
0181         MQ_OPEN_FAILED
0182       );
0183     }
0184 
0185     va_start( ap, oflag );
0186     va_arg( ap, mode_t );
0187     attr = va_arg( ap, const struct mq_attr * );
0188     va_end( ap );
0189 
0190     if ( attr == NULL ) {
0191       attr = &_POSIX_Message_queue_Default_attributes;
0192     }
0193 
0194     /*
0195      *  At this point, the message queue does not exist and everything has been
0196      *  checked. We should go ahead and create a message queue.
0197      */
0198 
0199     status = _POSIX_Message_queue_Create( name, name_len, oflag, attr );
0200   } else {
0201 
0202     /*
0203      * Check for existence with creation.
0204      */
0205 
0206     if ( ( oflag & ( O_CREAT | O_EXCL ) ) == ( O_CREAT | O_EXCL ) ) {
0207       _Objects_Allocator_unlock();
0208       rtems_set_errno_and_return_value( EEXIST, MQ_OPEN_FAILED );
0209     }
0210 
0211     the_mq->open_count += 1;
0212     status = the_mq->Object.id;
0213   }
0214 
0215   _Objects_Allocator_unlock();
0216   return status;
0217 }
0218 
0219 static void _POSIX_Message_queue_Manager_initialization( void )
0220 {
0221   _Objects_Initialize_information( &_POSIX_Message_queue_Information );
0222 }
0223 
0224 RTEMS_SYSINIT_ITEM(
0225   _POSIX_Message_queue_Manager_initialization,
0226   RTEMS_SYSINIT_POSIX_MESSAGE_QUEUE,
0227   RTEMS_SYSINIT_ORDER_MIDDLE
0228 );