source: rtems/cpukit/rtems/src/ratemonperiod.c @ ba3e987e

4.104.115
Last change on this file since ba3e987e was ba3e987e, checked in by Joel Sherrill <joel.sherrill@…>, on 12/10/09 at 20:23:22

2009-12-10 Joel Sherrill <joel.sherrill@…>

PR 1480/cpukit

  • rtems/src/ratemonperiod.c: Use _Rate_monotonic_Update_statistics() when period is expired, not _Rate_monotonic_Initiate_statistics(). The cound of missed periods was never updated.
  • Property mode set to 100644
File size: 10.4 KB
RevLine 
[5f9b3db]1/*
[e1bce86]2 *  Rate Monotonic Manager - Period Blocking and Status
[5f9b3db]3 *
[94d9bee]4 *  COPYRIGHT (c) 1989-2009.
[5f9b3db]5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
[277cc95]9 *  http://www.rtems.com/license/LICENSE.
[5f9b3db]10 *
11 *  $Id$
12 */
13
[1095ec1]14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
[5f9b3db]18#include <rtems/system.h>
19#include <rtems/rtems/status.h>
20#include <rtems/rtems/support.h>
21#include <rtems/score/isr.h>
22#include <rtems/score/object.h>
23#include <rtems/rtems/ratemon.h>
24#include <rtems/score/thread.h>
25
[eb37f9d]26bool _Rate_monotonic_Get_status(
27  Rate_monotonic_Control        *the_period,
28  Rate_monotonic_Period_time_t  *wall_since_last_period,
29  Thread_CPU_usage_t            *cpu_since_last_period
30)
31{
32  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
33    Timestamp_Control        uptime;
34  #endif
35    Thread_Control          *owning_thread = the_period->owner;
36    Thread_CPU_usage_t       used;
37
38  /*
39   *  Determine elapsed wall time since period initiated.
40   */
41  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
42    _TOD_Get_uptime( &uptime );
43    _Timestamp_Subtract(
44      &the_period->time_period_initiated, &uptime, wall_since_last_period
45    );
46  #else
47    *wall_since_last_period =
48      _Watchdog_Ticks_since_boot - the_period->time_period_initiated;
49  #endif
50
51  /*
52   *  Determine cpu usage since period initiated.
53   */
54  used = owning_thread->cpu_time_used;
55
56  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
57    if (owning_thread == _Thread_Executing) {
58
59      Thread_CPU_usage_t ran;
60
61      /* How much time time since last context switch */
62      _Timestamp_Subtract(
63        &_Thread_Time_of_last_context_switch, &uptime, &ran
64      );
65
66      /* cpu usage += ran */
67      _Timestamp_Add_to( &used, &ran );
68
69      /*
70       *  The cpu usage info was reset while executing.  Can't
71       *  determine a status.
72       */
73      if (_Timestamp_Less_than(&used, &the_period->cpu_usage_period_initiated))
74        return false;
75
76       /* used = current cpu usage - cpu usage at start of period */
77      _Timestamp_Subtract(
78         &the_period->cpu_usage_period_initiated,
79         &used,
80         cpu_since_last_period
81      );
82    }
83  #else
84      /*
85       *  The cpu usage info was reset while executing.  Can't
86       *  determine a status.
87       */
88      if (used < the_period->cpu_usage_period_initiated)
89        return false;
90
91      *cpu_since_last_period = used - the_period->cpu_usage_period_initiated;
92  #endif
93  return true;
94}
95
[94d9bee]96void _Rate_monotonic_Initiate_statistics(
97  Rate_monotonic_Control *the_period
98)
99{
100  Thread_Control *owning_thread = the_period->owner;
101
102  /*
[c6f7e060]103   *  If using nanosecond statistics, we need to obtain the uptime.
[94d9bee]104   */
[c6f7e060]105  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
106    Timestamp_Control  uptime;
[94d9bee]107
108    _TOD_Get_uptime( &uptime );
109  #endif
110
111  /*
112   *  Set the starting point and the CPU time used for the statistics.
113   */
[c6f7e060]114  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
[eb37f9d]115    the_period->time_period_initiated = uptime;
[94d9bee]116  #else
[eb37f9d]117    the_period->time_period_initiated = _Watchdog_Ticks_since_boot;
[94d9bee]118  #endif
119
[eb37f9d]120  the_period->cpu_usage_period_initiated = owning_thread->cpu_time_used;
[94d9bee]121
122  /*
[c6f7e060]123   *  If using nanosecond statistics and the period's thread is currently
124   *  executing, then we need to take into account how much time the
125   *  executing thread has run since the last context switch.  When this
126   *  routine is invoked from rtems_rate_monotonic_period, the owner will
127   *  be the executing thread.  When this routine is invoked from
128   *  _Rate_monotonic_Timeout, it will not.
[94d9bee]129   */
[c6f7e060]130  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
[05c1886]131    if (owning_thread == _Thread_Executing) {
[94d9bee]132
133      rtems_thread_cpu_usage_t ran;
134
135      /*
136       *  Adjust the CPU time used to account for the time since last
137       *  context switch.
138       */
139      _Timespec_Subtract(
140        &_Thread_Time_of_last_context_switch, &uptime, &ran
141      );
142
[eb37f9d]143      _Timespec_Add_to( &the_period->cpu_usage_period_initiated, &ran );
[94d9bee]144    }
145  #endif
146}
147
[e1bce86]148void _Rate_monotonic_Update_statistics(
149  Rate_monotonic_Control    *the_period
150)
151{
[9dc2c8d]152  Thread_CPU_usage_t              executed;
153  Rate_monotonic_Period_time_t    since_last_period;
[eb37f9d]154  Rate_monotonic_Statistics      *stats;
155  bool                            valid_status;
[e1bce86]156
157  /*
158   *  Assume we are only called in states where it is appropriate
159   *  to update the statistics.  This should only be RATE_MONOTONIC_ACTIVE
160   *  and RATE_MONOTONIC_EXPIRED.
161   */
162
163  /*
[94d9bee]164   *  Update the counts.
165   */
166  stats = &the_period->Statistics;
167  stats->count++;
168
169  if ( the_period->state == RATE_MONOTONIC_EXPIRED )
170    stats->missed_count++;
171
172  /*
[eb37f9d]173   *  Grab status for time statistics.
[e1bce86]174   */
[eb37f9d]175  valid_status =
176    _Rate_monotonic_Get_status( the_period, &since_last_period, &executed );
177  if (!valid_status)
178    return;
[e1bce86]179
180  /*
181   *  Update CPU time
182   */
[c6f7e060]183  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
[c16bcc0]184    _Timestamp_Add_to( &stats->total_cpu_time, &executed );
[c3330a8]185
[05c1886]186    if ( _Timestamp_Less_than( &executed, &stats->min_cpu_time ) )
[c3330a8]187      stats->min_cpu_time = executed;
188
[05c1886]189    if ( _Timestamp_Greater_than( &executed, &stats->max_cpu_time ) )
[c3330a8]190      stats->max_cpu_time = executed;
191  #else
[5fa5185]192    stats->total_cpu_time  += executed;
[e1bce86]193
[5fa5185]194    if ( executed < stats->min_cpu_time )
195      stats->min_cpu_time = executed;
[c3330a8]196
[5fa5185]197    if ( executed > stats->max_cpu_time )
198      stats->max_cpu_time = executed;
[c3330a8]199  #endif
[e1bce86]200
201  /*
202   *  Update Wall time
203   */
[c6f7e060]204  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
205    _Timestamp_Add_to( &stats->total_wall_time, &since_last_period );
[e1bce86]206
[c6f7e060]207    if ( _Timestamp_Less_than( &since_last_period, &stats->min_wall_time ) )
208      stats->min_wall_time = since_last_period;
209
210    if ( _Timestamp_Greater_than( &since_last_period, &stats->max_wall_time ) )
211      stats->max_wall_time = since_last_period;
212  #else
[a91e372]213
214    /* Sanity check wall time */
215    if ( since_last_period < executed )
216      since_last_period = executed;
217
[5fa5185]218    stats->total_wall_time += since_last_period;
[c3330a8]219
[5fa5185]220    if ( since_last_period < stats->min_wall_time )
221      stats->min_wall_time = since_last_period;
[c3330a8]222
[5fa5185]223    if ( since_last_period > stats->max_wall_time )
224      stats->max_wall_time = since_last_period;
[c3330a8]225  #endif
[e1bce86]226}
227
228
[5f9b3db]229/*PAGE
230 *
231 *  rtems_rate_monotonic_period
232 *
233 *  This directive allows a thread to manipulate a rate monotonic timer.
234 *
235 *  Input parameters:
236 *    id     - rate monotonic id
237 *    length - length of period (in ticks)
238 *
239 *  Output parameters:
240 *    RTEMS_SUCCESSFUL - if successful
[e980b219]241 *    error code       - if unsuccessful
[5f9b3db]242 */
243
244rtems_status_code rtems_rate_monotonic_period(
245  Objects_Id        id,
246  rtems_interval    length
247)
248{
249  Rate_monotonic_Control              *the_period;
250  Objects_Locations                    location;
251  rtems_status_code                    return_value;
252  rtems_rate_monotonic_period_states   local_state;
253  ISR_Level                            level;
254
255  the_period = _Rate_monotonic_Get( id, &location );
256
[94d9bee]257  switch ( location ) {
[5f9b3db]258    case OBJECTS_LOCAL:
259      if ( !_Thread_Is_executing( the_period->owner ) ) {
260        _Thread_Enable_dispatch();
261        return RTEMS_NOT_OWNER_OF_RESOURCE;
262      }
263
264      if ( length == RTEMS_PERIOD_STATUS ) {
265        switch ( the_period->state ) {
266          case RATE_MONOTONIC_INACTIVE:
267            return_value = RTEMS_NOT_DEFINED;
268            break;
269          case RATE_MONOTONIC_EXPIRED:
[11c16a64]270          case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
[5f9b3db]271            return_value = RTEMS_TIMEOUT;
272            break;
[ebe61382]273          case RATE_MONOTONIC_ACTIVE:
[5f9b3db]274          default:              /* unreached -- only to remove warnings */
[ebe61382]275            return_value = RTEMS_SUCCESSFUL;
[5f9b3db]276            break;
277        }
278        _Thread_Enable_dispatch();
279        return( return_value );
280      }
281
282      _ISR_Disable( level );
283      switch ( the_period->state ) {
[ec2078d]284        case RATE_MONOTONIC_INACTIVE: {
[e1bce86]285
[5f9b3db]286          _ISR_Enable( level );
[e1bce86]287
[94d9bee]288          /*
289           *  Baseline statistics information for the beginning of a period.
290           */
291          _Rate_monotonic_Initiate_statistics( the_period );
[c3330a8]292
[5f9b3db]293          the_period->state = RATE_MONOTONIC_ACTIVE;
294          _Watchdog_Initialize(
295            &the_period->Timer,
296            _Rate_monotonic_Timeout,
297            id,
298            NULL
299          );
300
[bebf0438]301          the_period->next_length = length;
[5f9b3db]302
303          _Watchdog_Insert_ticks( &the_period->Timer, length );
304          _Thread_Enable_dispatch();
305          return RTEMS_SUCCESSFUL;
[ec2078d]306        }
[5f9b3db]307        case RATE_MONOTONIC_ACTIVE:
[e1bce86]308
309          /*
[94d9bee]310           *  Update statistics from the concluding period.
[e1bce86]311           */
312          _Rate_monotonic_Update_statistics( the_period );
313
[5f9b3db]314          /*
315           *  This tells the _Rate_monotonic_Timeout that this task is
[bebf0438]316           *  in the process of blocking on the period and that we
317           *  may be changing the length of the next period.
[5f9b3db]318           */
319          the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
[bebf0438]320          the_period->next_length = length;
321
[5f9b3db]322          _ISR_Enable( level );
323
324          _Thread_Executing->Wait.id = the_period->Object.id;
325          _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
[50f32b11]326
[5f9b3db]327          /*
[50f32b11]328           *  Did the watchdog timer expire while we were actually blocking
[5f9b3db]329           *  on it?
330           */
331          _ISR_Disable( level );
332            local_state = the_period->state;
333            the_period->state = RATE_MONOTONIC_ACTIVE;
334          _ISR_Enable( level );
335
336          /*
337           *  If it did, then we want to unblock ourself and continue as
338           *  if nothing happen.  The period was reset in the timeout routine.
339           */
340          if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
341            _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
342
343          _Thread_Enable_dispatch();
344          return RTEMS_SUCCESSFUL;
345          break;
346
347        case RATE_MONOTONIC_EXPIRED:
[94d9bee]348
[e1bce86]349          /*
350           *  Update statistics from the concluding period
351           */
[ba3e987e]352          _Rate_monotonic_Update_statistics( the_period );
[e1bce86]353
[5f9b3db]354          _ISR_Enable( level );
[e1bce86]355
[5f9b3db]356          the_period->state = RATE_MONOTONIC_ACTIVE;
[bebf0438]357          the_period->next_length = length;
[5f9b3db]358
359          _Watchdog_Insert_ticks( &the_period->Timer, length );
360          _Thread_Enable_dispatch();
361          return RTEMS_TIMEOUT;
362
363        case RATE_MONOTONIC_OWNER_IS_BLOCKING:
364        case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
365          /*
366           *  These should never happen.
367           */
368          break;
369      }
[ebe61382]370
371#if defined(RTEMS_MULTIPROCESSING)
372    case OBJECTS_REMOTE:            /* should never return this */
373#endif
374    case OBJECTS_ERROR:
375      break;
[5f9b3db]376  }
377
[ebe61382]378  return RTEMS_INVALID_ID;
[5f9b3db]379}
Note: See TracBrowser for help on using the repository browser.