RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
mrspimpl.h
Go to the documentation of this file.
1
9/*
10 * Copyright (c) 2014, 2019 embedded brains GmbH. All rights reserved.
11 *
12 * embedded brains GmbH
13 * Dornierstr. 4
14 * 82178 Puchheim
15 * Germany
16 * <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#ifndef _RTEMS_SCORE_MRSPIMPL_H
24#define _RTEMS_SCORE_MRSPIMPL_H
25
26#include <rtems/score/mrsp.h>
27
28#if defined(RTEMS_SMP)
29
30#include <rtems/score/assert.h>
31#include <rtems/score/status.h>
34
35#ifdef __cplusplus
36extern "C" {
37#endif /* __cplusplus */
38
45#define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
46
53RTEMS_INLINE_ROUTINE void _MRSP_Acquire_critical(
54 MRSP_Control *mrsp,
55 Thread_queue_Context *queue_context
56)
57{
58 _Thread_queue_Acquire_critical( &mrsp->Wait_queue, queue_context );
59}
60
67RTEMS_INLINE_ROUTINE void _MRSP_Release(
68 MRSP_Control *mrsp,
69 Thread_queue_Context *queue_context
70)
71{
72 _Thread_queue_Release( &mrsp->Wait_queue, queue_context );
73}
74
83 const MRSP_Control *mrsp
84)
85{
86 return mrsp->Wait_queue.Queue.owner;
87}
88
95RTEMS_INLINE_ROUTINE void _MRSP_Set_owner(
96 MRSP_Control *mrsp,
97 Thread_Control *owner
98)
99{
100 mrsp->Wait_queue.Queue.owner = owner;
101}
102
111RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
112 const MRSP_Control *mrsp,
113 const Scheduler_Control *scheduler
114)
115{
116 uint32_t scheduler_index;
117
118 scheduler_index = _Scheduler_Get_index( scheduler );
119 return mrsp->ceiling_priorities[ scheduler_index ];
120}
121
129RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
130 MRSP_Control *mrsp,
131 const Scheduler_Control *scheduler,
132 Priority_Control new_priority
133)
134{
135 uint32_t scheduler_index;
136
137 scheduler_index = _Scheduler_Get_index( scheduler );
138 mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
139}
140
154RTEMS_INLINE_ROUTINE Status_Control _MRSP_Raise_priority(
155 MRSP_Control *mrsp,
156 Thread_Control *thread,
157 Priority_Node *priority_node,
158 Thread_queue_Context *queue_context
159)
160{
161 Status_Control status;
162 ISR_lock_Context lock_context;
163 const Scheduler_Control *scheduler;
164 Priority_Control ceiling_priority;
165 Scheduler_Node *scheduler_node;
166
168 _Thread_Wait_acquire_default_critical( thread, &lock_context );
169
170 scheduler = _Thread_Scheduler_get_home( thread );
171 scheduler_node = _Thread_Scheduler_get_home_node( thread );
172 ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
173
174 if (
175 ceiling_priority
176 <= _Priority_Get_priority( &scheduler_node->Wait.Priority )
177 ) {
178 _Priority_Node_initialize( priority_node, ceiling_priority );
179 _Thread_Priority_add( thread, priority_node, queue_context );
180 status = STATUS_SUCCESSFUL;
181 } else {
182 status = STATUS_MUTEX_CEILING_VIOLATED;
183 }
184
185 _Thread_Wait_release_default_critical( thread, &lock_context );
186 return status;
187}
188
196RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority(
197 Thread_Control *thread,
198 Priority_Node *priority_node,
199 Thread_queue_Context *queue_context
200)
201{
202 ISR_lock_Context lock_context;
203
205 _Thread_Wait_acquire_default_critical( thread, &lock_context );
206 _Thread_Priority_remove( thread, priority_node, queue_context );
207 _Thread_Wait_release_default_critical( thread, &lock_context );
208}
209
218RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority(
219 MRSP_Control *mrsp,
220 Thread_Control *thread,
221 Priority_Node *ceiling_priority
222)
223{
224 ISR_lock_Context lock_context;
225
226 _Thread_Wait_acquire_default( thread, &lock_context );
228 thread,
229 ceiling_priority,
230 &mrsp->Ceiling_priority
231 );
232 _Thread_Wait_release_default( thread, &lock_context );
233}
234
246RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership(
247 MRSP_Control *mrsp,
248 Thread_Control *executing,
249 Thread_queue_Context *queue_context
250)
251{
252 Status_Control status;
253 Per_CPU_Control *cpu_self;
254
255 status = _MRSP_Raise_priority(
256 mrsp,
257 executing,
258 &mrsp->Ceiling_priority,
259 queue_context
260 );
261
262 if ( status != STATUS_SUCCESSFUL ) {
263 _MRSP_Release( mrsp, queue_context );
264 return status;
265 }
266
267 _MRSP_Set_owner( mrsp, executing );
268 cpu_self = _Thread_queue_Dispatch_disable( queue_context );
269 _MRSP_Release( mrsp, queue_context );
270 _Thread_Priority_and_sticky_update( executing, 1 );
271 _Thread_Dispatch_enable( cpu_self );
272 return STATUS_SUCCESSFUL;
273}
274
289RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize(
290 MRSP_Control *mrsp,
291 const Scheduler_Control *scheduler,
292 Priority_Control ceiling_priority,
293 Thread_Control *executing,
294 bool initially_locked
295)
296{
297 uint32_t scheduler_count = _Scheduler_Count;
298 uint32_t i;
299
300 if ( initially_locked ) {
301 return STATUS_INVALID_NUMBER;
302 }
303
304 for ( i = 0 ; i < scheduler_count ; ++i ) {
305 const Scheduler_Control *scheduler_of_index;
306
307 scheduler_of_index = &_Scheduler_Table[ i ];
308
309 if ( scheduler != scheduler_of_index ) {
310 mrsp->ceiling_priorities[ i ] =
311 _Scheduler_Map_priority( scheduler_of_index, 0 );
312 } else {
313 mrsp->ceiling_priorities[ i ] = ceiling_priority;
314 }
315 }
316
317 _Thread_queue_Object_initialize( &mrsp->Wait_queue );
318 return STATUS_SUCCESSFUL;
319}
320
334RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership(
335 MRSP_Control *mrsp,
336 Thread_Control *executing,
337 Thread_queue_Context *queue_context
338)
339{
340 Status_Control status;
341 Priority_Node ceiling_priority;
342
343 status = _MRSP_Raise_priority(
344 mrsp,
345 executing,
346 &ceiling_priority,
347 queue_context
348 );
349
350 if ( status != STATUS_SUCCESSFUL ) {
351 _MRSP_Release( mrsp, queue_context );
352 return status;
353 }
354
356 queue_context,
358 );
359 status = _Thread_queue_Enqueue_sticky(
360 &mrsp->Wait_queue.Queue,
361 MRSP_TQ_OPERATIONS,
362 executing,
363 queue_context
364 );
365
366 if ( status == STATUS_SUCCESSFUL ) {
367 _MRSP_Replace_priority( mrsp, executing, &ceiling_priority );
368 } else {
369 Thread_queue_Context queue_context;
370 Per_CPU_Control *cpu_self;
371 int sticky_level_change;
372
373 if ( status != STATUS_DEADLOCK ) {
374 sticky_level_change = -1;
375 } else {
376 sticky_level_change = 0;
377 }
378
380 _MRSP_Remove_priority( executing, &ceiling_priority, &queue_context );
382 &queue_context.Lock_context.Lock_context
383 );
385 _Thread_Priority_and_sticky_update( executing, sticky_level_change );
386 _Thread_Dispatch_enable( cpu_self );
387 }
388
389 return status;
390}
391
406RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize(
407 MRSP_Control *mrsp,
408 Thread_Control *executing,
409 bool wait,
410 Thread_queue_Context *queue_context
411)
412{
413 Status_Control status;
414 Thread_Control *owner;
415
416 _MRSP_Acquire_critical( mrsp, queue_context );
417
418 owner = _MRSP_Get_owner( mrsp );
419
420 if ( owner == NULL ) {
421 status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
422 } else if ( owner == executing ) {
423 _MRSP_Release( mrsp, queue_context );
424 status = STATUS_UNAVAILABLE;
425 } else if ( wait ) {
426 status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context );
427 } else {
428 _MRSP_Release( mrsp, queue_context );
429 status = STATUS_UNAVAILABLE;
430 }
431
432 return status;
433}
434
445RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
446 MRSP_Control *mrsp,
447 Thread_Control *executing,
448 Thread_queue_Context *queue_context
449)
450{
451 Thread_queue_Heads *heads;
452
453 if ( _MRSP_Get_owner( mrsp ) != executing ) {
455 return STATUS_NOT_OWNER;
456 }
457
458 _MRSP_Acquire_critical( mrsp, queue_context );
459
460 _MRSP_Set_owner( mrsp, NULL );
461 _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
462
463 heads = mrsp->Wait_queue.Queue.heads;
464
465 if ( heads == NULL ) {
466 Per_CPU_Control *cpu_self;
467
469 &queue_context->Lock_context.Lock_context
470 );
471 _MRSP_Release( mrsp, queue_context );
472 _Thread_Priority_and_sticky_update( executing, -1 );
473 _Thread_Dispatch_enable( cpu_self );
474 return STATUS_SUCCESSFUL;
475 }
476
477 _Thread_queue_Surrender_sticky(
478 &mrsp->Wait_queue.Queue,
479 heads,
480 executing,
481 queue_context,
482 MRSP_TQ_OPERATIONS
483 );
484 return STATUS_SUCCESSFUL;
485}
486
497RTEMS_INLINE_ROUTINE Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp )
498{
499 if ( _MRSP_Get_owner( mrsp ) != NULL ) {
500 return STATUS_RESOURCE_IN_USE;
501 }
502
503 return STATUS_SUCCESSFUL;
504}
505
512RTEMS_INLINE_ROUTINE void _MRSP_Destroy(
513 MRSP_Control *mrsp,
514 Thread_queue_Context *queue_context
515)
516{
517 _MRSP_Release( mrsp, queue_context );
518 _Thread_queue_Destroy( &mrsp->Wait_queue );
519}
520
523#ifdef __cplusplus
524}
525#endif /* __cplusplus */
526
527#endif /* RTEMS_SMP */
528
529#endif /* _RTEMS_SCORE_MRSPIMPL_H */
Information for the Assert Handler.
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:66
#define _ISR_lock_ISR_enable(_context)
Restores the saved interrupt state of the ISR lock context.
Definition: isrlock.h:419
#define _ISR_lock_ISR_disable(_context)
Disables interrupts and saves the previous interrupt state in the ISR lock context.
Definition: isrlock.h:398
RTEMS_INLINE_ROUTINE void _Priority_Node_initialize(Priority_Node *node, Priority_Control priority)
Initializes the priority node to the given priority.
Definition: priorityimpl.h:156
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:70
RTEMS_INLINE_ROUTINE Priority_Control _Priority_Get_priority(const Priority_Aggregation *aggregation)
Gets the priority aggregation's priority.
Definition: priorityimpl.h:270
RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Map_priority(const Scheduler_Control *scheduler, Priority_Control priority)
Maps a thread priority from the user domain to the scheduler domain.
Definition: schedulerimpl.h:453
RTEMS_INLINE_ROUTINE uint32_t _Scheduler_Get_index(const Scheduler_Control *scheduler)
Gets the index of the scheduler.
Definition: schedulerimpl.h:834
#define _Scheduler_Count
Count of registered schedulers.
Definition: scheduler.h:325
const Scheduler_Control _Scheduler_Table[]
Registered schedulers.
RTEMS_INLINE_ROUTINE void _Thread_queue_Release(Thread_queue_Control *the_thread_queue, Thread_queue_Context *queue_context)
Releases the thread queue control and enables interrupts.
Definition: threadqimpl.h:787
RTEMS_INLINE_ROUTINE void _Thread_queue_Acquire_critical(Thread_queue_Control *the_thread_queue, Thread_queue_Context *queue_context)
Acquires the thread queue control in a critical section.
Definition: threadqimpl.h:681
RTEMS_INLINE_ROUTINE Per_CPU_Control * _Thread_queue_Dispatch_disable(Thread_queue_Context *queue_context)
Disables dispatching in a critical section.
Definition: threadqimpl.h:429
RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(Thread_queue_Control *the_thread_queue)
Destroys the thread queue.
Definition: threadqimpl.h:1378
RTEMS_INLINE_ROUTINE void _Thread_queue_Context_set_deadlock_callout(Thread_queue_Context *queue_context, Thread_queue_Deadlock_callout deadlock_callout)
Sets the deadlock callout in the thread queue context.
Definition: threadqimpl.h:324
RTEMS_INLINE_ROUTINE 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
void _Thread_queue_Deadlock_status(Thread_Control *the_thread)
Sets the thread wait return code to STATUS_DEADLOCK.
Definition: threadqenqueue.c:370
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 Scheduler_Node * _Thread_Scheduler_get_home_node(const Thread_Control *the_thread)
Gets the scheduler's home node.
Definition: threadimpl.h:1412
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:1692
void _Thread_Priority_replace(Thread_Control *the_thread, Priority_Node *victim_node, Priority_Node *replacement_node)
Replaces the victim priority node with the replacement priority node in the corresponding thread prio...
Definition: threadchangepriority.c:323
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:179
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
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
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
Definition: threaddispatch.c:362
RTEMS_INLINE_ROUTINE void _Thread_Wait_release_default(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Releases the thread wait default lock and restores the previous interrupt status.
Definition: threadimpl.h:1708
RTEMS_INLINE_ROUTINE const Scheduler_Control * _Thread_Scheduler_get_home(const Thread_Control *the_thread)
Gets the home scheduler of the thread.
Definition: threadimpl.h:1393
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:1632
RTEMS_INLINE_ROUTINE void _Thread_Wait_acquire_default(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Acquires the thread wait default lock and disables interrupts.
Definition: threadimpl.h:1673
Definitions for Multiprocessor Resource Sharing Protocol (MrsP).
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
Per CPU Core Structure.
Definition: percpu.h:347
The priority node to build up a priority aggregation.
Definition: priority.h:98
Scheduler node for per-thread data.
Definition: schedulernode.h:79
struct Scheduler_Node::@3981 Wait
Thread wait support block.
Thread queue context for the thread queue methods.
Definition: threadq.h:198
Thread_queue_Lock_context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:203
ISR_lock_Context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:130
Scheduler control.
Definition: scheduler.h:269
Definition: thread.h:732
Thread queue heads.
Definition: threadq.h:360
Constants and Structures Associated with the Manipulation of Objects.
Inlined Routines in the Watchdog Handler.