source: rtems/cpukit/rtems/src/semcreate.c @ 46c23871

5
Last change on this file since 46c23871 was 46c23871, checked in by Sebastian Huber <sebastian.huber@…>, on 06/16/20 at 05:28:58

rtems: Remove RTEMS_MP_NOT_CONFIGURED error

Some objects can be created with a local or global scope in a
multiprocessing network. In non-multiprocessing configurations setting
the scope to local or global had no effect since such a system can be
viewed as a multiprocessing network with just one node. One and all
nodes is the same in such a network. However, if multiprocessing was
configured, creation of a global object in a single node network
resulted in an RTEMS_MP_NOT_CONFIGURED error. Remove this error
condition for symmetry to the non-multiprocessing setup. This is in line
with the task affinity behaviour in SMP systems.

Update #4005.

  • 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 ( !_System_state_Is_multiprocessing ) {
61    attribute_set = _Attributes_Clear( attribute_set, RTEMS_GLOBAL );
62  }
63#endif
64
65  /* Attribute subset defining a potentially global semaphore variant */
66  maybe_global = attribute_set & SEMAPHORE_KIND_MASK;
67
68  /* Attribute subset defining a mutex variant with a locking protocol */
69  mutex_with_protocol =
70    attribute_set & ( SEMAPHORE_KIND_MASK | RTEMS_GLOBAL | RTEMS_PRIORITY );
71
72  if ( maybe_global == RTEMS_COUNTING_SEMAPHORE ) {
73    variant = SEMAPHORE_VARIANT_COUNTING;
74  } else if ( count > 1 ) {
75    /*
76     * The remaining variants are all binary semphores, thus reject an invalid
77     * count value.
78     */
79    return RTEMS_INVALID_NUMBER;
80  } else if ( maybe_global == RTEMS_SIMPLE_BINARY_SEMAPHORE ) {
81    variant = SEMAPHORE_VARIANT_SIMPLE_BINARY;
82  } else if ( maybe_global == RTEMS_BINARY_SEMAPHORE ) {
83    variant = SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL;
84  } else if (
85    mutex_with_protocol
86      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY )
87  ) {
88    variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
89  } else if (
90    mutex_with_protocol
91      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_PRIORITY_CEILING )
92  ) {
93    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
94  } else if (
95    mutex_with_protocol
96      == ( RTEMS_BINARY_SEMAPHORE | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
97  ) {
98#if defined(RTEMS_SMP)
99    variant = SEMAPHORE_VARIANT_MRSP;
100#else
101    /*
102     * On uni-processor configurations the Multiprocessor Resource Sharing
103     * Protocol is equivalent to the Priority Ceiling Protocol.
104     */
105    variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
106#endif
107  } else {
108    return RTEMS_NOT_DEFINED;
109  }
110
111  the_semaphore = _Semaphore_Allocate();
112
113  if ( !the_semaphore ) {
114    _Objects_Allocator_unlock();
115    return RTEMS_TOO_MANY;
116  }
117
118  flags = _Semaphore_Set_variant( 0, variant );
119
120#if defined(RTEMS_MULTIPROCESSING)
121  if ( _Attributes_Is_global( attribute_set ) ) {
122    bool ok;
123
124    ok = _Objects_MP_Allocate_and_open(
125      &_Semaphore_Information,
126      name,
127      the_semaphore->Object.id,
128      false
129    );
130
131    if ( !ok ) {
132      _Semaphore_Free( the_semaphore );
133      _Objects_Allocator_unlock();
134      return RTEMS_TOO_MANY;
135    }
136
137    flags = _Semaphore_Make_global( flags );
138  }
139#endif
140
141  if ( _Attributes_Is_priority( attribute_set ) ) {
142    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_PRIORITY );
143  } else {
144    flags = _Semaphore_Set_discipline( flags, SEMAPHORE_DISCIPLINE_FIFO );
145  }
146
147  _Semaphore_Set_flags( the_semaphore, flags );
148  executing = _Thread_Get_executing();
149
150  switch ( variant ) {
151    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
152    case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
153      _CORE_recursive_mutex_Initialize(
154        &the_semaphore->Core_control.Mutex.Recursive
155      );
156
157      if ( count == 0 ) {
158        _CORE_mutex_Set_owner(
159          &the_semaphore->Core_control.Mutex.Recursive.Mutex,
160          executing
161        );
162        _Thread_Resource_count_increment( executing );
163      }
164
165      status = STATUS_SUCCESSFUL;
166      break;
167    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
168      scheduler = _Thread_Scheduler_get_home( executing );
169      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
170
171      if ( valid ) {
172        _CORE_ceiling_mutex_Initialize(
173          &the_semaphore->Core_control.Mutex,
174          scheduler,
175          priority
176        );
177
178        if ( count == 0 ) {
179          Thread_queue_Context queue_context;
180
181          _Thread_queue_Context_initialize( &queue_context );
182          _Thread_queue_Context_clear_priority_updates( &queue_context );
183          _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
184          _CORE_mutex_Acquire_critical(
185            &the_semaphore->Core_control.Mutex.Recursive.Mutex,
186            &queue_context
187          );
188          status = _CORE_ceiling_mutex_Set_owner(
189            &the_semaphore->Core_control.Mutex,
190            executing,
191            &queue_context
192          );
193
194          if ( status != STATUS_SUCCESSFUL ) {
195            _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
196          }
197        } else {
198          status = STATUS_SUCCESSFUL;
199        }
200      } else {
201        status = STATUS_INVALID_PRIORITY;
202      }
203
204      break;
205#if defined(RTEMS_SMP)
206    case SEMAPHORE_VARIANT_MRSP:
207      scheduler = _Thread_Scheduler_get_home( executing );
208      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
209
210      if ( valid ) {
211        status = _MRSP_Initialize(
212          &the_semaphore->Core_control.MRSP,
213          scheduler,
214          priority,
215          executing,
216          count == 0
217        );
218      } else {
219        status = STATUS_INVALID_PRIORITY;
220      }
221
222      break;
223#endif
224    default:
225      _Assert(
226        variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
227          || variant == SEMAPHORE_VARIANT_COUNTING
228      );
229      _CORE_semaphore_Initialize(
230        &the_semaphore->Core_control.Semaphore,
231        count
232      );
233      status = STATUS_SUCCESSFUL;
234      break;
235  }
236
237  if ( status != STATUS_SUCCESSFUL ) {
238    _Semaphore_Free( the_semaphore );
239    _Objects_Allocator_unlock();
240    return _Status_Get( status );
241  }
242
243  /*
244   *  Whether we initialized it as a mutex or counting semaphore, it is
245   *  now ready to be "offered" for use as a Classic API Semaphore.
246   */
247  _Objects_Open(
248    &_Semaphore_Information,
249    &the_semaphore->Object,
250    (Objects_Name) name
251  );
252
253  *id = the_semaphore->Object.id;
254
255#if defined(RTEMS_MULTIPROCESSING)
256  if ( _Attributes_Is_global( attribute_set ) )
257    _Semaphore_MP_Send_process_packet(
258      SEMAPHORE_MP_ANNOUNCE_CREATE,
259      the_semaphore->Object.id,
260      name,
261      0                          /* Not used */
262    );
263#endif
264  _Objects_Allocator_unlock();
265  return RTEMS_SUCCESSFUL;
266}
267
268static void _Semaphore_Manager_initialization( void )
269{
270  _Objects_Initialize_information( &_Semaphore_Information );
271}
272
273RTEMS_SYSINIT_ITEM(
274  _Semaphore_Manager_initialization,
275  RTEMS_SYSINIT_CLASSIC_SEMAPHORE,
276  RTEMS_SYSINIT_ORDER_MIDDLE
277);
Note: See TracBrowser for help on using the repository browser.