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

4.11
Last change on this file since e6b31b27 was e6b31b27, checked in by Joel Sherrill <joel.sherrill@…>, on May 27, 2015 at 3:13:58 PM

Remove use ticks for statistics configure option.

This was obsolete and broken based upon recent time keeping changes.

Thie build option was previously enabled by adding
USE_TICKS_FOR_STATISTICS=1 to the configure command line.

This propagated into the code as preprocessor conditionals
using the RTEMS_USE_TICKS_FOR_STATISTICS conditional.

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