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

Last change on this file was b3b6d21e, checked in by Joel Sherrill <joel@…>, on 02/16/22 at 22:28:59

cpukit/rtems/src/[s-z]*.c: Change license to BSD-2

Updates #3053.

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSImplClassicSemaphore
7 *
8 * @brief This source file contains the implementation of
9 *   rtems_semaphore_create() and the Semaphore Manager system initialization.
10 */
11
12/*
13 *  COPYRIGHT (c) 1989-2014.
14 *  On-Line Applications Research Corporation (OAR).
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 *    notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 *    notice, this list of conditions and the following disclaimer in the
23 *    documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include <rtems/rtems/semimpl.h>
43#include <rtems/rtems/attrimpl.h>
44#include <rtems/rtems/statusimpl.h>
45#include <rtems/rtems/support.h>
46#include <rtems/rtems/tasksimpl.h>
47#include <rtems/score/schedulerimpl.h>
48#include <rtems/score/sysstate.h>
49#include <rtems/sysinit.h>
50
51#define SEMAPHORE_KIND_MASK ( RTEMS_SEMAPHORE_CLASS | RTEMS_INHERIT_PRIORITY \
52  | RTEMS_PRIORITY_CEILING | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
53
54rtems_status_code rtems_semaphore_create(
55  rtems_name           name,
56  uint32_t             count,
57  rtems_attribute      attribute_set,
58  rtems_task_priority  priority_ceiling,
59  rtems_id            *id
60)
61{
62  Semaphore_Control       *the_semaphore;
63  Thread_Control          *executing;
64  Status_Control           status;
65  rtems_attribute          maybe_global;
66  rtems_attribute          mutex_with_protocol;
67  Semaphore_Variant        variant;
68  const Scheduler_Control *scheduler;
69  bool                     valid;
70  Priority_Control         priority;
71  uintptr_t                flags;
72
73  if ( !rtems_is_name_valid( name ) )
74    return RTEMS_INVALID_NAME;
75
76  if ( !id )
77    return RTEMS_INVALID_ADDRESS;
78
79#if defined(RTEMS_MULTIPROCESSING)
80  if ( !_System_state_Is_multiprocessing ) {
81    attribute_set = _Attributes_Clear( attribute_set, RTEMS_GLOBAL );
82  }
83#endif
84
85  /* Attribute subset defining a potentially global semaphore variant */
86  maybe_global = attribute_set & SEMAPHORE_KIND_MASK;
87
88  /* Attribute subset defining a mutex variant with a locking protocol */
89  mutex_with_protocol =
90    attribute_set & ( SEMAPHORE_KIND_MASK | RTEMS_GLOBAL | RTEMS_PRIORITY );
91
92  if ( maybe_global == RTEMS_COUNTING_SEMAPHORE ) {
93    variant = SEMAPHORE_VARIANT_COUNTING;
94  } else if ( maybe_global == RTEMS_SIMPLE_BINARY_SEMAPHORE ) {
95    variant = SEMAPHORE_VARIANT_SIMPLE_BINARY;
96  } else if ( maybe_global == RTEMS_BINARY_SEMAPHORE ) {
97    variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
98  } else if (
99    mutex_with_protocol
100      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY )
101  ) {
102    variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
103  } else if (
104    mutex_with_protocol
105      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING )
106  ) {
107    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
108  } else if (
109    mutex_with_protocol == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY |
110      RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
111  ) {
112#if defined(RTEMS_SMP)
113    variant = SEMAPHORE_VARIANT_MRSP;
114#else
115    /*
116     * On uni-processor configurations the Multiprocessor Resource Sharing
117     * Protocol is equivalent to the Priority Ceiling Protocol.
118     */
119    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
120#endif
121  } else {
122    return RTEMS_NOT_DEFINED;
123  }
124
125  if ( count > 1 && variant != SEMAPHORE_VARIANT_COUNTING ) {
126    return RTEMS_INVALID_NUMBER;
127  }
128
129  the_semaphore = _Semaphore_Allocate();
130
131  if ( !the_semaphore ) {
132    _Objects_Allocator_unlock();
133    return RTEMS_TOO_MANY;
134  }
135
136  flags = _Semaphore_Set_variant( 0, variant );
137
138#if defined(RTEMS_MULTIPROCESSING)
139  if ( _Attributes_Is_global( attribute_set ) ) {
140    bool ok;
141
142    ok = _Objects_MP_Allocate_and_open(
143      &_Semaphore_Information,
144      name,
145      the_semaphore->Object.id,
146      false
147    );
148
149    if ( !ok ) {
150      _Semaphore_Free( the_semaphore );
151      _Objects_Allocator_unlock();
152      return RTEMS_TOO_MANY;
153    }
154
155    flags = _Semaphore_Make_global( flags );
156  }
157#endif
158
159  if ( _Attributes_Is_priority( attribute_set ) ) {
160    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_PRIORITY );
161  } else {
162    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_FIFO );
163  }
164
165  _Semaphore_Set_flags( the_semaphore, flags );
166  executing = _Thread_Get_executing();
167
168  switch ( variant ) {
169    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
170    case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
171      _CORE_recursive_mutex_Initialize(
172        &the_semaphore->Core_control.Mutex.Recursive
173      );
174
175      if ( count == 0 ) {
176        _CORE_mutex_Set_owner(
177          &the_semaphore->Core_control.Mutex.Recursive.Mutex,
178          executing
179        );
180        _Thread_Resource_count_increment( executing );
181      }
182
183      status = STATUS_SUCCESSFUL;
184      break;
185    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
186      scheduler = _Thread_Scheduler_get_home( executing );
187      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
188
189      if ( valid ) {
190        _CORE_ceiling_mutex_Initialize(
191          &the_semaphore->Core_control.Mutex,
192          scheduler,
193          priority
194        );
195
196        if ( count == 0 ) {
197          Thread_queue_Context queue_context;
198
199          _Thread_queue_Context_initialize( &queue_context );
200          _Thread_queue_Context_clear_priority_updates( &queue_context );
201          _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
202          _CORE_mutex_Acquire_critical(
203            &the_semaphore->Core_control.Mutex.Recursive.Mutex,
204            &queue_context
205          );
206          status = _CORE_ceiling_mutex_Set_owner(
207            &the_semaphore->Core_control.Mutex,
208            executing,
209            &queue_context
210          );
211
212          if ( status != STATUS_SUCCESSFUL ) {
213            _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
214          }
215        } else {
216          status = STATUS_SUCCESSFUL;
217        }
218      } else {
219        status = STATUS_INVALID_PRIORITY;
220      }
221
222      break;
223#if defined(RTEMS_SMP)
224    case SEMAPHORE_VARIANT_MRSP:
225      scheduler = _Thread_Scheduler_get_home( executing );
226      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
227
228      if ( valid ) {
229        status = _MRSP_Initialize(
230          &the_semaphore->Core_control.MRSP,
231          scheduler,
232          priority,
233          executing,
234          count == 0
235        );
236      } else {
237        status = STATUS_INVALID_PRIORITY;
238      }
239
240      break;
241#endif
242    default:
243      _Assert(
244        variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
245          || variant == SEMAPHORE_VARIANT_COUNTING
246      );
247      _CORE_semaphore_Initialize(
248        &the_semaphore->Core_control.Semaphore,
249        count
250      );
251      status = STATUS_SUCCESSFUL;
252      break;
253  }
254
255  if ( status != STATUS_SUCCESSFUL ) {
256    _Semaphore_Free( the_semaphore );
257    _Objects_Allocator_unlock();
258    return _Status_Get( status );
259  }
260
261  /*
262   *  Whether we initialized it as a mutex or counting semaphore, it is
263   *  now ready to be "offered" for use as a Classic API Semaphore.
264   */
265  *id = _Objects_Open_u32(
266    &_Semaphore_Information,
267    &the_semaphore->Object,
268    name
269  );
270
271#if defined(RTEMS_MULTIPROCESSING)
272  if ( _Attributes_Is_global( attribute_set ) )
273    _Semaphore_MP_Send_process_packet(
274      SEMAPHORE_MP_ANNOUNCE_CREATE,
275      the_semaphore->Object.id,
276      name,
277      0                          /* Not used */
278    );
279#endif
280  _Objects_Allocator_unlock();
281  return RTEMS_SUCCESSFUL;
282}
283
284static void _Semaphore_Manager_initialization( void )
285{
286  _Objects_Initialize_information( &_Semaphore_Information );
287}
288
289RTEMS_SYSINIT_ITEM(
290  _Semaphore_Manager_initialization,
291  RTEMS_SYSINIT_CLASSIC_SEMAPHORE,
292  RTEMS_SYSINIT_ORDER_MIDDLE
293);
Note: See TracBrowser for help on using the repository browser.