source: rtems/cpukit/posix/src/mqueueopen.c @ 5bc7c37

Last change on this file since 5bc7c37 was 5bc7c37, checked in by Sebastian Huber <sebastian.huber@…>, on 09/23/20 at 08:09:37

score: Improve _CORE_message_queue_Initialize()

Return a status code and differentiate between error conditions.

Update #4007.

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup POSIXAPI
5 *
6 * @brief Creates a new POSIX Message Queue or Opens an Existing Queue
7 */
8
9/*
10 *  NOTE:  The structure of the routines is identical to that of POSIX
11 *         Message_queues to leave the option of having unnamed message
12 *         queues at a future date.  They are currently not part of the
13 *         POSIX standard but unnamed message_queues are.  This is also
14 *         the reason for the apparently unnecessary tracking of
15 *         the process_shared attribute.  [In addition to the fact that
16 *         it would be trivial to add pshared to the mq_attr structure
17 *         and have process private message queues.]
18 *
19 *         This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
20 *         time.
21 *
22 *  COPYRIGHT (c) 1989-2009.
23 *  On-Line Applications Research Corporation (OAR).
24 *
25 *  The license and distribution terms for this file may be
26 *  found in the file LICENSE in this distribution or at
27 *  http://www.rtems.org/license/LICENSE.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <rtems/posix/mqueueimpl.h>
35#include <rtems/score/wkspace.h>
36#include <rtems/sysinit.h>
37
38#include <stdarg.h>
39#include <fcntl.h>
40
41#define MQ_OPEN_FAILED ((mqd_t) -1)
42
43/*
44 *  There is no real basis for the default values.  They will work
45 *  but were not compared against any existing implementation for
46 *  compatibility.  See README.mqueue for an example program we
47 *  think will print out the defaults.  Report anything you find with it.
48 */
49static const struct mq_attr _POSIX_Message_queue_Default_attributes = {
50  .mq_maxmsg = 10,
51  .mq_msgsize = 16
52};
53
54static mqd_t _POSIX_Message_queue_Create(
55  const char           *name_arg,
56  size_t                name_len,
57  int                   oflag,
58  const struct mq_attr *attr
59)
60{
61  POSIX_Message_queue_Control  *the_mq;
62  char                         *name;
63  Status_Control                status;
64
65  /* length of name has already been validated */
66
67  if ( attr->mq_maxmsg <= 0 ){
68    rtems_set_errno_and_return_value( EINVAL, MQ_OPEN_FAILED );
69  }
70
71  if ( attr->mq_msgsize <= 0 ){
72    rtems_set_errno_and_return_value( EINVAL, MQ_OPEN_FAILED );
73  }
74
75  the_mq = _POSIX_Message_queue_Allocate_unprotected();
76  if ( !the_mq ) {
77    rtems_set_errno_and_return_value( ENFILE, MQ_OPEN_FAILED );
78  }
79
80  /*
81   * Make a copy of the user's string for name just in case it was
82   * dynamically constructed.
83   */
84  name = _Workspace_String_duplicate( name_arg, name_len );
85  if ( !name ) {
86    _POSIX_Message_queue_Free( the_mq );
87    rtems_set_errno_and_return_value( ENOMEM, MQ_OPEN_FAILED );
88  }
89
90  the_mq->open_count = 1;
91  the_mq->linked = true;
92  the_mq->oflag = oflag;
93
94  /*
95   *  NOTE: That thread blocking discipline should be based on the
96   *  current scheduling policy.
97   *
98   *  Joel: Cite POSIX or OpenGroup on above statement so we can determine
99   *        if it is a real requirement.
100   */
101  status = _CORE_message_queue_Initialize(
102    &the_mq->Message_queue,
103    CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO,
104    attr->mq_maxmsg,
105    attr->mq_msgsize
106  );
107
108  if ( status != STATUS_SUCCESSFUL ) {
109    _POSIX_Message_queue_Free( the_mq );
110    _Workspace_Free( name );
111    rtems_set_errno_and_return_value( ENOSPC, MQ_OPEN_FAILED );
112  }
113
114  _Objects_Open_string(
115    &_POSIX_Message_queue_Information,
116    &the_mq->Object,
117    name
118  );
119  return the_mq->Object.id;
120}
121
122/*
123 *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
124 */
125mqd_t mq_open(
126  const char *name,
127  int         oflag,
128  ...
129  /* mode_t mode, */
130  /* struct mq_attr  attr */
131)
132{
133  POSIX_Message_queue_Control *the_mq;
134  size_t                       name_len;
135  Objects_Get_by_name_error    error;
136  mqd_t                        status;
137
138  _Objects_Allocator_lock();
139  the_mq = _POSIX_Message_queue_Get_by_name( name, &name_len, &error );
140
141  /*
142   *  If the name to id translation worked, then the message queue exists
143   *  and we can just return a pointer to the id.  Otherwise we may
144   *  need to check to see if this is a "message queue does not exist"
145   *  or some other miscellaneous error on the name.
146   */
147  if ( the_mq == NULL ) {
148    va_list               ap;
149    const struct mq_attr *attr;
150
151    /*
152     * Unless provided a valid name that did not already exist
153     * and we are willing to create then it is an error.
154     */
155
156    if ( error != OBJECTS_GET_BY_NAME_NO_OBJECT || ( oflag & O_CREAT ) == 0 ) {
157      _Objects_Allocator_unlock();
158      rtems_set_errno_and_return_value(
159        _POSIX_Get_by_name_error( error ),
160        MQ_OPEN_FAILED
161      );
162    }
163
164    va_start( ap, oflag );
165    va_arg( ap, mode_t );
166    attr = va_arg( ap, const struct mq_attr * );
167    va_end( ap );
168
169    if ( attr == NULL ) {
170      attr = &_POSIX_Message_queue_Default_attributes;
171    }
172
173    /*
174     *  At this point, the message queue does not exist and everything has been
175     *  checked. We should go ahead and create a message queue.
176     */
177
178    status = _POSIX_Message_queue_Create( name, name_len, oflag, attr );
179  } else {
180
181    /*
182     * Check for existence with creation.
183     */
184
185    if ( ( oflag & ( O_CREAT | O_EXCL ) ) == ( O_CREAT | O_EXCL ) ) {
186      _Objects_Allocator_unlock();
187      rtems_set_errno_and_return_value( EEXIST, MQ_OPEN_FAILED );
188    }
189
190    the_mq->open_count += 1;
191    status = the_mq->Object.id;
192  }
193
194  _Objects_Allocator_unlock();
195  return status;
196}
197
198static void _POSIX_Message_queue_Manager_initialization( void )
199{
200  _Objects_Initialize_information( &_POSIX_Message_queue_Information );
201}
202
203RTEMS_SYSINIT_ITEM(
204  _POSIX_Message_queue_Manager_initialization,
205  RTEMS_SYSINIT_POSIX_MESSAGE_QUEUE,
206  RTEMS_SYSINIT_ORDER_MIDDLE
207);
Note: See TracBrowser for help on using the repository browser.