source: rtems/cpukit/rtems/src/semcreate.c @ 6b5f22dc

Last change on this file since 6b5f22dc was 6b5f22dc, checked in by Sebastian Huber <sebastian.huber@…>, on 11/26/20 at 10:45:47

rtems: Canonicalize Doxygen @file comments

Use common phrases for the file brief descriptions.

Update #3706.

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