RTEMS  5.0.0
coremuteximpl.h
Go to the documentation of this file.
1 
9 /*
10  * COPYRIGHT (c) 1989-2009.
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 #ifndef _RTEMS_SCORE_COREMUTEXIMPL_H
19 #define _RTEMS_SCORE_COREMUTEXIMPL_H
20 
21 #include <rtems/score/coremutex.h>
22 #include <rtems/score/chainimpl.h>
24 #include <rtems/score/status.h>
25 #include <rtems/score/threadimpl.h>
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
37 #define CORE_MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
38 
39 #define CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS \
40  &_Thread_queue_Operations_priority_inherit
41 
42 RTEMS_INLINE_ROUTINE void _CORE_mutex_Initialize(
43  CORE_mutex_Control *the_mutex
44 )
45 {
47 }
48 
49 RTEMS_INLINE_ROUTINE void _CORE_mutex_Destroy( CORE_mutex_Control *the_mutex )
50 {
51  _Thread_queue_Destroy( &the_mutex->Wait_queue );
52 }
53 
54 RTEMS_INLINE_ROUTINE void _CORE_mutex_Acquire_critical(
55  CORE_mutex_Control *the_mutex,
56  Thread_queue_Context *queue_context
57 )
58 {
59  _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, queue_context );
60 }
61 
62 RTEMS_INLINE_ROUTINE void _CORE_mutex_Release(
63  CORE_mutex_Control *the_mutex,
64  Thread_queue_Context *queue_context
65 )
66 {
67  _Thread_queue_Release( &the_mutex->Wait_queue, queue_context );
68 }
69 
70 RTEMS_INLINE_ROUTINE Thread_Control *_CORE_mutex_Get_owner(
71  const CORE_mutex_Control *the_mutex
72 )
73 {
74  return the_mutex->Wait_queue.Queue.owner;
75 }
76 
89  const CORE_mutex_Control *the_mutex
90 )
91 {
92  return _CORE_mutex_Get_owner( the_mutex ) != NULL;
93 }
94 
95 Status_Control _CORE_mutex_Seize_slow(
96  CORE_mutex_Control *the_mutex,
97  const Thread_queue_Operations *operations,
98  Thread_Control *executing,
99  bool wait,
100  Thread_queue_Context *queue_context
101 );
102 
103 RTEMS_INLINE_ROUTINE void _CORE_mutex_Set_owner(
104  CORE_mutex_Control *the_mutex,
105  Thread_Control *owner
106 )
107 {
108  the_mutex->Wait_queue.Queue.owner = owner;
109 }
110 
111 RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_owner(
112  const CORE_mutex_Control *the_mutex,
113  const Thread_Control *the_thread
114 )
115 {
116  return _CORE_mutex_Get_owner( the_mutex ) == the_thread;
117 }
118 
119 RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize(
121 )
122 {
123  _CORE_mutex_Initialize( &the_mutex->Mutex );
124  the_mutex->nest_level = 0;
125 }
126 
127 RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Seize_nested(
129 )
130 {
131  ++the_mutex->nest_level;
132  return STATUS_SUCCESSFUL;
133 }
134 
135 RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Seize(
136  CORE_recursive_mutex_Control *the_mutex,
137  const Thread_queue_Operations *operations,
138  Thread_Control *executing,
139  bool wait,
140  Status_Control ( *nested )( CORE_recursive_mutex_Control * ),
141  Thread_queue_Context *queue_context
142 )
143 {
144  Thread_Control *owner;
145 
146  _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
147 
148  owner = _CORE_mutex_Get_owner( &the_mutex->Mutex );
149 
150  if ( owner == NULL ) {
151  _CORE_mutex_Set_owner( &the_mutex->Mutex, executing );
152  _Thread_Resource_count_increment( executing );
153  _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
154  return STATUS_SUCCESSFUL;
155  }
156 
157  if ( owner == executing ) {
158  Status_Control status;
159 
160  status = ( *nested )( the_mutex );
161  _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
162  return status;
163  }
164 
165  return _CORE_mutex_Seize_slow(
166  &the_mutex->Mutex,
167  operations,
168  executing,
169  wait,
170  queue_context
171  );
172 }
173 
174 RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender(
175  CORE_recursive_mutex_Control *the_mutex,
176  const Thread_queue_Operations *operations,
177  Thread_Control *executing,
178  Thread_queue_Context *queue_context
179 )
180 {
181  unsigned int nest_level;
182  Thread_queue_Heads *heads;
183 
184  _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
185 
186  if ( !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing ) ) {
187  _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
188  return STATUS_NOT_OWNER;
189  }
190 
191  nest_level = the_mutex->nest_level;
192 
193  if ( nest_level > 0 ) {
194  the_mutex->nest_level = nest_level - 1;
195  _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
196  return STATUS_SUCCESSFUL;
197  }
198 
199  _Thread_Resource_count_decrement( executing );
200  _CORE_mutex_Set_owner( &the_mutex->Mutex, NULL );
201 
202  heads = the_mutex->Mutex.Wait_queue.Queue.heads;
203 
204  if ( heads == NULL ) {
205  _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
206  return STATUS_SUCCESSFUL;
207  }
208 
210  &the_mutex->Mutex.Wait_queue.Queue,
211  heads,
212  executing,
213  queue_context,
214  operations
215  );
216  return STATUS_SUCCESSFUL;
217 }
218 
219 RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Initialize(
220  CORE_ceiling_mutex_Control *the_mutex,
221  const Scheduler_Control *scheduler,
222  Priority_Control priority_ceiling
223 )
224 {
225  _CORE_recursive_mutex_Initialize( &the_mutex->Recursive );
226  _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority_ceiling );
227 #if defined(RTEMS_SMP)
228  the_mutex->scheduler = scheduler;
229 #endif
230 }
231 
233 _CORE_ceiling_mutex_Get_scheduler(
234  const CORE_ceiling_mutex_Control *the_mutex
235 )
236 {
237 #if defined(RTEMS_SMP)
238  return the_mutex->scheduler;
239 #else
240  return &_Scheduler_Table[ 0 ];
241 #endif
242 }
243 
244 RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Set_priority(
245  CORE_ceiling_mutex_Control *the_mutex,
246  Priority_Control priority_ceiling,
247  Thread_queue_Context *queue_context
248 )
249 {
250  Thread_Control *owner;
251 
252  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
253 
254  if ( owner != NULL ) {
255  _Thread_Wait_acquire( owner, queue_context );
257  owner,
258  &the_mutex->Priority_ceiling,
259  priority_ceiling,
260  false,
261  queue_context
262  );
263  _Thread_Wait_release( owner, queue_context );
264  } else {
265  the_mutex->Priority_ceiling.priority = priority_ceiling;
266  }
267 }
268 
269 RTEMS_INLINE_ROUTINE Priority_Control _CORE_ceiling_mutex_Get_priority(
270  const CORE_ceiling_mutex_Control *the_mutex
271 )
272 {
273  return the_mutex->Priority_ceiling.priority;
274 }
275 
276 RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner(
277  CORE_ceiling_mutex_Control *the_mutex,
278  Thread_Control *owner,
279  Thread_queue_Context *queue_context
280 )
281 {
282  ISR_lock_Context lock_context;
283  Scheduler_Node *scheduler_node;
284  Per_CPU_Control *cpu_self;
285 
286  _Thread_Wait_acquire_default_critical( owner, &lock_context );
287 
288  scheduler_node = _Thread_Scheduler_get_home_node( owner );
289 
290  if (
291  _Priority_Get_priority( &scheduler_node->Wait.Priority )
292  < the_mutex->Priority_ceiling.priority
293  ) {
294  _Thread_Wait_release_default_critical( owner, &lock_context );
295  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
296  return STATUS_MUTEX_CEILING_VIOLATED;
297  }
298 
299  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
300  _Thread_Resource_count_increment( owner );
302  owner,
303  &the_mutex->Priority_ceiling,
304  queue_context
305  );
306  _Thread_Wait_release_default_critical( owner, &lock_context );
307 
308  cpu_self = _Thread_queue_Dispatch_disable( queue_context );
309  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
310  _Thread_Priority_update( queue_context );
311  _Thread_Dispatch_enable( cpu_self );
312  return STATUS_SUCCESSFUL;
313 }
314 
315 RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Seize(
316  CORE_ceiling_mutex_Control *the_mutex,
317  Thread_Control *executing,
318  bool wait,
319  Status_Control ( *nested )( CORE_recursive_mutex_Control * ),
320  Thread_queue_Context *queue_context
321 )
322 {
323  Thread_Control *owner;
324 
325  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
326 
327  owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
328 
329  if ( owner == NULL ) {
330 #if defined(RTEMS_SMP)
331  if (
332  _Thread_Scheduler_get_home( executing )
333  != _CORE_ceiling_mutex_Get_scheduler( the_mutex )
334  ) {
335  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
336  return STATUS_NOT_DEFINED;
337  }
338 #endif
339 
340  _Thread_queue_Context_clear_priority_updates( queue_context );
341  return _CORE_ceiling_mutex_Set_owner(
342  the_mutex,
343  executing,
344  queue_context
345  );
346  }
347 
348  if ( owner == executing ) {
349  Status_Control status;
350 
351  status = ( *nested )( &the_mutex->Recursive );
352  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
353  return status;
354  }
355 
356  return _CORE_mutex_Seize_slow(
357  &the_mutex->Recursive.Mutex,
358  CORE_MUTEX_TQ_OPERATIONS,
359  executing,
360  wait,
361  queue_context
362  );
363 }
364 
365 RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender(
366  CORE_ceiling_mutex_Control *the_mutex,
367  Thread_Control *executing,
368  Thread_queue_Context *queue_context
369 )
370 {
371  unsigned int nest_level;
372  ISR_lock_Context lock_context;
373  Per_CPU_Control *cpu_self;
374  Thread_Control *new_owner;
375 
376  _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
377 
378  if ( !_CORE_mutex_Is_owner( &the_mutex->Recursive.Mutex, executing ) ) {
379  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
380  return STATUS_NOT_OWNER;
381  }
382 
383  nest_level = the_mutex->Recursive.nest_level;
384 
385  if ( nest_level > 0 ) {
386  the_mutex->Recursive.nest_level = nest_level - 1;
387  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
388  return STATUS_SUCCESSFUL;
389  }
390 
391  _Thread_Resource_count_decrement( executing );
392 
393  _Thread_queue_Context_clear_priority_updates( queue_context );
394  _Thread_Wait_acquire_default_critical( executing, &lock_context );
396  executing,
397  &the_mutex->Priority_ceiling,
398  queue_context
399  );
400  _Thread_Wait_release_default_critical( executing, &lock_context );
401 
402  new_owner = _Thread_queue_First_locked(
403  &the_mutex->Recursive.Mutex.Wait_queue,
404  CORE_MUTEX_TQ_OPERATIONS
405  );
406  _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, new_owner );
407 
409  &queue_context->Lock_context.Lock_context
410  );
411 
412  if ( new_owner != NULL ) {
413 #if defined(RTEMS_MULTIPROCESSING)
414  if ( _Objects_Is_local_id( new_owner->Object.id ) )
415 #endif
416  {
417  _Thread_Resource_count_increment( new_owner );
419  new_owner,
420  &the_mutex->Priority_ceiling,
421  queue_context
422  );
423  }
424 
426  &the_mutex->Recursive.Mutex.Wait_queue.Queue,
427  CORE_MUTEX_TQ_OPERATIONS,
428  new_owner,
429  queue_context
430  );
431  } else {
432  _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
433  }
434 
435  _Thread_Priority_update( queue_context );
436  _Thread_Dispatch_enable( cpu_self );
437  return STATUS_SUCCESSFUL;
438 }
439 
442 #ifdef __cplusplus
443 }
444 #endif
445 
446 #endif
447 /* end of include file */
Priority_Node Priority_ceiling
The priority ceiling node for the mutex owner.
Definition: coremutex.h:87
Thread_Control * owner
The thread queue owner.
Definition: threadq.h:426
void _Thread_queue_Object_initialize(Thread_queue_Control *the_thread_queue)
Initializes a thread queue embedded in an object with identifier.
Definition: threadq.c:148
RTEMS_INLINE_ROUTINE void _Thread_Priority_change(Thread_Control *the_thread, Priority_Node *priority_node, Priority_Control new_priority, bool prepend_it, Thread_queue_Context *queue_context)
Changes the thread priority value of the specified thread priority node in the corresponding thread p...
Definition: threadimpl.h:499
Thread_queue_Control Wait_queue
The thread queue of this mutex.
Definition: coremutex.h:57
void _Thread_Priority_update(Thread_queue_Context *queue_context)
Adds a priority node to the corresponding thread priority aggregation.
Definition: threadchangepriority.c:339
RTEMS_INLINE_ROUTINE Thread_Control * _Thread_queue_First_locked(Thread_queue_Control *the_thread_queue, const Thread_queue_Operations *operations)
Returns the first thread on the thread queue if it exists, otherwise NULL.
Definition: threadqimpl.h:971
Thread queue context for the thread queue methods.
Definition: threadq.h:193
unsigned int nest_level
The nest level in case of a recursive seize.
Definition: coremutex.h:72
void _Thread_Priority_add(Thread_Control *the_thread, Priority_Node *priority_node, Thread_queue_Context *queue_context)
Adds the specified thread priority node to the corresponding thread priority aggregation.
Definition: threadchangepriority.c:277
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:65
CORE_recursive_mutex_Control Recursive
The plain recursive mutex.
Definition: coremutex.h:82
Inlined Routines Associated with the Manipulation of the Scheduler.
Priority_Control priority
The priority value of this node.
Definition: priority.h:106
void _Thread_queue_Surrender(Thread_queue_Queue *queue, Thread_queue_Heads *heads, Thread_Control *previous_owner, Thread_queue_Context *queue_context, const Thread_queue_Operations *operations)
Surrenders the thread queue previously owned by the thread to the first enqueued thread.
Definition: threadqenqueue.c:659
Thread queue operations.
Definition: threadq.h:512
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:66
Thread_queue_Queue Queue
The actual thread queue.
Definition: threadq.h:578
Thread_queue_Heads * heads
Lock to protect this thread queue.
Definition: threadq.h:421
Thread queue heads.
Definition: threadq.h:355
void _Thread_Priority_remove(Thread_Control *the_thread, Priority_Node *priority_node, Thread_queue_Context *queue_context)
Removes the specified thread priority node from the corresponding thread priority aggregation...
Definition: threadchangepriority.c:292
RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_default_critical(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Acquires the thread wait default lock inside a critical section (interrupts disabled).
Definition: threadimpl.h:1160
Definition: thread.h:728
Per CPU Core Structure.
Definition: percpu.h:290
void _Thread_queue_Extract_critical(Thread_queue_Queue *queue, const Thread_queue_Operations *operations, Thread_Control *the_thread, Thread_queue_Context *queue_context)
Extracts the thread from the thread queue and unblocks it.
Definition: threadqenqueue.c:599
Thread_queue_Lock_context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:198
Objects_Control Object
Definition: thread.h:730
RTEMS_INLINE_ROUTINE bool _Objects_Is_local_id(Objects_Id id RTEMS_UNUSED)
Definition: objectimpl.h:623
CORE_mutex_Control Mutex
The plain non-recursive mutex.
Definition: coremutex.h:67
Chain Handler API.
The recursive mutex control.
Definition: coremutex.h:63
struct Scheduler_Node::@3976 Wait
Thread wait support block.
Control block used to manage each mutex.
Definition: coremutex.h:51
Scheduler control.
Definition: scheduler.h:266
Scheduler node for per-thread data.
Definition: schedulernode.h:65
const Scheduler_Control _Scheduler_Table[]
Registered schedulers.
Inlined Routines from the Thread Handler.
RTEMS_INLINE_ROUTINE void _Thread_Wait_release(Thread_Control *the_thread, Thread_queue_Context *queue_context)
Releases the thread wait lock and restores the previous interrupt status.
Definition: threadimpl.h:1413
RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_locked(const CORE_mutex_Control *the_mutex)
Is mutex locked.
Definition: coremuteximpl.h:88
RTEMS_INLINE_ROUTINE Per_CPU_Control * _Thread_Dispatch_disable_critical(const ISR_lock_Context *lock_context)
Disables thread dispatching inside a critical section (interrupts disabled).
Definition: threaddispatch.h:175
The recursive mutex control with priority ceiling protocol support.
Definition: coremutex.h:78
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
ISR_lock_Context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:125
CORE Mutex API.
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
Definition: threaddispatch.c:353
RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire(Thread_Control *the_thread, Thread_queue_Context *queue_context)
Acquires the thread wait default lock and disables interrupts.
Definition: threadimpl.h:1352
RTEMS_INLINE_ROUTINE void _Thread_Wait_release_default_critical(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Releases the thread wait default lock inside a critical section (interrupts disabled).
Definition: threadimpl.h:1220
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
Objects_Id id
Definition: objectdata.h:43