source: rtems/cpukit/rtems/src/ratemonperiod.c @ 300f6a48

5
Last change on this file since 300f6a48 was 300f6a48, checked in by Sebastian Huber <sebastian.huber@…>, on 06/22/16 at 15:09:23

score: Rework thread priority management

Add priority nodes which contribute to the overall thread priority.

The actual priority of a thread is now an aggregation of priority nodes.
The thread priority aggregation for the home scheduler instance of a
thread consists of at least one priority node, which is normally the
real priority of the thread. The locking protocols (e.g. priority
ceiling and priority inheritance), rate-monotonic period objects and the
POSIX sporadic server add, change and remove priority nodes.

A thread changes its priority now immediately, e.g. priority changes are
not deferred until the thread releases its last resource.

Replace the _Thread_Change_priority() function with

  • _Thread_Priority_perform_actions(),
  • _Thread_Priority_add(),
  • _Thread_Priority_remove(),
  • _Thread_Priority_change(), and
  • _Thread_Priority_update().

Update #2412.
Update #2556.

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief Rate Monotonic Support
5 *  @ingroup ClassicRateMon
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-2010.
10 *  On-Line Applications Research Corporation (OAR).
11 *  Copyright (c) 2016 embedded brains GmbH.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <rtems/rtems/ratemonimpl.h>
23#include <rtems/score/schedulerimpl.h>
24#include <rtems/score/todimpl.h>
25
26bool _Rate_monotonic_Get_status(
27  const Rate_monotonic_Control *the_period,
28  Timestamp_Control            *wall_since_last_period,
29  Timestamp_Control            *cpu_since_last_period
30)
31{
32  Timestamp_Control        uptime;
33  Thread_Control          *owning_thread = the_period->owner;
34  Timestamp_Control        used;
35
36  /*
37   *  Determine elapsed wall time since period initiated.
38   */
39  _TOD_Get_uptime( &uptime );
40  _Timestamp_Subtract(
41    &the_period->time_period_initiated, &uptime, wall_since_last_period
42  );
43
44  /*
45   *  Determine cpu usage since period initiated.
46   */
47  _Thread_Get_CPU_time_used( owning_thread, &used );
48
49  /*
50   *  The cpu usage info was reset while executing.  Can't
51   *  determine a status.
52   */
53  if ( _Timestamp_Less_than( &used, &the_period->cpu_usage_period_initiated ) )
54    return false;
55
56   /* used = current cpu usage - cpu usage at start of period */
57  _Timestamp_Subtract(
58    &the_period->cpu_usage_period_initiated,
59    &used,
60    cpu_since_last_period
61  );
62
63  return true;
64}
65
66static void _Rate_monotonic_Release_job(
67  Rate_monotonic_Control *the_period,
68  Thread_Control         *owner,
69  rtems_interval          next_length,
70  ISR_lock_Context       *lock_context
71)
72{
73  Per_CPU_Control      *cpu_self;
74  Thread_queue_Context  queue_context;
75  uint64_t              deadline;
76
77  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
78
79  deadline = _Watchdog_Per_CPU_insert_relative(
80    &the_period->Timer,
81    cpu_self,
82    next_length
83  );
84  _Scheduler_Release_job(
85    owner,
86    &the_period->Priority,
87    deadline,
88    &queue_context
89  );
90
91  _Rate_monotonic_Release( the_period, lock_context );
92  _Thread_Priority_update( &queue_context );
93  _Thread_Dispatch_enable( cpu_self );
94}
95
96void _Rate_monotonic_Restart(
97  Rate_monotonic_Control *the_period,
98  Thread_Control         *owner,
99  ISR_lock_Context       *lock_context
100)
101{
102  /*
103   *  Set the starting point and the CPU time used for the statistics.
104   */
105  _TOD_Get_uptime( &the_period->time_period_initiated );
106  _Thread_Get_CPU_time_used( owner, &the_period->cpu_usage_period_initiated );
107
108  _Rate_monotonic_Release_job(
109    the_period,
110    owner,
111    the_period->next_length,
112    lock_context
113  );
114}
115
116static void _Rate_monotonic_Update_statistics(
117  Rate_monotonic_Control    *the_period
118)
119{
120  Timestamp_Control          executed;
121  Timestamp_Control          since_last_period;
122  Rate_monotonic_Statistics *stats;
123  bool                       valid_status;
124
125  /*
126   *  Assume we are only called in states where it is appropriate
127   *  to update the statistics.  This should only be RATE_MONOTONIC_ACTIVE
128   *  and RATE_MONOTONIC_EXPIRED.
129   */
130
131  /*
132   *  Update the counts.
133   */
134  stats = &the_period->Statistics;
135  stats->count++;
136
137  if ( the_period->state == RATE_MONOTONIC_EXPIRED )
138    stats->missed_count++;
139
140  /*
141   *  Grab status for time statistics.
142   */
143  valid_status =
144    _Rate_monotonic_Get_status( the_period, &since_last_period, &executed );
145  if (!valid_status)
146    return;
147
148  /*
149   *  Update CPU time
150   */
151  _Timestamp_Add_to( &stats->total_cpu_time, &executed );
152
153  if ( _Timestamp_Less_than( &executed, &stats->min_cpu_time ) )
154    stats->min_cpu_time = executed;
155
156  if ( _Timestamp_Greater_than( &executed, &stats->max_cpu_time ) )
157    stats->max_cpu_time = executed;
158
159  /*
160   *  Update Wall time
161   */
162  _Timestamp_Add_to( &stats->total_wall_time, &since_last_period );
163
164  if ( _Timestamp_Less_than( &since_last_period, &stats->min_wall_time ) )
165    stats->min_wall_time = since_last_period;
166
167  if ( _Timestamp_Greater_than( &since_last_period, &stats->max_wall_time ) )
168    stats->max_wall_time = since_last_period;
169}
170
171static rtems_status_code _Rate_monotonic_Get_status_for_state(
172  rtems_rate_monotonic_period_states state
173)
174{
175  switch ( state ) {
176    case RATE_MONOTONIC_INACTIVE:
177      return RTEMS_NOT_DEFINED;
178    case RATE_MONOTONIC_EXPIRED:
179      return RTEMS_TIMEOUT;
180    default:
181      _Assert( state == RATE_MONOTONIC_ACTIVE );
182      return RTEMS_SUCCESSFUL;
183  }
184}
185
186static rtems_status_code _Rate_monotonic_Activate(
187  Rate_monotonic_Control *the_period,
188  rtems_interval          length,
189  Thread_Control         *executing,
190  ISR_lock_Context       *lock_context
191)
192{
193  the_period->state = RATE_MONOTONIC_ACTIVE;
194  the_period->next_length = length;
195  _Rate_monotonic_Restart( the_period, executing, lock_context );
196  return RTEMS_SUCCESSFUL;
197}
198
199static rtems_status_code _Rate_monotonic_Block_while_active(
200  Rate_monotonic_Control *the_period,
201  rtems_interval          length,
202  Thread_Control         *executing,
203  ISR_lock_Context       *lock_context
204)
205{
206  Per_CPU_Control *cpu_self;
207  bool             success;
208
209  /*
210   *  Update statistics from the concluding period.
211   */
212  _Rate_monotonic_Update_statistics( the_period );
213
214  /*
215   *  This tells the _Rate_monotonic_Timeout that this task is
216   *  in the process of blocking on the period and that we
217   *  may be changing the length of the next period.
218   */
219  the_period->next_length = length;
220  executing->Wait.return_argument = the_period;
221  _Thread_Wait_flags_set( executing, RATE_MONOTONIC_INTEND_TO_BLOCK );
222
223  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
224  _Rate_monotonic_Release( the_period, lock_context );
225
226  _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD );
227
228  success = _Thread_Wait_flags_try_change_acquire(
229    executing,
230    RATE_MONOTONIC_INTEND_TO_BLOCK,
231    RATE_MONOTONIC_BLOCKED
232  );
233  if ( !success ) {
234    _Assert(
235      _Thread_Wait_flags_get( executing ) == RATE_MONOTONIC_READY_AGAIN
236    );
237    _Thread_Unblock( executing );
238  }
239
240  _Thread_Dispatch_enable( cpu_self );
241  return RTEMS_SUCCESSFUL;
242}
243
244static rtems_status_code _Rate_monotonic_Block_while_expired(
245  Rate_monotonic_Control *the_period,
246  rtems_interval          length,
247  Thread_Control         *executing,
248  ISR_lock_Context       *lock_context
249)
250{
251  /*
252   *  Update statistics from the concluding period
253   */
254  _Rate_monotonic_Update_statistics( the_period );
255
256  the_period->state = RATE_MONOTONIC_ACTIVE;
257  the_period->next_length = length;
258
259  _Rate_monotonic_Release_job( the_period, executing, length, lock_context );
260  return RTEMS_TIMEOUT;
261}
262
263rtems_status_code rtems_rate_monotonic_period(
264  rtems_id       id,
265  rtems_interval length
266)
267{
268  Rate_monotonic_Control            *the_period;
269  ISR_lock_Context                   lock_context;
270  Thread_Control                    *executing;
271  rtems_status_code                  status;
272  rtems_rate_monotonic_period_states state;
273
274  the_period = _Rate_monotonic_Get( id, &lock_context );
275  if ( the_period == NULL ) {
276    return RTEMS_INVALID_ID;
277  }
278
279  executing = _Thread_Executing;
280  if ( executing != the_period->owner ) {
281    _ISR_lock_ISR_enable( &lock_context );
282    return RTEMS_NOT_OWNER_OF_RESOURCE;
283  }
284
285  _Rate_monotonic_Acquire_critical( the_period, &lock_context );
286
287  state = the_period->state;
288
289  if ( length == RTEMS_PERIOD_STATUS ) {
290    status = _Rate_monotonic_Get_status_for_state( state );
291    _Rate_monotonic_Release( the_period, &lock_context );
292  } else {
293    switch ( state ) {
294      case RATE_MONOTONIC_ACTIVE:
295        status = _Rate_monotonic_Block_while_active(
296          the_period,
297          length,
298          executing,
299          &lock_context
300        );
301        break;
302      case RATE_MONOTONIC_INACTIVE:
303        status = _Rate_monotonic_Activate(
304          the_period,
305          length,
306          executing,
307          &lock_context
308        );
309        break;
310      default:
311        _Assert( state == RATE_MONOTONIC_EXPIRED );
312        status = _Rate_monotonic_Block_while_expired(
313          the_period,
314          length,
315          executing,
316          &lock_context
317        );
318        break;
319    }
320  }
321
322  return status;
323}
Note: See TracBrowser for help on using the repository browser.