source: rtems/cpukit/posix/src/mqueueopen.c @ 21275b58

Last change on this file since 21275b58 was 21275b58, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 22, 2018 at 6:14:51 PM

score: Static Objects_Information initialization

Statically allocate the objects information together with the initial
set of objects either via <rtems/confdefs.h>. Provide default object
informations with zero objects via librtemscpu.a. This greatly
simplifies the workspace size estimate. RTEMS applications which do not
use the unlimited objects option are easier to debug since all objects
reside now in statically allocated objects of the right types.

Close #3621.

  • Property mode set to 100644
File size: 5.4 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#include <rtems/sysinit.h>
36
37#include <stdarg.h>
38#include <fcntl.h>
39
40#define MQ_OPEN_FAILED ((mqd_t) -1)
41
42/*
43 *  There is no real basis for the default values.  They will work
44 *  but were not compared against any existing implementation for
45 *  compatibility.  See README.mqueue for an example program we
46 *  think will print out the defaults.  Report anything you find with it.
47 */
48static const struct mq_attr _POSIX_Message_queue_Default_attributes = {
49  .mq_maxmsg = 10,
50  .mq_msgsize = 16
51};
52
53static mqd_t _POSIX_Message_queue_Create(
54  const char           *name_arg,
55  size_t                name_len,
56  int                   oflag,
57  const struct mq_attr *attr
58)
59{
60  POSIX_Message_queue_Control  *the_mq;
61  char                         *name;
62
63  /* length of name has already been validated */
64
65  if ( attr->mq_maxmsg <= 0 ){
66    rtems_set_errno_and_return_value( EINVAL, MQ_OPEN_FAILED );
67  }
68
69  if ( attr->mq_msgsize <= 0 ){
70    rtems_set_errno_and_return_value( EINVAL, MQ_OPEN_FAILED );
71  }
72
73  the_mq = _POSIX_Message_queue_Allocate_unprotected();
74  if ( !the_mq ) {
75    rtems_set_errno_and_return_value( ENFILE, MQ_OPEN_FAILED );
76  }
77
78  /*
79   * Make a copy of the user's string for name just in case it was
80   * dynamically constructed.
81   */
82  name = _Workspace_String_duplicate( name_arg, name_len );
83  if ( !name ) {
84    _POSIX_Message_queue_Free( the_mq );
85    rtems_set_errno_and_return_value( ENOMEM, MQ_OPEN_FAILED );
86  }
87
88  the_mq->open_count = 1;
89  the_mq->linked = true;
90  the_mq->oflag = oflag;
91
92  /*
93   *  NOTE: That thread blocking discipline should be based on the
94   *  current scheduling policy.
95   *
96   *  Joel: Cite POSIX or OpenGroup on above statement so we can determine
97   *        if it is a real requirement.
98   */
99  if (
100    !_CORE_message_queue_Initialize(
101      &the_mq->Message_queue,
102      CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO,
103      attr->mq_maxmsg,
104      attr->mq_msgsize
105    )
106  ) {
107    _POSIX_Message_queue_Free( the_mq );
108    _Workspace_Free( name );
109    rtems_set_errno_and_return_value( ENOSPC, MQ_OPEN_FAILED );
110  }
111
112  _Objects_Open_string(
113    &_POSIX_Message_queue_Information,
114    &the_mq->Object,
115    name
116  );
117  return the_mq->Object.id;
118}
119
120/*
121 *  15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
122 */
123mqd_t mq_open(
124  const char *name,
125  int         oflag,
126  ...
127  /* mode_t mode, */
128  /* struct mq_attr  attr */
129)
130{
131  POSIX_Message_queue_Control *the_mq;
132  size_t                       name_len;
133  Objects_Get_by_name_error    error;
134  mqd_t                        status;
135
136  _Objects_Allocator_lock();
137  the_mq = _POSIX_Message_queue_Get_by_name( name, &name_len, &error );
138
139  /*
140   *  If the name to id translation worked, then the message queue exists
141   *  and we can just return a pointer to the id.  Otherwise we may
142   *  need to check to see if this is a "message queue does not exist"
143   *  or some other miscellaneous error on the name.
144   */
145  if ( the_mq == NULL ) {
146    va_list               ap;
147    const struct mq_attr *attr;
148
149    /*
150     * Unless provided a valid name that did not already exist
151     * and we are willing to create then it is an error.
152     */
153
154    if ( error != OBJECTS_GET_BY_NAME_NO_OBJECT || ( oflag & O_CREAT ) == 0 ) {
155      _Objects_Allocator_unlock();
156      rtems_set_errno_and_return_value(
157        _POSIX_Get_by_name_error( error ),
158        MQ_OPEN_FAILED
159      );
160    }
161
162    va_start( ap, oflag );
163    va_arg( ap, mode_t );
164    attr = va_arg( ap, const struct mq_attr * );
165    va_end( ap );
166
167    if ( attr == NULL ) {
168      attr = &_POSIX_Message_queue_Default_attributes;
169    }
170
171    /*
172     *  At this point, the message queue does not exist and everything has been
173     *  checked. We should go ahead and create a message queue.
174     */
175
176    status = _POSIX_Message_queue_Create( name, name_len, oflag, attr );
177  } else {
178
179    /*
180     * Check for existence with creation.
181     */
182
183    if ( ( oflag & ( O_CREAT | O_EXCL ) ) == ( O_CREAT | O_EXCL ) ) {
184      _Objects_Allocator_unlock();
185      rtems_set_errno_and_return_value( EEXIST, MQ_OPEN_FAILED );
186    }
187
188    the_mq->open_count += 1;
189    status = the_mq->Object.id;
190  }
191
192  _Objects_Allocator_unlock();
193  return status;
194}
195
196static void _POSIX_Message_queue_Manager_initialization( void )
197{
198  _Objects_Initialize_information( &_POSIX_Message_queue_Information );
199}
200
201RTEMS_SYSINIT_ITEM(
202  _POSIX_Message_queue_Manager_initialization,
203  RTEMS_SYSINIT_POSIX_MESSAGE_QUEUE,
204  RTEMS_SYSINIT_ORDER_MIDDLE
205);
Note: See TracBrowser for help on using the repository browser.