RTEMS 6.1-rc7
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#endif
353}
354
362static inline const Scheduler_Control *
363_CORE_ceiling_mutex_Get_scheduler(
364 const CORE_ceiling_mutex_Control *the_mutex
365)
366{
367#if defined(RTEMS_SMP)
368 return the_mutex->scheduler;
369#else
370 return &_Scheduler_Table[ 0 ];
371#endif
372}
373
380static inline void _CORE_ceiling_mutex_Set_priority(
382 Priority_Control priority_ceiling
383)
384{
385 Thread_Control *owner;
386
387 owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
388
389 if ( owner != NULL ) {
390 Thread_queue_Context queue_context;
391
392 _Thread_queue_Context_initialize( &queue_context );
393 _Thread_queue_Context_clear_priority_updates( &queue_context );
394 _Thread_Wait_acquire_critical( owner, &queue_context );
395 _Thread_Priority_change(
396 owner,
397 &the_mutex->Priority_ceiling,
398 priority_ceiling,
400 &queue_context
401 );
402 _Thread_Wait_release_critical( owner, &queue_context );
403 } else {
404 the_mutex->Priority_ceiling.priority = priority_ceiling;
405 }
406}
407
415static inline Priority_Control _CORE_ceiling_mutex_Get_priority(
416 const CORE_ceiling_mutex_Control *the_mutex
417)
418{
419 return the_mutex->Priority_ceiling.priority;
420}
421
433static inline Status_Control _CORE_ceiling_mutex_Set_owner(
435 Thread_Control *owner,
436 Thread_queue_Context *queue_context
437)
438{
439 ISR_lock_Context lock_context;
440 Scheduler_Node *scheduler_node;
441 Per_CPU_Control *cpu_self;
442
443 _Thread_Wait_acquire_default_critical( owner, &lock_context );
444
445 scheduler_node = _Thread_Scheduler_get_home_node( owner );
446
447 if (
448 _Priority_Get_priority( &scheduler_node->Wait.Priority )
449 < the_mutex->Priority_ceiling.priority
450 ) {
451 _Thread_Wait_release_default_critical( owner, &lock_context );
452 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
453 return STATUS_MUTEX_CEILING_VIOLATED;
454 }
455
456 _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner );
457 _Thread_Resource_count_increment( owner );
459 owner,
460 &the_mutex->Priority_ceiling,
461 queue_context
462 );
463 _Thread_Wait_release_default_critical( owner, &lock_context );
464
465 cpu_self = _Thread_queue_Dispatch_disable( queue_context );
466 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
467 _Thread_Priority_update( queue_context );
468 _Thread_Dispatch_enable( cpu_self );
469 return STATUS_SUCCESSFUL;
470}
471
487static inline Status_Control _CORE_ceiling_mutex_Seize(
489 Thread_Control *executing,
490 bool wait,
492 Thread_queue_Context *queue_context
493)
494{
495 Thread_Control *owner;
496
497 _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
498
499#if defined(RTEMS_SMP)
500 if (
501 _Thread_Scheduler_get_home( executing )
502 != _CORE_ceiling_mutex_Get_scheduler( the_mutex )
503 ) {
504 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
505 return STATUS_NOT_DEFINED;
506 }
507#endif
508
509 owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex );
510
511 if ( owner == NULL ) {
512 _Thread_queue_Context_clear_priority_updates( queue_context );
513 return _CORE_ceiling_mutex_Set_owner(
514 the_mutex,
515 executing,
516 queue_context
517 );
518 }
519
520 if ( owner == executing ) {
521 Status_Control status;
522
523 status = ( *nested )( &the_mutex->Recursive );
524 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
525 return status;
526 }
527
529 &the_mutex->Recursive.Mutex,
530 CORE_MUTEX_TQ_OPERATIONS,
531 executing,
532 wait,
533 queue_context
534 );
535}
536
547static inline Status_Control _CORE_ceiling_mutex_Surrender(
549 Thread_Control *executing,
550 Thread_queue_Context *queue_context
551)
552{
553 unsigned int nest_level;
554
555 _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context );
556
557 if ( !_CORE_mutex_Is_owner( &the_mutex->Recursive.Mutex, executing ) ) {
558 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
559 return STATUS_NOT_OWNER;
560 }
561
562 nest_level = the_mutex->Recursive.nest_level;
563
564 if ( nest_level > 0 ) {
565 the_mutex->Recursive.nest_level = nest_level - 1;
566 _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context );
567 return STATUS_SUCCESSFUL;
568 }
569
571 &the_mutex->Recursive.Mutex.Wait_queue.Queue,
572 executing,
573 &the_mutex->Priority_ceiling,
574 queue_context,
575 CORE_MUTEX_TQ_OPERATIONS
576 );
577}
578
581#ifdef __cplusplus
582}
583#endif
584
585#endif
586/* 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:691
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:760
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::@4406 Wait
Thread wait support block.
Thread queue context for the thread queue methods.
Definition: threadq.h:216
Thread_queue_Queue Queue
The actual thread queue.
Definition: threadq.h:640
The thread queue operations are used to manage the threads of a thread queue.
Definition: threadq.h:554
Thread_queue_Heads * heads
The thread queue heads.
Definition: threadq.h:451
Thread_Control * owner
The thread queue owner.
Definition: threadq.h:456
Scheduler control.
Definition: scheduler.h:337
Definition: thread.h:837
Thread queue heads.
Definition: threadq.h:385
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...