source: rtems/cpukit/include/rtems/score/mrspimpl.h @ 4c20da4b

5
Last change on this file since 4c20da4b was 4c20da4b, checked in by Sebastian Huber <sebastian.huber@…>, on 04/04/19 at 07:18:11

doxygen: Rename Score* groups in RTEMSScore*

Update #3706

  • Property mode set to 100644
File size: 9.4 KB
Line 
1/*
2 * Copyright (c) 2014, 2016 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifndef _RTEMS_SCORE_MRSPIMPL_H
16#define _RTEMS_SCORE_MRSPIMPL_H
17
18#include <rtems/score/mrsp.h>
19
20#if defined(RTEMS_SMP)
21
22#include <rtems/score/assert.h>
23#include <rtems/score/status.h>
24#include <rtems/score/threadqimpl.h>
25#include <rtems/score/watchdogimpl.h>
26#include <rtems/score/wkspace.h>
27
28#ifdef __cplusplus
29extern "C" {
30#endif /* __cplusplus */
31
32/**
33 * @addtogroup RTEMSScoreMRSP
34 *
35 * @{
36 */
37
38#define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit
39
40RTEMS_INLINE_ROUTINE void _MRSP_Acquire_critical(
41  MRSP_Control         *mrsp,
42  Thread_queue_Context *queue_context
43)
44{
45  _Thread_queue_Acquire_critical( &mrsp->Wait_queue, queue_context );
46}
47
48RTEMS_INLINE_ROUTINE void _MRSP_Release(
49  MRSP_Control         *mrsp,
50  Thread_queue_Context *queue_context
51)
52{
53  _Thread_queue_Release( &mrsp->Wait_queue, queue_context );
54}
55
56RTEMS_INLINE_ROUTINE Thread_Control *_MRSP_Get_owner(
57  const MRSP_Control *mrsp
58)
59{
60  return mrsp->Wait_queue.Queue.owner;
61}
62
63RTEMS_INLINE_ROUTINE void _MRSP_Set_owner(
64  MRSP_Control   *mrsp,
65  Thread_Control *owner
66)
67{
68  mrsp->Wait_queue.Queue.owner = owner;
69}
70
71RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
72  const MRSP_Control      *mrsp,
73  const Scheduler_Control *scheduler
74)
75{
76  uint32_t scheduler_index;
77
78  scheduler_index = _Scheduler_Get_index( scheduler );
79  return mrsp->ceiling_priorities[ scheduler_index ];
80}
81
82RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
83  MRSP_Control            *mrsp,
84  const Scheduler_Control *scheduler,
85  Priority_Control         new_priority
86)
87{
88  uint32_t scheduler_index;
89
90  scheduler_index = _Scheduler_Get_index( scheduler );
91  mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
92}
93
94RTEMS_INLINE_ROUTINE Status_Control _MRSP_Raise_priority(
95  MRSP_Control         *mrsp,
96  Thread_Control       *thread,
97  Priority_Node        *priority_node,
98  Thread_queue_Context *queue_context
99)
100{
101  Status_Control           status;
102  ISR_lock_Context         lock_context;
103  const Scheduler_Control *scheduler;
104  Priority_Control         ceiling_priority;
105  Scheduler_Node          *scheduler_node;
106
107  _Thread_queue_Context_clear_priority_updates( queue_context );
108  _Thread_Wait_acquire_default_critical( thread, &lock_context );
109
110  scheduler = _Thread_Scheduler_get_home( thread );
111  scheduler_node = _Thread_Scheduler_get_home_node( thread );
112  ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
113
114  if (
115    ceiling_priority
116      <= _Priority_Get_priority( &scheduler_node->Wait.Priority )
117  ) {
118    _Priority_Node_initialize( priority_node, ceiling_priority );
119    _Thread_Priority_add( thread, priority_node, queue_context );
120    status = STATUS_SUCCESSFUL;
121  } else {
122    status = STATUS_MUTEX_CEILING_VIOLATED;
123  }
124
125  _Thread_Wait_release_default_critical( thread, &lock_context );
126  return status;
127}
128
129RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority(
130  Thread_Control       *thread,
131  Priority_Node        *priority_node,
132  Thread_queue_Context *queue_context
133)
134{
135  ISR_lock_Context lock_context;
136
137  _Thread_queue_Context_clear_priority_updates( queue_context );
138  _Thread_Wait_acquire_default_critical( thread, &lock_context );
139  _Thread_Priority_remove( thread, priority_node, queue_context );
140  _Thread_Wait_release_default_critical( thread, &lock_context );
141}
142
143RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority(
144  MRSP_Control   *mrsp,
145  Thread_Control *thread,
146  Priority_Node  *ceiling_priority
147)
148{
149  ISR_lock_Context lock_context;
150
151  _Thread_Wait_acquire_default( thread, &lock_context );
152  _Thread_Priority_replace(
153    thread,
154    ceiling_priority,
155    &mrsp->Ceiling_priority
156  );
157  _Thread_Wait_release_default( thread, &lock_context );
158}
159
160RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership(
161  MRSP_Control         *mrsp,
162  Thread_Control       *executing,
163  Thread_queue_Context *queue_context
164)
165{
166  Status_Control   status;
167  Per_CPU_Control *cpu_self;
168
169  status = _MRSP_Raise_priority(
170    mrsp,
171    executing,
172    &mrsp->Ceiling_priority,
173    queue_context
174  );
175
176  if ( status != STATUS_SUCCESSFUL ) {
177    _MRSP_Release( mrsp, queue_context );
178    return status;
179  }
180
181  _MRSP_Set_owner( mrsp, executing );
182  cpu_self = _Thread_queue_Dispatch_disable( queue_context );
183  _MRSP_Release( mrsp, queue_context );
184  _Thread_Priority_and_sticky_update( executing, 1 );
185  _Thread_Dispatch_enable( cpu_self );
186  return STATUS_SUCCESSFUL;
187}
188
189RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize(
190  MRSP_Control            *mrsp,
191  const Scheduler_Control *scheduler,
192  Priority_Control         ceiling_priority,
193  Thread_Control          *executing,
194  bool                     initially_locked
195)
196{
197  uint32_t scheduler_count = _Scheduler_Count;
198  uint32_t i;
199
200  if ( initially_locked ) {
201    return STATUS_INVALID_NUMBER;
202  }
203
204  mrsp->ceiling_priorities = _Workspace_Allocate(
205    sizeof( *mrsp->ceiling_priorities ) * scheduler_count
206  );
207  if ( mrsp->ceiling_priorities == NULL ) {
208    return STATUS_NO_MEMORY;
209  }
210
211  for ( i = 0 ; i < scheduler_count ; ++i ) {
212    const Scheduler_Control *scheduler_of_index;
213
214    scheduler_of_index = &_Scheduler_Table[ i ];
215
216    if ( scheduler != scheduler_of_index ) {
217      mrsp->ceiling_priorities[ i ] =
218        _Scheduler_Map_priority( scheduler_of_index, 0 );
219    } else {
220      mrsp->ceiling_priorities[ i ] = ceiling_priority;
221    }
222  }
223
224  _Thread_queue_Object_initialize( &mrsp->Wait_queue );
225  return STATUS_SUCCESSFUL;
226}
227
228RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership(
229  MRSP_Control         *mrsp,
230  Thread_Control       *executing,
231  Thread_queue_Context *queue_context
232)
233{
234  Status_Control status;
235  Priority_Node  ceiling_priority;
236
237  status = _MRSP_Raise_priority(
238    mrsp,
239    executing,
240    &ceiling_priority,
241    queue_context
242  );
243
244  if ( status != STATUS_SUCCESSFUL ) {
245    _MRSP_Release( mrsp, queue_context );
246    return status;
247  }
248
249  _Thread_queue_Context_set_deadlock_callout(
250    queue_context,
251    _Thread_queue_Deadlock_status
252  );
253  status = _Thread_queue_Enqueue_sticky(
254    &mrsp->Wait_queue.Queue,
255    MRSP_TQ_OPERATIONS,
256    executing,
257    queue_context
258  );
259
260  if ( status == STATUS_SUCCESSFUL ) {
261    _MRSP_Replace_priority( mrsp, executing, &ceiling_priority );
262  } else {
263    Thread_queue_Context  queue_context;
264    Per_CPU_Control      *cpu_self;
265    int                   sticky_level_change;
266
267    if ( status != STATUS_DEADLOCK ) {
268      sticky_level_change = -1;
269    } else {
270      sticky_level_change = 0;
271    }
272
273    _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
274    _MRSP_Remove_priority( executing, &ceiling_priority, &queue_context );
275    cpu_self = _Thread_Dispatch_disable_critical(
276      &queue_context.Lock_context.Lock_context
277    );
278    _ISR_lock_ISR_enable( &queue_context.Lock_context.Lock_context );
279    _Thread_Priority_and_sticky_update( executing, sticky_level_change );
280    _Thread_Dispatch_enable( cpu_self );
281  }
282
283  return status;
284}
285
286RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize(
287  MRSP_Control         *mrsp,
288  Thread_Control       *executing,
289  bool                  wait,
290  Thread_queue_Context *queue_context
291)
292{
293  Status_Control  status;
294  Thread_Control *owner;
295
296  _MRSP_Acquire_critical( mrsp, queue_context );
297
298  owner = _MRSP_Get_owner( mrsp );
299
300  if ( owner == NULL ) {
301    status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
302  } else if ( owner == executing ) {
303    _MRSP_Release( mrsp, queue_context );
304    status = STATUS_UNAVAILABLE;
305  } else if ( wait ) {
306    status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context );
307  } else {
308    _MRSP_Release( mrsp, queue_context );
309    status = STATUS_UNAVAILABLE;
310  }
311
312  return status;
313}
314
315RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
316  MRSP_Control         *mrsp,
317  Thread_Control       *executing,
318  Thread_queue_Context *queue_context
319)
320{
321  Thread_queue_Heads *heads;
322
323  if ( _MRSP_Get_owner( mrsp ) != executing ) {
324    _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
325    return STATUS_NOT_OWNER;
326  }
327
328  _MRSP_Acquire_critical( mrsp, queue_context );
329
330  _MRSP_Set_owner( mrsp, NULL );
331  _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
332
333  heads = mrsp->Wait_queue.Queue.heads;
334
335  if ( heads == NULL ) {
336    Per_CPU_Control *cpu_self;
337
338    cpu_self = _Thread_Dispatch_disable_critical(
339      &queue_context->Lock_context.Lock_context
340    );
341    _MRSP_Release( mrsp, queue_context );
342    _Thread_Priority_and_sticky_update( executing, -1 );
343    _Thread_Dispatch_enable( cpu_self );
344    return STATUS_SUCCESSFUL;
345  }
346
347  _Thread_queue_Surrender_sticky(
348    &mrsp->Wait_queue.Queue,
349    heads,
350    executing,
351    queue_context,
352    MRSP_TQ_OPERATIONS
353  );
354  return STATUS_SUCCESSFUL;
355}
356
357RTEMS_INLINE_ROUTINE Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp )
358{
359  if ( _MRSP_Get_owner( mrsp ) != NULL ) {
360    return STATUS_RESOURCE_IN_USE;
361  }
362
363  return STATUS_SUCCESSFUL;
364}
365
366RTEMS_INLINE_ROUTINE void _MRSP_Destroy(
367  MRSP_Control         *mrsp,
368  Thread_queue_Context *queue_context
369)
370{
371  _MRSP_Release( mrsp, queue_context );
372  _Thread_queue_Destroy( &mrsp->Wait_queue );
373  _Workspace_Free( mrsp->ceiling_priorities );
374}
375
376/** @} */
377
378#ifdef __cplusplus
379}
380#endif /* __cplusplus */
381
382#endif /* RTEMS_SMP */
383
384#endif /* _RTEMS_SCORE_MRSPIMPL_H */
Note: See TracBrowser for help on using the repository browser.