RTEMS
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
36 extern "C" {
37 #endif /* __cplusplus */
38 
45 #define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
46 
54  MRSP_Control *mrsp,
55  Thread_queue_Context *queue_context
56 )
57 {
58  _Thread_queue_Acquire_critical( &mrsp->Wait_queue, queue_context );
59 }
60 
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 
96  MRSP_Control *mrsp,
97  Thread_Control *owner
98 )
99 {
100  mrsp->Wait_queue.Queue.owner = owner;
101 }
102 
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 
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 
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 
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 
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 
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 
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 
318  return STATUS_SUCCESSFUL;
319 }
320 
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  );
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 
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 
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 
478  &mrsp->Wait_queue.Queue,
479  heads,
480  executing,
481  queue_context,
482  MRSP_TQ_OPERATIONS
483  );
484  return STATUS_SUCCESSFUL;
485 }
486 
498 {
499  if ( _MRSP_Get_owner( mrsp ) != NULL ) {
500  return STATUS_RESOURCE_IN_USE;
501  }
502 
503  return STATUS_SUCCESSFUL;
504 }
505 
513  MRSP_Control *mrsp,
514  Thread_queue_Context *queue_context
515 )
516 {
517  _MRSP_Release( mrsp, queue_context );
519 }
520 
523 #ifdef __cplusplus
524 }
525 #endif /* __cplusplus */
526 
527 #endif /* RTEMS_SMP */
528 
529 #endif /* _RTEMS_SCORE_MRSPIMPL_H */
static __inline__ 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
Thread_Control * owner
The thread queue owner.
Definition: threadq.h:431
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:70
static __inline__ Status_Control _MRSP_Initialize(MRSP_Control *mrsp, const Scheduler_Control *scheduler, Priority_Control ceiling_priority, Thread_Control *executing, bool initially_locked)
Initializes a MrsP control.
Definition: mrspimpl.h:289
static __inline__ Per_CPU_Control * _Thread_queue_Dispatch_disable(Thread_queue_Context *queue_context)
Disables dispatching in a critical section.
Definition: threadqimpl.h:429
Thread queue context for the thread queue methods.
Definition: threadq.h:198
The priority node to build up a priority aggregation.
Definition: priority.h:98
static __inline__ 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
static __inline__ const Scheduler_Control * _Thread_Scheduler_get_home(const Thread_Control *the_thread)
Gets the home scheduler of the thread.
Definition: threadimpl.h:1419
Inlined Routines in the Watchdog Handler.
Priority_Node Ceiling_priority
The ceiling priority used by the owner thread.
Definition: mrsp.h:71
Thread_queue_Control Wait_queue
The thread queue to manage ownership and waiting threads.
Definition: mrsp.h:66
static __inline__ Priority_Control _Scheduler_Map_priority(const Scheduler_Control *scheduler, Priority_Control priority)
Maps a thread priority from the user domain to the scheduler domain.
#define _ISR_lock_ISR_enable(_context)
Restores the saved interrupt state of the ISR lock context.
Definition: isrlock.h:416
void _Thread_Priority_and_sticky_update(Thread_Control *the_thread, int sticky_level_change)
Updates the priority of the thread and changes it sticky level.
Priority_Control ceiling_priorities[RTEMS_ZERO_LENGTH_ARRAY]
One ceiling priority per scheduler instance.
Definition: mrsp.h:76
static __inline__ Priority_Control _MRSP_Get_priority(const MRSP_Control *mrsp, const Scheduler_Control *scheduler)
Gets priority of the MrsP control.
Definition: mrspimpl.h:111
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
static __inline__ Thread_Control * _MRSP_Get_owner(const MRSP_Control *mrsp)
Gets owner of the MrsP control.
Definition: mrspimpl.h:82
static __inline__ Status_Control _MRSP_Raise_priority(MRSP_Control *mrsp, Thread_Control *thread, Priority_Node *priority_node, Thread_queue_Context *queue_context)
Adds the priority to the given thread.
Definition: mrspimpl.h:154
static __inline__ Status_Control _MRSP_Seize(MRSP_Control *mrsp, Thread_Control *executing, bool wait, Thread_queue_Context *queue_context)
Seizes the MrsP control.
Definition: mrspimpl.h:406
Information for the Assert Handler.
Thread_queue_Queue Queue
The actual thread queue.
Definition: threadq.h:583
Thread_queue_Heads * heads
The thread queue heads.
Definition: threadq.h:426
Thread queue heads.
Definition: threadq.h:360
static __inline__ Per_CPU_Control * _Thread_Dispatch_disable_critical(const ISR_lock_Context *lock_context)
Disables thread dispatching inside a critical section (interrupts disabled).
static __inline__ void _MRSP_Acquire_critical(MRSP_Control *mrsp, Thread_queue_Context *queue_context)
Acquires critical accordingt to MrsP.
Definition: mrspimpl.h:53
void _Thread_queue_Deadlock_status(Thread_Control *the_thread)
Sets the thread wait return code to STATUS_DEADLOCK.
static __inline__ void _MRSP_Release(MRSP_Control *mrsp, Thread_queue_Context *queue_context)
Releases according to MrsP.
Definition: mrspimpl.h:67
static __inline__ void _MRSP_Replace_priority(MRSP_Control *mrsp, Thread_Control *thread, Priority_Node *ceiling_priority)
Replaces the given priority node with the ceiling priority of the MrsP control.
Definition: mrspimpl.h:218
static __inline__ Status_Control _MRSP_Wait_for_ownership(MRSP_Control *mrsp, Thread_Control *executing, Thread_queue_Context *queue_context)
Waits for the ownership of the MrsP control.
Definition: mrspimpl.h:334
Per CPU Core Structure.
Definition: percpu.h:347
static __inline__ void _MRSP_Remove_priority(Thread_Control *thread, Priority_Node *priority_node, Thread_queue_Context *queue_context)
Removes the priority from the given thread.
Definition: mrspimpl.h:196
static __inline__ Scheduler_Node * _Thread_Scheduler_get_home_node(const Thread_Control *the_thread)
Gets the scheduler&#39;s home node.
Definition: threadimpl.h:1438
Thread_queue_Lock_context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:203
MrsP control block.
Definition: mrsp.h:62
Constants and Structures Associated with the Manipulation of Objects.
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...
static __inline__ Status_Control _MRSP_Surrender(MRSP_Control *mrsp, Thread_Control *executing, Thread_queue_Context *queue_context)
Surrenders the MrsP control.
Definition: mrspimpl.h:445
const Scheduler_Control _Scheduler_Table[]
This table contains the configured schedulers.
static __inline__ 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:1699
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
static __inline__ 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_Surrender_sticky(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.
struct Scheduler_Node::@20 Wait
Thread wait support block.
Definitions for Multiprocessor Resource Sharing Protocol (MrsP).
static __inline__ Status_Control _MRSP_Claim_ownership(MRSP_Control *mrsp, Thread_Control *executing, Thread_queue_Context *queue_context)
Claims ownership of the MrsP control.
Definition: mrspimpl.h:246
const size_t _Scheduler_Count
This constant contains the count of configured schedulers.
Scheduler control.
Definition: scheduler.h:264
Scheduler node for per-thread data.
Definition: schedulernode.h:79
#define _ISR_lock_ISR_disable(_context)
Disables interrupts and saves the previous interrupt state in the ISR lock context.
Definition: isrlock.h:392
static __inline__ Priority_Control _Priority_Get_priority(const Priority_Aggregation *aggregation)
Gets the priority aggregation&#39;s priority.
Definition: priorityimpl.h:270
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...
static __inline__ 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:1658
static __inline__ Status_Control _MRSP_Can_destroy(MRSP_Control *mrsp)
Checks if the MrsP control can be destroyed.
Definition: mrspimpl.h:497
static __inline__ void _MRSP_Destroy(MRSP_Control *mrsp, Thread_queue_Context *queue_context)
Destroys the MrsP control.
Definition: mrspimpl.h:512
static __inline__ void _MRSP_Set_priority(MRSP_Control *mrsp, const Scheduler_Control *scheduler, Priority_Control new_priority)
Sets priority of the MrsP control.
Definition: mrspimpl.h:129
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:130
static __inline__ void _Thread_queue_Destroy(Thread_queue_Control *the_thread_queue)
Destroys the thread queue.
Definition: threadqimpl.h:1378
#define RTEMS_INLINE_ROUTINE
Gives a hint to the compiler in a function declaration to inline this function.
Definition: basedefs.h:683
Status_Control _Thread_queue_Enqueue_sticky(Thread_queue_Queue *queue, const Thread_queue_Operations *operations, Thread_Control *the_thread, Thread_queue_Context *queue_context)
Enqueues the thread on the thread queue and busy waits for dequeue.
static __inline__ 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:1718
void _Thread_queue_Release(Thread_queue_Control *the_thread_queue, Thread_queue_Context *queue_context)
Releases the thread queue control and enables interrupts.
Definition: threadq.c:118
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.
static __inline__ 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:1734
static __inline__ uint32_t _Scheduler_Get_index(const Scheduler_Control *scheduler)
Gets the index of the scheduler.
static __inline__ void _MRSP_Set_owner(MRSP_Control *mrsp, Thread_Control *owner)
Sets owner of the MrsP control.
Definition: mrspimpl.h:95
static __inline__ void _Priority_Node_initialize(Priority_Node *node, Priority_Control priority)
Initializes the priority node to the given priority.
Definition: priorityimpl.h:156