RTEMS 6.1-rc5
Loading...
Searching...
No Matches
mrspimpl.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause */
2
12/*
13 * Copyright (C) 2014, 2019 embedded brains GmbH & Co. KG
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#ifndef _RTEMS_SCORE_MRSPIMPL_H
38#define _RTEMS_SCORE_MRSPIMPL_H
39
40#include <rtems/score/mrsp.h>
41
42#if defined(RTEMS_SMP)
43
44#include <rtems/score/assert.h>
45#include <rtems/score/status.h>
48
49#ifdef __cplusplus
50extern "C" {
51#endif /* __cplusplus */
52
59#define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
60
67static inline void _MRSP_Acquire_critical(
68 MRSP_Control *mrsp,
69 Thread_queue_Context *queue_context
70)
71{
72 _Thread_queue_Acquire_critical( &mrsp->Wait_queue, queue_context );
73}
74
81static inline void _MRSP_Release(
82 MRSP_Control *mrsp,
83 Thread_queue_Context *queue_context
84)
85{
86 _Thread_queue_Release( &mrsp->Wait_queue, queue_context );
87}
88
96static inline Thread_Control *_MRSP_Get_owner(
97 const MRSP_Control *mrsp
98)
99{
100 return mrsp->Wait_queue.Queue.owner;
101}
102
109static inline void _MRSP_Set_owner(
110 MRSP_Control *mrsp,
111 Thread_Control *owner
112)
113{
114 mrsp->Wait_queue.Queue.owner = owner;
115}
116
125static inline Priority_Control _MRSP_Get_priority(
126 const MRSP_Control *mrsp,
127 const Scheduler_Control *scheduler
128)
129{
130 uint32_t scheduler_index;
131
132 scheduler_index = _Scheduler_Get_index( scheduler );
133 _Assert( scheduler_index < _Scheduler_Count );
134 return mrsp->ceiling_priorities[ scheduler_index ];
135}
136
144static inline void _MRSP_Set_priority(
145 MRSP_Control *mrsp,
146 const Scheduler_Control *scheduler,
147 Priority_Control new_priority
148)
149{
150 uint32_t scheduler_index;
151
152 scheduler_index = _Scheduler_Get_index( scheduler );
153 _Assert( scheduler_index < _Scheduler_Count );
154 mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
155}
156
170static inline Status_Control _MRSP_Raise_priority(
171 MRSP_Control *mrsp,
172 Thread_Control *thread,
173 Priority_Node *priority_node,
174 Thread_queue_Context *queue_context
175)
176{
177 Status_Control status;
178 ISR_lock_Context lock_context;
179 const Scheduler_Control *scheduler;
180 Priority_Control ceiling_priority;
181 Scheduler_Node *scheduler_node;
182
183 _Thread_queue_Context_clear_priority_updates( queue_context );
184 _Thread_Wait_acquire_default_critical( thread, &lock_context );
185
186 scheduler = _Thread_Scheduler_get_home( thread );
187 scheduler_node = _Thread_Scheduler_get_home_node( thread );
188 ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
189
190 if (
191 ceiling_priority
192 <= _Priority_Get_priority( &scheduler_node->Wait.Priority )
193 ) {
194 _Priority_Node_initialize( priority_node, ceiling_priority );
195 _Thread_Priority_add( thread, priority_node, queue_context );
196 status = STATUS_SUCCESSFUL;
197 } else {
198 status = STATUS_MUTEX_CEILING_VIOLATED;
199 }
200
201 _Thread_Wait_release_default_critical( thread, &lock_context );
202 return status;
203}
204
212static inline void _MRSP_Remove_priority(
213 Thread_Control *thread,
214 Priority_Node *priority_node,
215 Thread_queue_Context *queue_context
216)
217{
218 ISR_lock_Context lock_context;
219
220 _Thread_queue_Context_clear_priority_updates( queue_context );
221 _Thread_Wait_acquire_default_critical( thread, &lock_context );
222 _Thread_Priority_remove( thread, priority_node, queue_context );
223 _Thread_Wait_release_default_critical( thread, &lock_context );
224}
225
234static inline void _MRSP_Replace_priority(
235 MRSP_Control *mrsp,
236 Thread_Control *thread,
237 Priority_Node *ceiling_priority
238)
239{
240 ISR_lock_Context lock_context;
241
242 _Thread_Wait_acquire_default( thread, &lock_context );
243 _Thread_Priority_replace(
244 thread,
245 ceiling_priority,
246 &mrsp->Ceiling_priority
247 );
248 _Thread_Wait_release_default( thread, &lock_context );
249}
250
262static inline Status_Control _MRSP_Claim_ownership(
263 MRSP_Control *mrsp,
264 Thread_Control *executing,
265 Thread_queue_Context *queue_context
266)
267{
268 Status_Control status;
269 Per_CPU_Control *cpu_self;
270
271 status = _MRSP_Raise_priority(
272 mrsp,
273 executing,
274 &mrsp->Ceiling_priority,
275 queue_context
276 );
277
278 if ( status != STATUS_SUCCESSFUL ) {
279 _MRSP_Release( mrsp, queue_context );
280 return status;
281 }
282
283 _MRSP_Set_owner( mrsp, executing );
284 cpu_self = _Thread_queue_Dispatch_disable( queue_context );
285 _MRSP_Release( mrsp, queue_context );
286 _Thread_Priority_update_and_make_sticky( executing );
287 _Thread_Dispatch_enable( cpu_self );
288 return STATUS_SUCCESSFUL;
289}
290
305static inline Status_Control _MRSP_Initialize(
306 MRSP_Control *mrsp,
307 const Scheduler_Control *scheduler,
308 Priority_Control ceiling_priority,
309 Thread_Control *executing,
310 bool initially_locked
311)
312{
313 Thread_queue_Context queue_context;
314 ISR_Level level;
315 size_t scheduler_count;
316 size_t i;
317 Status_Control status;
318
319 scheduler_count = _Scheduler_Count;
320
321 for ( i = 0 ; i < scheduler_count ; ++i ) {
322 const Scheduler_Control *scheduler_of_index;
323
324 scheduler_of_index = &_Scheduler_Table[ i ];
325
326 if ( scheduler != scheduler_of_index ) {
327 mrsp->ceiling_priorities[ i ] =
328 _Scheduler_Map_priority( scheduler_of_index, 0 );
329 } else {
330 mrsp->ceiling_priorities[ i ] = ceiling_priority;
331 }
332 }
333
334 _Thread_queue_Object_initialize( &mrsp->Wait_queue );
335
336 if ( !initially_locked ) {
337 return STATUS_SUCCESSFUL;
338 }
339
340 _Thread_queue_Context_initialize( &queue_context );
341 _Thread_queue_Context_ISR_disable( &queue_context, level );
342 _Thread_queue_Context_set_ISR_level( &queue_context, level );
343 _MRSP_Acquire_critical( mrsp, &queue_context );
344 status = _MRSP_Claim_ownership( mrsp, executing, &queue_context );
345
346 if ( status != STATUS_SUCCESSFUL ) {
347 _Thread_queue_Destroy( &mrsp->Wait_queue );
348 }
349
350 return status;
351}
352
366static inline Status_Control _MRSP_Wait_for_ownership(
367 MRSP_Control *mrsp,
368 Thread_Control *executing,
369 Thread_queue_Context *queue_context
370)
371{
372 Status_Control status;
373 Priority_Node ceiling_priority;
374
375 status = _MRSP_Raise_priority(
376 mrsp,
377 executing,
378 &ceiling_priority,
379 queue_context
380 );
381
382 if ( status != STATUS_SUCCESSFUL ) {
383 _MRSP_Release( mrsp, queue_context );
384 return status;
385 }
386
387 _Thread_queue_Context_set_deadlock_callout(
388 queue_context,
390 );
391 status = _Thread_queue_Enqueue_sticky(
392 &mrsp->Wait_queue.Queue,
393 MRSP_TQ_OPERATIONS,
394 executing,
395 queue_context
396 );
397
398 if ( status == STATUS_SUCCESSFUL ) {
399 _MRSP_Replace_priority( mrsp, executing, &ceiling_priority );
400 } else {
401 Per_CPU_Control *cpu_self;
402
404 _MRSP_Remove_priority( executing, &ceiling_priority, queue_context );
405 cpu_self = _Thread_Dispatch_disable_critical(
406 &queue_context->Lock_context.Lock_context
407 );
409
410 if ( status != STATUS_DEADLOCK ) {
411 _Thread_Priority_update_and_clean_sticky( executing );
412 } else {
413 _Thread_Priority_update_ignore_sticky( executing );
414 }
415
416 _Thread_Dispatch_enable( cpu_self );
417 }
418
419 return status;
420}
421
444static inline Status_Control _MRSP_Seize(
445 MRSP_Control *mrsp,
446 Thread_Control *executing,
447 bool wait,
448 Thread_queue_Context *queue_context
449)
450{
451 Status_Control status;
452 Thread_Control *owner;
453
454 _MRSP_Acquire_critical( mrsp, queue_context );
455
456 owner = _MRSP_Get_owner( mrsp );
457
458 if ( owner == NULL ) {
459 status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
460 } else if ( owner == executing ) {
461 _MRSP_Release( mrsp, queue_context );
462 status = STATUS_DEADLOCK;
463 } else if ( wait ) {
464 status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context );
465 } else {
466 _MRSP_Release( mrsp, queue_context );
467 status = STATUS_UNAVAILABLE;
468 }
469
470 return status;
471}
472
483static inline Status_Control _MRSP_Surrender(
484 MRSP_Control *mrsp,
485 Thread_Control *executing,
486 Thread_queue_Context *queue_context
487)
488{
489 Thread_queue_Heads *heads;
490
491 if ( _MRSP_Get_owner( mrsp ) != executing ) {
493 return STATUS_NOT_OWNER;
494 }
495
496 _MRSP_Acquire_critical( mrsp, queue_context );
497
498 _MRSP_Set_owner( mrsp, NULL );
499 _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
500
501 heads = mrsp->Wait_queue.Queue.heads;
502
503 if ( heads == NULL ) {
504 Per_CPU_Control *cpu_self;
505
506 cpu_self = _Thread_Dispatch_disable_critical(
507 &queue_context->Lock_context.Lock_context
508 );
509 _MRSP_Release( mrsp, queue_context );
510 _Thread_Priority_update_and_clean_sticky( executing );
511 _Thread_Dispatch_enable( cpu_self );
512 return STATUS_SUCCESSFUL;
513 }
514
515 _Thread_queue_Surrender_sticky(
516 &mrsp->Wait_queue.Queue,
517 heads,
518 executing,
519 queue_context,
520 MRSP_TQ_OPERATIONS
521 );
522 return STATUS_SUCCESSFUL;
523}
524
535static inline Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp )
536{
537 if ( _MRSP_Get_owner( mrsp ) != NULL ) {
538 return STATUS_RESOURCE_IN_USE;
539 }
540
541 return STATUS_SUCCESSFUL;
542}
543
550static inline void _MRSP_Destroy(
551 MRSP_Control *mrsp,
552 Thread_queue_Context *queue_context
553)
554{
555 _MRSP_Release( mrsp, queue_context );
556 _Thread_queue_Destroy( &mrsp->Wait_queue );
557}
558
561#ifdef __cplusplus
562}
563#endif /* __cplusplus */
564
565#endif /* RTEMS_SMP */
566
567#endif /* _RTEMS_SCORE_MRSPIMPL_H */
This header file provides the interfaces of the Assert Handler.
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG and static analysis runs.
Definition: assert.h:96
#define _ISR_lock_ISR_enable(_context)
Restores the saved interrupt state of the ISR lock context.
Definition: isrlock.h:385
#define _ISR_lock_ISR_disable(_context)
Disables interrupts and saves the previous interrupt state in the ISR lock context.
Definition: isrlock.h:364
uint32_t ISR_Level
Definition: isrlevel.h:60
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:91
#define _Scheduler_Count
This constant contains the count of configured schedulers.
Definition: scheduler.h:395
const Scheduler_Control _Scheduler_Table[]
This table contains the configured schedulers.
Status_Control
Status codes.
Definition: status.h:111
void _Thread_queue_Deadlock_status(Thread_Control *the_thread)
Sets the thread wait return code to STATUS_DEADLOCK.
Definition: threadqenqueue.c:396
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_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_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:347
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
This header file provides interfaces of the Multiprocessor Resource Sharing Protocol (MrsP) which are...
This header file provides the interfaces of the Operation Status Support.
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:94
Per CPU Core Structure.
Definition: percpu.h:384
The priority node to build up a priority aggregation.
Definition: priority.h:112
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_Lock_context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:221
ISR_lock_Context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:148
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 Queue Handler which are only used by the implement...
This header file provides interfaces of the Watchdog Handler which are only used by the implementatio...