source: rtems/cpukit/rtems/src/semcreate.c @ cfe8f7a

5
Last change on this file since cfe8f7a was cfe8f7a, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/20 at 14:14:06

doxygen: Switch @brief and @ingroup

This order change fixes the Latex documentation build via Doxygen.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ClassicSem Semaphores
5 *
6 * @brief rtems_semaphore_create
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2014.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <rtems/rtems/semimpl.h>
23#include <rtems/rtems/attrimpl.h>
24#include <rtems/rtems/statusimpl.h>
25#include <rtems/rtems/support.h>
26#include <rtems/rtems/tasksimpl.h>
27#include <rtems/score/schedulerimpl.h>
28#include <rtems/score/sysstate.h>
29#include <rtems/sysinit.h>
30
31#define SEMAPHORE_KIND_MASK ( RTEMS_SEMAPHORE_CLASS | RTEMS_INHERIT_PRIORITY \
32  | RTEMS_PRIORITY_CEILING | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
33
34rtems_status_code rtems_semaphore_create(
35  rtems_name           name,
36  uint32_t             count,
37  rtems_attribute      attribute_set,
38  rtems_task_priority  priority_ceiling,
39  rtems_id            *id
40)
41{
42  Semaphore_Control       *the_semaphore;
43  Thread_Control          *executing;
44  Status_Control           status;
45  rtems_attribute          maybe_global;
46  rtems_attribute          mutex_with_protocol;
47  Semaphore_Variant        variant;
48  const Scheduler_Control *scheduler;
49  bool                     valid;
50  Priority_Control         priority;
51  uintptr_t                flags;
52
53  if ( !rtems_is_name_valid( name ) )
54    return RTEMS_INVALID_NAME;
55
56  if ( !id )
57    return RTEMS_INVALID_ADDRESS;
58
59#if defined(RTEMS_MULTIPROCESSING)
60  if (
61    _Attributes_Is_global( attribute_set )
62      && !_System_state_Is_multiprocessing
63  ) {
64    return RTEMS_MP_NOT_CONFIGURED;
65  }
66#endif
67
68  /* Attribute subset defining a potentially global semaphore variant */
69  maybe_global = attribute_set & SEMAPHORE_KIND_MASK;
70
71  /* Attribute subset defining a mutex variant with a locking protocol */
72  mutex_with_protocol =
73    attribute_set & ( SEMAPHORE_KIND_MASK | RTEMS_GLOBAL | RTEMS_PRIORITY );
74
75  if ( maybe_global == RTEMS_COUNTING_SEMAPHORE ) {
76    variant = SEMAPHORE_VARIANT_COUNTING;
77  } else if ( count > 1 ) {
78    /*
79     * The remaining variants are all binary semphores, thus reject an invalid
80     * count value.
81     */
82    return RTEMS_INVALID_NUMBER;
83  } else if ( maybe_global == RTEMS_SIMPLE_BINARY_SEMAPHORE ) {
84    variant = SEMAPHORE_VARIANT_SIMPLE_BINARY;
85  } else if ( maybe_global == RTEMS_BINARY_SEMAPHORE ) {
86    variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
87  } else if (
88    mutex_with_protocol
89      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY )
90  ) {
91    variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
92  } else if (
93    mutex_with_protocol
94      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING )
95  ) {
96    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
97  } else if (
98    mutex_with_protocol
99      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
100  ) {
101#if defined(RTEMS_SMP)
102    variant = SEMAPHORE_VARIANT_MRSP;
103#else
104    /*
105     * On uni-processor configurations the Multiprocessor Resource Sharing
106     * Protocol is equivalent to the Priority Ceiling Protocol.
107     */
108    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
109#endif
110  } else {
111    return RTEMS_NOT_DEFINED;
112  }
113
114  the_semaphore = _Semaphore_Allocate();
115
116  if ( !the_semaphore ) {
117    _Objects_Allocator_unlock();
118    return RTEMS_TOO_MANY;
119  }
120
121  flags = _Semaphore_Set_variant( 0, variant );
122
123#if defined(RTEMS_MULTIPROCESSING)
124  if ( _Attributes_Is_global( attribute_set ) ) {
125    bool ok;
126
127    ok = _Objects_MP_Allocate_and_open(
128      &_Semaphore_Information,
129      name,
130      the_semaphore->Object.id,
131      false
132    );
133
134    if ( !ok ) {
135      _Semaphore_Free( the_semaphore );
136      _Objects_Allocator_unlock();
137      return RTEMS_TOO_MANY;
138    }
139
140    flags = _Semaphore_Make_global( flags );
141  }
142#endif
143
144  if ( _Attributes_Is_priority( attribute_set ) ) {
145    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_PRIORITY );
146  } else {
147    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_FIFO );
148  }
149
150  _Semaphore_Set_flags( the_semaphore, flags );
151  executing = _Thread_Get_executing();
152
153  switch ( variant ) {
154    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
155    case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
156      _CORE_recursive_mutex_Initialize(
157        &the_semaphore->Core_control.Mutex.Recursive
158      );
159
160      if ( count == 0 ) {
161        _CORE_mutex_Set_owner(
162          &the_semaphore->Core_control.Mutex.Recursive.Mutex,
163          executing
164        );
165        _Thread_Resource_count_increment( executing );
166      }
167
168      status = STATUS_SUCCESSFUL;
169      break;
170    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
171      scheduler = _Thread_Scheduler_get_home( executing );
172      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
173
174      if ( valid ) {
175        _CORE_ceiling_mutex_Initialize(
176          &the_semaphore->Core_control.Mutex,
177          scheduler,
178          priority
179        );
180
181        if ( count == 0 ) {
182          Thread_queue_Context queue_context;
183
184          _Thread_queue_Context_initialize( &queue_context );
185          _Thread_queue_Context_clear_priority_updates( &queue_context );
186          _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
187          _CORE_mutex_Acquire_critical(
188            &the_semaphore->Core_control.Mutex.Recursive.Mutex,
189            &queue_context
190          );
191          status = _CORE_ceiling_mutex_Set_owner(
192            &the_semaphore->Core_control.Mutex,
193            executing,
194            &queue_context
195          );
196
197          if ( status != STATUS_SUCCESSFUL ) {
198            _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
199          }
200        } else {
201          status = STATUS_SUCCESSFUL;
202        }
203      } else {
204        status = STATUS_INVALID_PRIORITY;
205      }
206
207      break;
208#if defined(RTEMS_SMP)
209    case SEMAPHORE_VARIANT_MRSP:
210      scheduler = _Thread_Scheduler_get_home( executing );
211      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
212
213      if ( valid ) {
214        status = _MRSP_Initialize(
215          &the_semaphore->Core_control.MRSP,
216          scheduler,
217          priority,
218          executing,
219          count == 0
220        );
221      } else {
222        status = STATUS_INVALID_PRIORITY;
223      }
224
225      break;
226#endif
227    default:
228      _Assert(
229        variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
230          || variant == SEMAPHORE_VARIANT_COUNTING
231      );
232      _CORE_semaphore_Initialize(
233        &the_semaphore->Core_control.Semaphore,
234        count
235      );
236      status = STATUS_SUCCESSFUL;
237      break;
238  }
239
240  if ( status != STATUS_SUCCESSFUL ) {
241    _Semaphore_Free( the_semaphore );
242    _Objects_Allocator_unlock();
243    return _Status_Get( status );
244  }
245
246  /*
247   *  Whether we initialized it as a mutex or counting semaphore, it is
248   *  now ready to be "offered" for use as a Classic API Semaphore.
249   */
250  _Objects_Open(
251    &_Semaphore_Information,
252    &the_semaphore->Object,
253    (Objects_Name) name
254  );
255
256  *id = the_semaphore->Object.id;
257
258#if defined(RTEMS_MULTIPROCESSING)
259  if ( _Attributes_Is_global( attribute_set ) )
260    _Semaphore_MP_Send_process_packet(
261      SEMAPHORE_MP_ANNOUNCE_CREATE,
262      the_semaphore->Object.id,
263      name,
264      0                          /* Not used */
265    );
266#endif
267  _Objects_Allocator_unlock();
268  return RTEMS_SUCCESSFUL;
269}
270
271static void _Semaphore_Manager_initialization( void )
272{
273  _Objects_Initialize_information( &_Semaphore_Information );
274}
275
276RTEMS_SYSINIT_ITEM(
277  _Semaphore_Manager_initialization,
278  RTEMS_SYSINIT_CLASSIC_SEMAPHORE,
279  RTEMS_SYSINIT_ORDER_MIDDLE
280);
Note: See TracBrowser for help on using the repository browser.