source: rtems/cpukit/score/include/rtems/score/mrspimpl.h @ b5f1b24

5
Last change on this file since b5f1b24 was 3a27248, checked in by Sebastian Huber <sebastian.huber@…>, on 10/21/16 at 07:23:58

score: First part of new MrsP implementation

Update #2556.

  • Property mode set to 100644
File size: 9.3 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 ScoreMRSP
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( MRSP_Control *mrsp )
57{
58  return mrsp->Wait_queue.Queue.owner;
59}
60
61RTEMS_INLINE_ROUTINE void _MRSP_Set_owner(
62  MRSP_Control   *mrsp,
63  Thread_Control *owner
64)
65{
66  mrsp->Wait_queue.Queue.owner = owner;
67}
68
69RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority(
70  const MRSP_Control      *mrsp,
71  const Scheduler_Control *scheduler
72)
73{
74  uint32_t scheduler_index;
75
76  scheduler_index = _Scheduler_Get_index( scheduler );
77  return mrsp->ceiling_priorities[ scheduler_index ];
78}
79
80RTEMS_INLINE_ROUTINE void _MRSP_Set_priority(
81  MRSP_Control            *mrsp,
82  const Scheduler_Control *scheduler,
83  Priority_Control         new_priority
84)
85{
86  uint32_t scheduler_index;
87
88  scheduler_index = _Scheduler_Get_index( scheduler );
89  mrsp->ceiling_priorities[ scheduler_index ] = new_priority;
90}
91
92RTEMS_INLINE_ROUTINE Status_Control _MRSP_Raise_priority(
93  MRSP_Control         *mrsp,
94  Thread_Control       *thread,
95  Priority_Node        *priority_node,
96  Thread_queue_Context *queue_context
97)
98{
99  Status_Control           status;
100  ISR_lock_Context         lock_context;
101  const Scheduler_Control *scheduler;
102  Priority_Control         ceiling_priority;
103  Scheduler_Node          *own_node;
104
105  _Thread_queue_Context_clear_priority_updates( queue_context );
106  _Thread_Wait_acquire_default_critical( thread, &lock_context );
107
108  scheduler = _Scheduler_Get_own( thread );
109  own_node = _Thread_Scheduler_get_own_node( thread );
110  ceiling_priority = _MRSP_Get_priority( mrsp, scheduler );
111
112  if ( ceiling_priority <= own_node->Wait.Priority.Node.priority ) {
113    _Priority_Node_initialize( priority_node, ceiling_priority );
114    _Thread_Priority_add( thread, priority_node, queue_context );
115    status = STATUS_SUCCESSFUL;
116  } else {
117    status = STATUS_MUTEX_CEILING_VIOLATED;
118  }
119
120  _Thread_Wait_release_default_critical( thread, &lock_context );
121  return status;
122}
123
124RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority(
125  Thread_Control       *thread,
126  Priority_Node        *priority_node,
127  Thread_queue_Context *queue_context
128)
129{
130  ISR_lock_Context  lock_context;
131
132  _Thread_queue_Context_clear_priority_updates( queue_context );
133  _Thread_Wait_acquire_default_critical( thread, &lock_context );
134  _Thread_Priority_remove( thread, priority_node, queue_context );
135  _Thread_Wait_release_default_critical( thread, &lock_context );
136}
137
138RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority(
139  MRSP_Control   *mrsp,
140  Thread_Control *thread,
141  Priority_Node  *ceiling_priority
142)
143{
144  ISR_lock_Context lock_context;
145
146  _Thread_Wait_acquire_default( thread, &lock_context );
147  _Thread_Priority_replace(
148    thread,
149    ceiling_priority,
150    &mrsp->Ceiling_priority
151  );
152  _Thread_Wait_release_default( thread, &lock_context );
153}
154
155RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership(
156  MRSP_Control         *mrsp,
157  Thread_Control       *executing,
158  Thread_queue_Context *queue_context
159)
160{
161  Status_Control   status;
162  Per_CPU_Control *cpu_self;
163
164  status = _MRSP_Raise_priority(
165    mrsp,
166    executing,
167    &mrsp->Ceiling_priority,
168    queue_context
169  );
170
171  if ( status != STATUS_SUCCESSFUL ) {
172    _MRSP_Release( mrsp, queue_context );
173    return status;
174  }
175
176  _MRSP_Set_owner( mrsp, executing );
177  cpu_self = _Thread_Dispatch_disable_critical(
178    &queue_context->Lock_context.Lock_context
179  );
180  _MRSP_Release( mrsp, queue_context );
181  _Thread_Priority_and_sticky_update( executing, 1 );
182  _Thread_Dispatch_enable( cpu_self );
183  return STATUS_SUCCESSFUL;
184}
185
186RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize(
187  MRSP_Control            *mrsp,
188  const Scheduler_Control *scheduler,
189  Priority_Control         ceiling_priority,
190  Thread_Control          *executing,
191  bool                     initially_locked
192)
193{
194  uint32_t scheduler_count = _Scheduler_Count;
195  uint32_t i;
196
197  if ( initially_locked ) {
198    return STATUS_INVALID_NUMBER;
199  }
200
201  mrsp->ceiling_priorities = _Workspace_Allocate(
202    sizeof( *mrsp->ceiling_priorities ) * scheduler_count
203  );
204  if ( mrsp->ceiling_priorities == NULL ) {
205    return STATUS_NO_MEMORY;
206  }
207
208  for ( i = 0 ; i < scheduler_count ; ++i ) {
209    const Scheduler_Control *scheduler_of_cpu;
210
211    scheduler_of_cpu = _Scheduler_Get_by_CPU_index( i );
212
213    if ( scheduler != scheduler_of_cpu ) {
214      mrsp->ceiling_priorities[ i ] =
215        _Scheduler_Map_priority( scheduler_of_cpu, 0 );
216    } else {
217      mrsp->ceiling_priorities[ i ] = ceiling_priority;
218    }
219  }
220
221  _Thread_queue_Initialize( &mrsp->Wait_queue );
222  return STATUS_SUCCESSFUL;
223}
224
225RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership(
226  MRSP_Control         *mrsp,
227  Thread_Control       *executing,
228  Thread_queue_Context *queue_context
229)
230{
231  Status_Control status;
232  Priority_Node  ceiling_priority;
233
234  status = _MRSP_Raise_priority(
235    mrsp,
236    executing,
237    &ceiling_priority,
238    queue_context
239  );
240
241  if ( status != STATUS_SUCCESSFUL ) {
242    _MRSP_Release( mrsp, queue_context );
243    return status;
244  }
245
246  _Thread_queue_Context_set_deadlock_callout(
247    queue_context,
248    _Thread_queue_Deadlock_status
249  );
250  status = _Thread_queue_Enqueue_sticky(
251    &mrsp->Wait_queue.Queue,
252    MRSP_TQ_OPERATIONS,
253    executing,
254    queue_context
255  );
256
257  if ( status == STATUS_SUCCESSFUL ) {
258    _MRSP_Replace_priority( mrsp, executing, &ceiling_priority );
259  } else {
260    Thread_queue_Context  queue_context;
261    Per_CPU_Control      *cpu_self;
262    int                   sticky_level_change;
263
264    if ( status != STATUS_DEADLOCK ) {
265      sticky_level_change = -1;
266    } else {
267      sticky_level_change = 0;
268    }
269
270    _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context );
271    _MRSP_Remove_priority( executing, &ceiling_priority, &queue_context );
272    cpu_self = _Thread_Dispatch_disable_critical(
273      &queue_context.Lock_context.Lock_context
274    );
275    _ISR_lock_ISR_enable( &queue_context.Lock_context.Lock_context );
276    _Thread_Priority_and_sticky_update( executing, sticky_level_change );
277    _Thread_Dispatch_enable( cpu_self );
278  }
279
280  return status;
281}
282
283RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize(
284  MRSP_Control         *mrsp,
285  Thread_Control       *executing,
286  bool                  wait,
287  Thread_queue_Context *queue_context
288)
289{
290  Status_Control  status;
291  Thread_Control *owner;
292
293  _MRSP_Acquire_critical( mrsp, queue_context );
294
295  owner = _MRSP_Get_owner( mrsp );
296
297  if ( owner == NULL ) {
298    status = _MRSP_Claim_ownership( mrsp, executing, queue_context );
299  } else if ( owner == executing ) {
300    _MRSP_Release( mrsp, queue_context );
301    status = STATUS_UNAVAILABLE;
302  } else if ( wait ) {
303    status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context );
304  } else {
305    _MRSP_Release( mrsp, queue_context );
306    status = STATUS_UNAVAILABLE;
307  }
308
309  return status;
310}
311
312RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender(
313  MRSP_Control         *mrsp,
314  Thread_Control       *executing,
315  Thread_queue_Context *queue_context
316)
317{
318  Thread_queue_Heads *heads;
319
320  if ( _MRSP_Get_owner( mrsp ) != executing ) {
321    _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context );
322    return STATUS_NOT_OWNER;
323  }
324
325  _MRSP_Acquire_critical( mrsp, queue_context );
326
327  _MRSP_Set_owner( mrsp, NULL );
328  _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context );
329
330  heads = mrsp->Wait_queue.Queue.heads;
331
332  if ( heads == NULL ) {
333    Per_CPU_Control *cpu_self;
334
335    cpu_self = _Thread_Dispatch_disable_critical(
336      &queue_context->Lock_context.Lock_context
337    );
338    _MRSP_Release( mrsp, queue_context );
339    _Thread_Priority_and_sticky_update( executing, -1 );
340    _Thread_Dispatch_enable( cpu_self );
341    return STATUS_SUCCESSFUL;
342  }
343
344  _Thread_queue_Surrender_sticky(
345    &mrsp->Wait_queue.Queue,
346    heads,
347    executing,
348    queue_context,
349    MRSP_TQ_OPERATIONS
350  );
351  return STATUS_SUCCESSFUL;
352}
353
354RTEMS_INLINE_ROUTINE Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp )
355{
356  if ( _MRSP_Get_owner( mrsp ) != NULL ) {
357    return STATUS_RESOURCE_IN_USE;
358  }
359
360  return STATUS_SUCCESSFUL;
361}
362
363RTEMS_INLINE_ROUTINE void _MRSP_Destroy(
364  MRSP_Control         *mrsp,
365  Thread_queue_Context *queue_context
366)
367{
368  _MRSP_Release( mrsp, queue_context );
369  _Thread_queue_Destroy( &mrsp->Wait_queue );
370  _Workspace_Free( mrsp->ceiling_priorities );
371}
372
373/** @} */
374
375#ifdef __cplusplus
376}
377#endif /* __cplusplus */
378
379#endif /* RTEMS_SMP */
380
381#endif /* _RTEMS_SCORE_MRSPIMPL_H */
Note: See TracBrowser for help on using the repository browser.