source: rtems/cpukit/posix/src/mqueueopen.c @ 4a4f41e

Last change on this file since 4a4f41e was 4a4f41e, checked in by Sebastian Huber <sebastian.huber@…>, on 09/23/20 at 14:47:58

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.

  • Property mode set to 100644
File size: 5.6 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    _CORE_message_queue_Workspace_allocate,
107    NULL
108  );
109
110  if ( status != STATUS_SUCCESSFUL ) {
111    _POSIX_Message_queue_Free( the_mq );
112    _Workspace_Free( name );
113    rtems_set_errno_and_return_value( ENOSPC, MQ_OPEN_FAILED );
114  }
115
116  _Objects_Open_string(
117    &_POSIX_Message_queue_Information,
118    &the_mq->Object,
119    name
120  );
121  return the_mq->Object.id;
122}
123
124/*
125 *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
126 */
127mqd_t mq_open(
128  const char *name,
129  int         oflag,
130  ...
131  /* mode_t mode, */
132  /* struct mq_attr  attr */
133)
134{
135  POSIX_Message_queue_Control *the_mq;
136  size_t                       name_len;
137  Objects_Get_by_name_error    error;
138  mqd_t                        status;
139
140  _Objects_Allocator_lock();
141  the_mq = _POSIX_Message_queue_Get_by_name( name, &name_len, &error );
142
143  /*
144   *  If the name to id translation worked, then the message queue exists
145   *  and we can just return a pointer to the id.  Otherwise we may
146   *  need to check to see if this is a "message queue does not exist"
147   *  or some other miscellaneous error on the name.
148   */
149  if ( the_mq == NULL ) {
150    va_list               ap;
151    const struct mq_attr *attr;
152
153    /*
154     * Unless provided a valid name that did not already exist
155     * and we are willing to create then it is an error.
156     */
157
158    if ( error != OBJECTS_GET_BY_NAME_NO_OBJECT || ( oflag & O_CREAT ) == 0 ) {
159      _Objects_Allocator_unlock();
160      rtems_set_errno_and_return_value(
161        _POSIX_Get_by_name_error( error ),
162        MQ_OPEN_FAILED
163      );
164    }
165
166    va_start( ap, oflag );
167    va_arg( ap, mode_t );
168    attr = va_arg( ap, const struct mq_attr * );
169    va_end( ap );
170
171    if ( attr == NULL ) {
172      attr = &_POSIX_Message_queue_Default_attributes;
173    }
174
175    /*
176     *  At this point, the message queue does not exist and everything has been
177     *  checked. We should go ahead and create a message queue.
178     */
179
180    status = _POSIX_Message_queue_Create( name, name_len, oflag, attr );
181  } else {
182
183    /*
184     * Check for existence with creation.
185     */
186
187    if ( ( oflag & ( O_CREAT | O_EXCL ) ) == ( O_CREAT | O_EXCL ) ) {
188      _Objects_Allocator_unlock();
189      rtems_set_errno_and_return_value( EEXIST, MQ_OPEN_FAILED );
190    }
191
192    the_mq->open_count += 1;
193    status = the_mq->Object.id;
194  }
195
196  _Objects_Allocator_unlock();
197  return status;
198}
199
200static void _POSIX_Message_queue_Manager_initialization( void )
201{
202  _Objects_Initialize_information( &_POSIX_Message_queue_Information );
203}
204
205RTEMS_SYSINIT_ITEM(
206  _POSIX_Message_queue_Manager_initialization,
207  RTEMS_SYSINIT_POSIX_MESSAGE_QUEUE,
208  RTEMS_SYSINIT_ORDER_MIDDLE
209);
Note: See TracBrowser for help on using the repository browser.