RTEMS 7.0-rc1
Loading...
Searching...
No Matches
coremuteximpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * COPYRIGHT (c) 1989-2009.
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#ifndef _RTEMS_SCORE_COREMUTEXIMPL_H
39#define _RTEMS_SCORE_COREMUTEXIMPL_H
40
44#include <rtems/score/status.h>
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
58#define CORE_MUTEX_TQ_OPERATIONS &_Thread_queue_Operations_priority
59
60#define CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS \
61 &_Thread_queue_Operations_priority_inherit
62
68static inline void _CORE_mutex_Initialize(
69 CORE_mutex_Control *the_mutex
70)
71{
73}
74
80static inline void _CORE_mutex_Destroy( CORE_mutex_Control *the_mutex )
81{
82 _Thread_queue_Destroy( &the_mutex->Wait_queue );
83}
84
91static inline void _CORE_mutex_Acquire_critical(
92 CORE_mutex_Control *the_mutex,
93 Thread_queue_Context *queue_context
94)
95{
96 _Thread_queue_Acquire_critical( &the_mutex->Wait_queue, queue_context );
97}
98
105static inline void _CORE_mutex_Release(
106 CORE_mutex_Control *the_mutex,
107 Thread_queue_Context *queue_context
108)
109{
110 _Thread_queue_Release( &the_mutex->Wait_queue, queue_context );
111}
112
120static inline Thread_Control *_CORE_mutex_Get_owner(
121 const CORE_mutex_Control *the_mutex
122)
123{
124 return the_mutex->Wait_queue.Queue.owner;
125}
126
138static inline bool _CORE_mutex_Is_locked(
139 const CORE_mutex_Control *the_mutex
140)
141{
142 return _CORE_mutex_Get_owner( the_mutex ) != NULL;
143}
144
158 CORE_mutex_Control *the_mutex,
159 const Thread_queue_Operations *operations,
160 Thread_Control *executing,
161 bool wait,
162 Thread_queue_Context *queue_context
163);
164
171static inline void _CORE_mutex_Set_owner(
172 CORE_mutex_Control *the_mutex,
173 Thread_Control *owner
174)
175{
176 the_mutex->Wait_queue.Queue.owner = owner;
177}
178
188static inline bool _CORE_mutex_Is_owner(
189 const CORE_mutex_Control *the_mutex,
190 const Thread_Control *the_thread
191)
192{
193 return _CORE_mutex_Get_owner( the_mutex ) == the_thread;
194}
195
201static inline void _CORE_recursive_mutex_Initialize(
203)
204{
205 _CORE_mutex_Initialize( &the_mutex->Mutex );
206 the_mutex->nest_level = 0;
207}
208
216static inline Status_Control _CORE_recursive_mutex_Seize_nested(
218)
219{
220 ++the_mutex->nest_level;
221 return STATUS_SUCCESSFUL;
222}
223
239static inline Status_Control _CORE_recursive_mutex_Seize(
241 const Thread_queue_Operations *operations,
242 Thread_Control *executing,
243 bool wait,
245 Thread_queue_Context *queue_context
246)
247{
248 Thread_Control *owner;
249
250 _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
251
252 owner = _CORE_mutex_Get_owner( &the_mutex->Mutex );
253
254 if ( owner == NULL ) {
255 _CORE_mutex_Set_owner( &the_mutex->Mutex, executing );
256 _Thread_Resource_count_increment( executing );
257 _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
258 return STATUS_SUCCESSFUL;
259 }
260
261 if ( owner == executing ) {
262 Status_Control status;
263
264 status = ( *nested )( the_mutex );
265 _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
266 return status;
267 }
268
270 &the_mutex->Mutex,
271 operations,
272 executing,
273 wait,
274 queue_context
275 );
276}
277
289static inline Status_Control _CORE_recursive_mutex_Surrender(
291 const Thread_queue_Operations *operations,
292 Thread_Control *executing,
293 Thread_queue_Context *queue_context
294)
295{
296 unsigned int nest_level;
297 Thread_queue_Heads *heads;
298
299 _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
300
301 if ( !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing ) ) {
302 _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
303 return STATUS_NOT_OWNER;
304 }
305
306 nest_level = the_mutex->nest_level;
307
308 if ( nest_level > 0 ) {
309 the_mutex->nest_level = nest_level - 1;
310 _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
311 return STATUS_SUCCESSFUL;
312 }
313
314 _Thread_Resource_count_decrement( executing );
315 _CORE_mutex_Set_owner( &the_mutex->Mutex, NULL );
316
317 heads = the_mutex->Mutex.Wait_queue.Queue.heads;
318
319 if ( heads == NULL ) {
320 _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
321 return STATUS_SUCCESSFUL;
322 }
323
325 &the_mutex->Mutex.Wait_queue.Queue,
326 heads,
327 executing,
328 queue_context,
329 operations
330 );
331 return STATUS_SUCCESSFUL;
332}
333
342static inline void _CORE_ceiling_mutex_Initialize(
344 const Scheduler_Control *scheduler,
345 Priority_Control priority_ceiling
346)
347{
348 _CORE_recursive_mutex_Initialize( &the_mutex->Recursive );
349 _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority_ceiling );
350#if defined(RTEMS_SMP)
351 the_mutex->scheduler = scheduler;
352#else
353 (void) scheduler;
354#endif
355}
356
364static inline const Scheduler_Control *
365_CORE_ceiling_mutex_Get_scheduler(
366 const CORE_ceiling_mutex_Control *the_mutex
367)
368{
369#if defined(RTEMS_SMP)
370 return the_mutex->scheduler;
371#else
372 (void) the_mutex;
373 return &_Scheduler_Table[ 0 ];
374#endif
375}
376
383static inline void _CORE_ceiling_mutex_Set_priority(
385 Priority_Control priority_ceiling
386)
387{
388 Thread_Control *owner;
389
390 owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
391
392 if ( owner != NULL ) {
393 Thread_queue_Context queue_context;
394
395 _Thread_queue_Context_initialize( &queue_context );
396 _Thread_queue_Context_clear_priority_updates( &queue_context );
397 _Thread_Wait_acquire_critical( owner, &queue_context );
398 _Thread_Priority_change(
399 owner,
400 &the_mutex->Priority_ceiling,
401 priority_ceiling,
403 &queue_context
404 );
405 _Thread_Wait_release_critical( owner, &queue_context );
406 } else {
407 the_mutex->Priority_ceiling.priority = priority_ceiling;
408 }
409}
410
418static inline Priority_Control _CORE_ceiling_mutex_Get_priority(
419 const CORE_ceiling_mutex_Control *the_mutex
420)
421{
422 return the_mutex->Priority_ceiling.priority;
423}
424
436static inline Status_Control _CORE_ceiling_mutex_Set_owner(
438 Thread_Control *owner,
439 Thread_queue_Context *queue_context
440)
441{
442 ISR_lock_Context lock_context;
443 Scheduler_Node *scheduler_node;
444 Per_CPU_Control *cpu_self;
445
446 _Thread_Wait_acquire_default_critical( owner, &lock_context );
447
448 scheduler_node = _Thread_Scheduler_get_home_node( owner );
449
450 if (
451 _Priority_Get_priority( &scheduler_node->Wait.Priority )
452 < the_mutex->Priority_ceiling.priority
453 ) {
454 _Thread_Wait_release_default_critical( owner, &lock_context );
455 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
456 return STATUS_MUTEX_CEILING_VIOLATED;
457 }
458
459 _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
460 _Thread_Resource_count_increment( owner );
462 owner,
463 &the_mutex->Priority_ceiling,
464 queue_context
465 );
466 _Thread_Wait_release_default_critical( owner, &lock_context );
467
468 cpu_self = _Thread_queue_Dispatch_disable( queue_context );
469 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
470 _Thread_Priority_update( queue_context );
471 _Thread_Dispatch_enable( cpu_self );
472 return STATUS_SUCCESSFUL;
473}
474
490static inline Status_Control _CORE_ceiling_mutex_Seize(
492 Thread_Control *executing,
493 bool wait,
495 Thread_queue_Context *queue_context
496)
497{
498 Thread_Control *owner;
499
500 _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
501
502#if defined(RTEMS_SMP)
503 if (
504 _Thread_Scheduler_get_home( executing )
505 != _CORE_ceiling_mutex_Get_scheduler( the_mutex )
506 ) {
507 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
508 return STATUS_NOT_DEFINED;
509 }
510#endif
511
512 owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
513
514 if ( owner == NULL ) {
515 _Thread_queue_Context_clear_priority_updates( queue_context );
516 return _CORE_ceiling_mutex_Set_owner(
517 the_mutex,
518 executing,
519 queue_context
520 );
521 }
522
523 if ( owner == executing ) {
524 Status_Control status;
525
526 status = ( *nested )( &the_mutex->Recursive );
527 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
528 return status;
529 }
530
532 &the_mutex->Recursive.Mutex,
533 CORE_MUTEX_TQ_OPERATIONS,
534 executing,
535 wait,
536 queue_context
537 );
538}
539
550static inline Status_Control _CORE_ceiling_mutex_Surrender(
552 Thread_Control *executing,
553 Thread_queue_Context *queue_context
554)
555{
556 unsigned int nest_level;
557
558 _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
559
560 if ( !_CORE_mutex_Is_owner( &the_mutex->Recursive.Mutex, executing ) ) {
561 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
562 return STATUS_NOT_OWNER;
563 }
564
565 nest_level = the_mutex->Recursive.nest_level;
566
567 if ( nest_level > 0 ) {
568 the_mutex->Recursive.nest_level = nest_level - 1;
569 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
570 return STATUS_SUCCESSFUL;
571 }
572
574 &the_mutex->Recursive.Mutex.Wait_queue.Queue,
575 executing,
576 &the_mutex->Priority_ceiling,
577 queue_context,
578 CORE_MUTEX_TQ_OPERATIONS
579 );
580}
581
584#ifdef __cplusplus
585}
586#endif
587
588#endif
589/* end of include file */
This header file provides interfaces of the Chain Handler which are only used by the implementation.
This header file provides interfaces of the Mutex Handler which are used by the implementation and th...
Status_Control _CORE_mutex_Seize_slow(CORE_mutex_Control *the_mutex, const Thread_queue_Operations *operations, Thread_Control *executing, bool wait, Thread_queue_Context *queue_context)
Seize the mutex slowly.
Definition: coremutexseize.c:47
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:91
@ PRIORITY_GROUP_LAST
Priority group last option requests that the priority node is inserted as the last node into its prio...
Definition: priorityimpl.h:73
const Scheduler_Control _Scheduler_Table[]
This table contains the configured schedulers.
Status_Control
Status codes.
Definition: status.h:111
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:698
Status_Control _Thread_queue_Surrender_priority_ceiling(Thread_queue_Queue *queue, Thread_Control *executing, Priority_Node *ceiling_priority, 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:767
void _Thread_queue_Object_initialize(Thread_queue_Control *the_thread_queue)
Initializes a thread queue embedded in an object with identifier.
Definition: threadq.c:170
void _Thread_Priority_update(Thread_queue_Context *queue_context)
Updates the priority of all threads in the set.
Definition: threadchangepriority.c:396
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:332
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
This header file provides interfaces of the Scheduler Handler which are only used by the implementati...
This header file provides the interfaces of the Operation Status Support.
The recursive mutex control with priority ceiling protocol support.
Definition: coremutex.h:101
Priority_Node Priority_ceiling
The priority ceiling node for the mutex owner.
Definition: coremutex.h:110
CORE_recursive_mutex_Control Recursive
The plain recursive mutex.
Definition: coremutex.h:105
Control block used to manage each mutex.
Definition: coremutex.h:74
Thread_queue_Control Wait_queue
The thread queue of this mutex.
Definition: coremutex.h:80
The recursive mutex control.
Definition: coremutex.h:86
unsigned int nest_level
The nest level in case of a recursive seize.
Definition: coremutex.h:95
CORE_mutex_Control Mutex
The plain non-recursive mutex.
Definition: coremutex.h:90
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:94
Per CPU Core Structure.
Definition: percpu.h:384
Priority_Control priority
The priority value of this node.
Definition: priority.h:124
Scheduler node for per-thread data.
Definition: schedulernode.h:94
struct Scheduler_Node::@4366 Wait
Thread wait support block.
Thread queue context for the thread queue methods.
Definition: threadq.h:217
Thread_queue_Queue Queue
The actual thread queue.
Definition: threadq.h:649
The thread queue operations are used to manage the threads of a thread queue.
Definition: threadq.h:563
Thread_queue_Heads * heads
The thread queue heads.
Definition: threadq.h:460
Thread_Control * owner
The thread queue owner.
Definition: threadq.h:465
Scheduler control.
Definition: scheduler.h:337
Definition: thread.h:837
Thread queue heads.
Definition: threadq.h:394
This header file provides interfaces of the Thread Handler which are only used by the implementation.
This header file provides interfaces of the Thread Queue Handler which are only used by the implement...