RTEMS  5.1
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 
53 RTEMS_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 
67 RTEMS_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 
82 RTEMS_INLINE_ROUTINE Thread_Control *_MRSP_Get_owner(
83  const MRSP_Control *mrsp
84 )
85 {
86  return mrsp->Wait_queue.Queue.owner;
87 }
88 
95 RTEMS_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 
111 RTEMS_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 
129 RTEMS_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 
154 RTEMS_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 
196 RTEMS_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 
218 RTEMS_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 
246 RTEMS_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 
289 RTEMS_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 
334 RTEMS_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 
406 RTEMS_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 
445 RTEMS_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 
497 RTEMS_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 
512 RTEMS_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 */
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 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 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
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:70
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
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
Inlined Routines in the Watchdog Handler.
#define _ISR_lock_ISR_enable(_context)
Restores the saved interrupt state of the ISR lock context.
Definition: isrlock.h:419
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 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
Information for the Assert Handler.
Thread queue heads.
Definition: threadq.h:360
RTEMS_INLINE_ROUTINE uint32_t _Scheduler_Get_index(const Scheduler_Control *scheduler)
Gets the index of the scheduler.
Definition: schedulerimpl.h:834
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
void _Thread_queue_Deadlock_status(Thread_Control *the_thread)
Sets the thread wait return code to STATUS_DEADLOCK.
Definition: threadqenqueue.c:370
Definition: thread.h:732
RTEMS_INLINE_ROUTINE void _Thread_queue_Destroy(Thread_queue_Control *the_thread_queue)
Destroys the thread queue.
Definition: threadqimpl.h:1378
Per CPU Core Structure.
Definition: percpu.h:347
#define _Scheduler_Count
Count of registered schedulers.
Definition: scheduler.h:325
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
Thread_queue_Lock_context Lock_context
The lock context for the thread queue acquire and release operations.
Definition: threadq.h:203
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...
Definition: threadchangepriority.c:323
const Scheduler_Control _Scheduler_Table[]
Registered schedulers.
void _Thread_Dispatch_enable(Per_CPU_Control *cpu_self)
Enables thread dispatching.
Definition: threaddispatch.c:362
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
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 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
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
Definitions for Multiprocessor Resource Sharing Protocol (MrsP).
Scheduler control.
Definition: scheduler.h:269
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:398
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
struct Scheduler_Node::@3980 Wait
Thread wait support block.
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 Priority_Control _Priority_Get_priority(const Priority_Aggregation *aggregation)
Gets the priority aggregation's priority.
Definition: priorityimpl.h:270
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
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
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
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:66
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
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77