source: rtems/cpukit/posix/src/mqueueopen.c @ 127c20eb

5
Last change on this file since 127c20eb was c8982e5, checked in by Sebastian Huber <sebastian.huber@…>, on 04/26/16 at 19:20:31

posix: Simplify message queues

The mq_open() function returns a descriptor to a POSIX message queue
object identified by a name. This is similar to sem_open(). In
contrast to the POSIX semaphore the POSIX message queues use a separate
object for the descriptor. This extra object is superfluous, since the
object identifier can be used directly for this purpose, just like for
the semaphores.

Update #2702.
Update #2555.

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