source: rtems/cpukit/posix/src/semopen.c @ c090db7

Last change on this file since c090db7 was c090db7, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 12, 2017 at 6:09:16 AM

posix: Implement self-contained POSIX semaphores

For semaphore object pointer and object validation see
POSIX_SEMAPHORE_VALIDATE_OBJECT().

Destruction or close of a busy semaphore returns an error status. The
object is not flushed.

POSIX semaphores are now available in all configurations and no longer
depend on --enable-posix.

Update #2514.
Update #3116.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief Function Creates New POSIX semaphore or Opens an existing Semaphore
5 * @ingroup POSIXAPI
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2007.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/posix/semaphoreimpl.h>
22#include <rtems/score/wkspace.h>
23
24#include <stdarg.h>
25#include <fcntl.h>
26#include <limits.h>
27
28static sem_t *_POSIX_Semaphore_Create_support(
29  const char   *name_arg,
30  size_t        name_len,
31  unsigned int  value
32)
33{
34  POSIX_Semaphore_Control *the_semaphore;
35  char                    *name;
36
37  if ( value > SEM_VALUE_MAX ) {
38    rtems_set_errno_and_return_value( EINVAL, SEM_FAILED );
39  }
40
41  /*
42   * Make a copy of the user's string for name just in case it was
43   * dynamically constructed.
44   */
45  name = _Workspace_String_duplicate( name_arg, name_len );
46  if ( name == NULL ) {
47    rtems_set_errno_and_return_value( ENOMEM, SEM_FAILED );
48  }
49
50  the_semaphore = _POSIX_Semaphore_Allocate_unprotected();
51  if ( the_semaphore == NULL ) {
52    _Workspace_Free( name );
53    rtems_set_errno_and_return_value( ENOSPC, SEM_FAILED );
54  }
55
56  the_semaphore->open_count = 1;
57  the_semaphore->linked = true;
58
59  /*
60   *  POSIX does not appear to specify what the discipline for
61   *  blocking tasks on this semaphore should be.  It could somehow
62   *  be derived from the current scheduling policy.  One
63   *  thing is certain, no matter what we decide, it won't be
64   *  the same as  all other POSIX implementations. :)
65   */
66  _POSIX_Semaphore_Initialize( &the_semaphore->Semaphore, name, value );
67
68  /*
69   *  Make the semaphore available for use.
70   */
71  _Objects_Open_string(
72    &_POSIX_Semaphore_Information,
73    &the_semaphore->Object,
74    name
75  );
76
77  return &the_semaphore->Semaphore;
78}
79
80/*
81 *  sem_open
82 *
83 *  Opens a named semaphore.  Used in conjunction with the sem_close
84 *  and sem_unlink commands.
85 *
86 *  11.2.3 Initialize/Open a Named Semaphore, P1003.1b-1993, p.221
87 *
88 *  NOTE: When oflag is O_CREAT, then optional third and fourth
89 *        parameters must be present.
90 */
91sem_t *sem_open(
92  const char *name,
93  int         oflag,
94  ...
95  /* mode_t mode, */
96  /* unsigned int value */
97)
98{
99  /*
100   * mode is set but never used. GCC gives a warning for this
101   * and we need to tell GCC not to complain. But we have to
102   * have it because we have to work through the variable
103   * arguments to get to attr.
104   */
105  mode_t                     mode RTEMS_UNUSED;
106
107  va_list                    arg;
108  unsigned int               value = 0;
109  POSIX_Semaphore_Control   *the_semaphore;
110  size_t                     name_len;
111  Objects_Get_by_name_error  error;
112  sem_t                     *sem;
113
114  if ( oflag & O_CREAT ) {
115    va_start(arg, oflag);
116    mode = va_arg( arg, mode_t );
117    value = va_arg( arg, unsigned int );
118    va_end(arg);
119  }
120
121  _Objects_Allocator_lock();
122  the_semaphore = _POSIX_Semaphore_Get_by_name( name, &name_len, &error );
123
124  /*
125   *  If the name to id translation worked, then the semaphore exists
126   *  and we can just return a pointer to the id.  Otherwise we may
127   *  need to check to see if this is a "semaphore does not exist"
128   *  or some other miscellaneous error on the name.
129   */
130
131  if ( the_semaphore == NULL ) {
132
133    /*
134     * Unless provided a valid name that did not already exist
135     * and we are willing to create then it is an error.
136     */
137
138    if ( !( error == OBJECTS_GET_BY_NAME_NO_OBJECT && (oflag & O_CREAT) ) ) {
139      _Objects_Allocator_unlock();
140      rtems_set_errno_and_return_value(
141        _POSIX_Get_by_name_error( error ),
142        SEM_FAILED
143      );
144    }
145  } else {
146
147    /*
148     * Check for existence with creation.
149     */
150
151    if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
152      _Objects_Allocator_unlock();
153      rtems_set_errno_and_return_value( EEXIST, SEM_FAILED );
154    }
155
156    the_semaphore->open_count += 1;
157    _Objects_Allocator_unlock();
158    return &the_semaphore->Semaphore;
159  }
160
161  /*
162   *  At this point, the semaphore does not exist and everything has been
163   *  checked. We should go ahead and create a semaphore.
164   */
165
166  sem = _POSIX_Semaphore_Create_support(
167    name,
168    name_len,
169    value
170  );
171
172  _Objects_Allocator_unlock();
173  return sem;
174}
Note: See TracBrowser for help on using the repository browser.