source: rtems/cpukit/rtems/src/semcreate.c @ 21275b58

Last change on this file since 21275b58 was 21275b58, checked in by Sebastian Huber <sebastian.huber@…>, on Nov 22, 2018 at 6:14:51 PM

score: Static Objects_Information initialization

Statically allocate the objects information together with the initial
set of objects either via <rtems/confdefs.h>. Provide default object
informations with zero objects via librtemscpu.a. This greatly
simplifies the workspace size estimate. RTEMS applications which do not
use the unlimited objects option are easier to debug since all objects
reside now in statically allocated objects of the right types.

Close #3621.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/**
2 * @file
3 *
4 * @brief rtems_semaphore_create
5 * @ingroup ClassicSem Semaphores
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2014.
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/rtems/semimpl.h>
22#include <rtems/rtems/attrimpl.h>
23#include <rtems/rtems/statusimpl.h>
24#include <rtems/rtems/support.h>
25#include <rtems/rtems/tasksimpl.h>
26#include <rtems/score/schedulerimpl.h>
27#include <rtems/score/sysstate.h>
28#include <rtems/sysinit.h>
29
30#define SEMAPHORE_KIND_MASK ( RTEMS_SEMAPHORE_CLASS | RTEMS_INHERIT_PRIORITY \
31  | RTEMS_PRIORITY_CEILING | RTEMS_MULTIPROCESSOR_RESOURCE_SHARING )
32
33rtems_status_code rtems_semaphore_create(
34  rtems_name           name,
35  uint32_t             count,
36  rtems_attribute      attribute_set,
37  rtems_task_priority  priority_ceiling,
38  rtems_id            *id
39)
40{
41  Semaphore_Control       *the_semaphore;
42  Thread_Control          *executing;
43  Status_Control           status;
44  rtems_attribute          maybe_global;
45  rtems_attribute          mutex_with_protocol;
46  Semaphore_Variant        variant;
47  const Scheduler_Control *scheduler;
48  bool                     valid;
49  Priority_Control         priority;
50
51  if ( !rtems_is_name_valid( name ) )
52    return RTEMS_INVALID_NAME;
53
54  if ( !id )
55    return RTEMS_INVALID_ADDRESS;
56
57#if defined(RTEMS_MULTIPROCESSING)
58  if (
59    _Attributes_Is_global( attribute_set )
60      && !_System_state_Is_multiprocessing
61  ) {
62    return RTEMS_MP_NOT_CONFIGURED;
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#if defined(RTEMS_MULTIPROCESSING)
120  the_semaphore->is_global = _Attributes_Is_global( attribute_set );
121
122  if ( _Attributes_Is_global( attribute_set ) &&
123       ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
124                            the_semaphore->Object.id, false ) ) ) {
125    _Semaphore_Free( the_semaphore );
126    _Objects_Allocator_unlock();
127    return RTEMS_TOO_MANY;
128  }
129#endif
130
131  executing = _Thread_Get_executing();
132
133  the_semaphore->variant = variant;
134
135  if ( _Attributes_Is_priority( attribute_set ) ) {
136    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_PRIORITY;
137  } else {
138    the_semaphore->discipline = SEMAPHORE_DISCIPLINE_FIFO;
139  }
140
141  switch ( the_semaphore->variant ) {
142    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
143    case SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY:
144      _CORE_recursive_mutex_Initialize(
145        &the_semaphore->Core_control.Mutex.Recursive
146      );
147
148      if ( count == 0 ) {
149        _CORE_mutex_Set_owner(
150          &the_semaphore->Core_control.Mutex.Recursive.Mutex,
151          executing
152        );
153        _Thread_Resource_count_increment( executing );
154      }
155
156      status = STATUS_SUCCESSFUL;
157      break;
158    case SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING:
159      scheduler = _Thread_Scheduler_get_home( executing );
160      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
161
162      if ( valid ) {
163        _CORE_ceiling_mutex_Initialize(
164          &the_semaphore->Core_control.Mutex,
165          scheduler,
166          priority
167        );
168
169        if ( count == 0 ) {
170          Thread_queue_Context queue_context;
171
172          _Thread_queue_Context_initialize( &queue_context );
173          _Thread_queue_Context_clear_priority_updates( &queue_context );
174          _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
175          _CORE_mutex_Acquire_critical(
176            &the_semaphore->Core_control.Mutex.Recursive.Mutex,
177            &queue_context
178          );
179          status = _CORE_ceiling_mutex_Set_owner(
180            &the_semaphore->Core_control.Mutex,
181            executing,
182            &queue_context
183          );
184
185          if ( status != STATUS_SUCCESSFUL ) {
186            _Thread_queue_Destroy( &the_semaphore->Core_control.Wait_queue );
187          }
188        } else {
189          status = STATUS_SUCCESSFUL;
190        }
191      } else {
192        status = STATUS_INVALID_PRIORITY;
193      }
194
195      break;
196#if defined(RTEMS_SMP)
197    case SEMAPHORE_VARIANT_MRSP:
198      scheduler = _Thread_Scheduler_get_home( executing );
199      priority = _RTEMS_Priority_To_core( scheduler, priority_ceiling, &valid );
200
201      if ( valid ) {
202        status = _MRSP_Initialize(
203          &the_semaphore->Core_control.MRSP,
204          scheduler,
205          priority,
206          executing,
207          count == 0
208        );
209      } else {
210        status = STATUS_INVALID_PRIORITY;
211      }
212
213      break;
214#endif
215    default:
216      _Assert(
217        the_semaphore->variant == SEMAPHORE_VARIANT_SIMPLE_BINARY
218          || the_semaphore->variant == SEMAPHORE_VARIANT_COUNTING
219      );
220      _CORE_semaphore_Initialize(
221        &the_semaphore->Core_control.Semaphore,
222        count
223      );
224      status = STATUS_SUCCESSFUL;
225      break;
226  }
227
228  if ( status != STATUS_SUCCESSFUL ) {
229    _Semaphore_Free( the_semaphore );
230    _Objects_Allocator_unlock();
231    return _Status_Get( status );
232  }
233
234  /*
235   *  Whether we initialized it as a mutex or counting semaphore, it is
236   *  now ready to be "offered" for use as a Classic API Semaphore.
237   */
238  _Objects_Open(
239    &_Semaphore_Information,
240    &the_semaphore->Object,
241    (Objects_Name) name
242  );
243
244  *id = the_semaphore->Object.id;
245
246#if defined(RTEMS_MULTIPROCESSING)
247  if ( _Attributes_Is_global( attribute_set ) )
248    _Semaphore_MP_Send_process_packet(
249      SEMAPHORE_MP_ANNOUNCE_CREATE,
250      the_semaphore->Object.id,
251      name,
252      0                          /* Not used */
253    );
254#endif
255  _Objects_Allocator_unlock();
256  return RTEMS_SUCCESSFUL;
257}
258
259static void _Semaphore_Manager_initialization(void)
260{
261  _Objects_Initialize_information( &_Semaphore_Information );
262
263#if defined(RTEMS_MULTIPROCESSING)
264  _MPCI_Register_packet_processor(
265    MP_PACKET_SEMAPHORE,
266    _Semaphore_MP_Process_packet
267  );
268#endif
269}
270
271RTEMS_SYSINIT_ITEM(
272  _Semaphore_Manager_initialization,
273  RTEMS_SYSINIT_CLASSIC_SEMAPHORE,
274  RTEMS_SYSINIT_ORDER_MIDDLE
275);
Note: See TracBrowser for help on using the repository browser.