RTEMS
semcreate.c
Go to the documentation of this file.
1 
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>
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 
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
87  ) {
88  variant = SEMAPHORE_VARIANT_MUTEX_INHERIT_PRIORITY;
89  } else if (
90  mutex_with_protocol
92  ) {
93  variant = SEMAPHORE_VARIANT_MUTEX_PRIORITY_CEILING;
94  } else if (
95  mutex_with_protocol
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 ) {
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(
126  name,
127  the_semaphore->Object.id,
128  false
129  );
130 
131  if ( !ok ) {
132  _Semaphore_Free( the_semaphore );
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:
154  &the_semaphore->Core_control.Mutex.Recursive
155  );
156 
157  if ( count == 0 ) {
159  &the_semaphore->Core_control.Mutex.Recursive.Mutex,
160  executing
161  );
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 ) {
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 );
185  &the_semaphore->Core_control.Mutex.Recursive.Mutex,
186  &queue_context
187  );
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  );
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 );
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  */
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
265  return RTEMS_SUCCESSFUL;
266 }
267 
268 static void _Semaphore_Manager_initialization( void )
269 {
271 }
272 
273 RTEMS_SYSINIT_ITEM(
274  _Semaphore_Manager_initialization,
275  RTEMS_SYSINIT_CLASSIC_SEMAPHORE,
276  RTEMS_SYSINIT_ORDER_MIDDLE
277 );
This status code indicates you have attempted to create too many instances of a particular object cla...
Definition: status.h:112
static __inline__ void _Objects_Allocator_unlock(void)
Unlocks the object allocator mutex.
Definition: objectimpl.h:846
This header file defines support services of the API.
static __inline__ Priority_Control _RTEMS_Priority_To_core(const Scheduler_Control *scheduler, rtems_task_priority priority, bool *valid)
Converts the RTEMS API priority to the corresponding SuperCore priority and validates it...
Definition: tasksimpl.h:96
void _CORE_semaphore_Initialize(CORE_semaphore_Control *the_semaphore, uint32_t initial_value)
Initializes the semaphore based on the parameters passed.
Definition: coresem.c:23
static __inline__ Semaphore_Control * _Semaphore_Allocate(void)
Allocates a semaphore control block from the inactive chain of free semaphore control blocks...
Definition: semimpl.h:144
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:70
static __inline__ Status_Control _MRSP_Initialize(MRSP_Control *mrsp, const Scheduler_Control *scheduler, Priority_Control ceiling_priority, Thread_Control *executing, bool initially_locked)
Initializes a MrsP control.
Definition: mrspimpl.h:289
RTEMS_INLINE_ROUTINE bool _Attributes_Is_priority(rtems_attribute attribute_set)
Checks if the priority attribute is enabled in the attribute_set.
Definition: attrimpl.h:119
Thread queue context for the thread queue methods.
Definition: threadq.h:198
uint32_t rtems_name
This type is used to represent a Classic API object name.
Definition: types.h:227
static __inline__ const Scheduler_Control * _Thread_Scheduler_get_home(const Thread_Control *the_thread)
Gets the home scheduler of the thread.
Definition: threadimpl.h:1419
CORE_ceiling_mutex_Control Mutex
Definition: semdata.h:71
void _Objects_Initialize_information(Objects_Information *information)
Initializes the specified objects information.
static __inline__ void _CORE_mutex_Set_owner(CORE_mutex_Control *the_mutex, Thread_Control *owner)
Sets the owner of the mutex.
static __inline__ void _Thread_Resource_count_increment(Thread_Control *the_thread)
Increments the thread&#39;s resource count.
Definition: threadimpl.h:1339
CORE_recursive_mutex_Control Recursive
The plain recursive mutex.
Definition: coremutex.h:87
Inlined Routines Associated with the Manipulation of the Scheduler.
#define RTEMS_INHERIT_PRIORITY
This attribute constant indicates that the Classic API Semaphore object shall use the Priority Inheri...
Definition: attr.h:185
static __inline__ void _Thread_queue_Context_initialize(Thread_queue_Context *queue_context)
Initializes a thread queue context.
Definition: threadqimpl.h:152
Thread_queue_Control Wait_queue
The thread queue present in all other variants.
Definition: semdata.h:65
static bool rtems_is_name_valid(rtems_status_code name)
Returns true, if the specified object name is valid, otherwise returns false.
Definition: support.h:126
#define RTEMS_MULTIPROCESSOR_RESOURCE_SHARING
This attribute constant indicates that the Classic API Semaphore object shall use the Multiprocessor ...
Definition: attr.h:207
static __inline__ Status_Control _CORE_ceiling_mutex_Set_owner(CORE_ceiling_mutex_Control *the_mutex, Thread_Control *owner, Thread_queue_Context *queue_context)
Sets the owner of the ceiling mutex.
This status code indicates that a specified number was invalid.
Definition: status.h:138
#define RTEMS_COUNTING_SEMAPHORE
This attribute constant indicates that the Classic API Semaphore object shall be a counting semaphore...
Definition: attr.h:131
Objects_Control Object
The object management portion of a semaphore instance.
Definition: semdata.h:50
static __inline__ struct _Thread_Control * _Thread_Get_executing(void)
Returns the thread control block of the executing thread.
Definition: percpu.h:878
#define RTEMS_PRIORITY
This attribute constant indicates that the Classic API object shall manage blocking tasks using the t...
Definition: attr.h:260
uint32_t rtems_task_priority
%
Definition: tasks.h:94
rtems_status_code rtems_semaphore_create(rtems_name name, uint32_t count, rtems_attribute attribute_set, rtems_task_priority priority_ceiling, rtems_id *id)
Creates a semaphore with the specified properties and returns its identifier.
Definition: semcreate.c:34
This status code indicates successful completion.
Definition: status.h:86
#define RTEMS_SIMPLE_BINARY_SEMAPHORE
This attribute constant indicates that the Classic API Semaphore object shall be a simple binary sema...
Definition: attr.h:292
static __inline__ void _Objects_Open(Objects_Information *information, Objects_Control *the_object, Objects_Name name)
Places the_object control pointer and object name in the Local Pointer and Local Name Tables...
Definition: objectimpl.h:750
Classic Semaphore Manager Implementation.
rtems_status_code
This enumeration provides status codes for directives of the Classic API.
Definition: status.h:82
#define RTEMS_BINARY_SEMAPHORE
This attribute constant indicates that the Classic API Semaphore object shall be a proper binary sema...
Definition: attr.h:121
Classic Status Implementation.
Thread_queue_Lock_context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:203
CORE_mutex_Control Mutex
The plain non-recursive mutex.
Definition: coremutex.h:72
static __inline__ void _Semaphore_Free(Semaphore_Control *the_semaphore)
Frees a semaphore control block to the inactive chain of free semaphore control blocks.
Definition: semimpl.h:156
static __inline__ void _CORE_ceiling_mutex_Initialize(CORE_ceiling_mutex_Control *the_mutex, const Scheduler_Control *scheduler, Priority_Control priority_ceiling)
initializes a ceiling mutex.
static __inline__ void _Thread_queue_Context_clear_priority_updates(Thread_queue_Context *queue_context)
Clears the priority update count of the thread queue context.
Definition: threadqimpl.h:338
This status code indicates that a specified address was invalid.
Definition: status.h:133
uint32_t rtems_attribute
This type is used to represent Classic API attributes.
Definition: attr.h:91
#define RTEMS_PRIORITY_CEILING
This attribute constant indicates that the Classic API Semaphore object shall use the Priority Ceilin...
Definition: attr.h:272
This status code indicates that the item has not been initialized.
Definition: status.h:143
Classic Attributes Implementation.
Objects_Id rtems_id
Values of this type identify an RTEMS object.
Definition: types.h:99
System State Handler API.
RTEMS_INLINE_ROUTINE rtems_attribute _Attributes_Clear(rtems_attribute attribute_set, rtems_attribute mask)
Clears the requested new_attributes in the attribute_set passed in.
Definition: attrimpl.h:75
CORE_semaphore_Control Semaphore
Definition: semdata.h:77
Scheduler control.
Definition: scheduler.h:264
#define _ISR_lock_ISR_disable(_context)
Disables interrupts and saves the previous interrupt state in the ISR lock context.
Definition: isrlock.h:392
static __inline__ void _CORE_mutex_Acquire_critical(CORE_mutex_Control *the_mutex, Thread_queue_Context *queue_context)
Acquires the mutex critical.
Definition: coremuteximpl.h:71
Objects_Information _Semaphore_Information
The Classic Semaphore objects information.
Definition: sem.c:47
ISR_lock_Context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:130
static __inline__ void _Thread_queue_Destroy(Thread_queue_Control *the_thread_queue)
Destroys the thread queue.
Definition: threadqimpl.h:1378
This status code indicates that an object name was invalid.
Definition: status.h:101
union Semaphore_Control::@8 Core_control
#define RTEMS_GLOBAL
This attribute constant indicates that the Classic API object shall be a global resource in a multipr...
Definition: attr.h:173
Semaphore_Variant
Classic semaphore variants.
Definition: semimpl.h:42
static __inline__ void _CORE_recursive_mutex_Initialize(CORE_recursive_mutex_Control *the_mutex)
Initializes a recursive mutex.
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG.
Definition: assert.h:100
Classic Tasks Manager Implementation.
Objects_Id id
Definition: objectdata.h:43