source: rtems/cpukit/rtems/src/ratemonperiod.c @ 7eef54e

4.115
Last change on this file since 7eef54e was 7eef54e, checked in by Joel Sherrill <joel.sherrill@…>, on 07/26/10 at 13:49:01

2010-07-26 Joel Sherrill <joel.sherrilL@…>

  • rtems/src/ratemonperiod.c: Use if not switch since all cases of enum are not valid and switch was generating dead code.
  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 *  Rate Monotonic Manager - Period Blocking and Status
3 *
4 *  COPYRIGHT (c) 1989-2010.
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
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#if HAVE_CONFIG_H
15#include "config.h"
16#endif
17
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
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
96void _Rate_monotonic_Initiate_statistics(
97  Rate_monotonic_Control *the_period
98)
99{
100  Thread_Control *owning_thread = the_period->owner;
101
102  /*
103   *  If using nanosecond statistics, we need to obtain the uptime.
104   */
105  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
106    Timestamp_Control  uptime;
107
108    _TOD_Get_uptime( &uptime );
109  #endif
110
111  /*
112   *  Set the starting point and the CPU time used for the statistics.
113   */
114  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
115    the_period->time_period_initiated = uptime;
116  #else
117    the_period->time_period_initiated = _Watchdog_Ticks_since_boot;
118  #endif
119
120  the_period->cpu_usage_period_initiated = owning_thread->cpu_time_used;
121
122  /*
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.
129   */
130  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
131    if (owning_thread == _Thread_Executing) {
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
143      _Timespec_Add_to( &the_period->cpu_usage_period_initiated, &ran );
144    }
145  #endif
146}
147
148void _Rate_monotonic_Update_statistics(
149  Rate_monotonic_Control    *the_period
150)
151{
152  Thread_CPU_usage_t              executed;
153  Rate_monotonic_Period_time_t    since_last_period;
154  Rate_monotonic_Statistics      *stats;
155  bool                            valid_status;
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  /*
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  /*
173   *  Grab status for time statistics.
174   */
175  valid_status =
176    _Rate_monotonic_Get_status( the_period, &since_last_period, &executed );
177  if (!valid_status)
178    return;
179
180  /*
181   *  Update CPU time
182   */
183  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
184    _Timestamp_Add_to( &stats->total_cpu_time, &executed );
185
186    if ( _Timestamp_Less_than( &executed, &stats->min_cpu_time ) )
187      stats->min_cpu_time = executed;
188
189    if ( _Timestamp_Greater_than( &executed, &stats->max_cpu_time ) )
190      stats->max_cpu_time = executed;
191  #else
192    stats->total_cpu_time  += executed;
193
194    if ( executed < stats->min_cpu_time )
195      stats->min_cpu_time = executed;
196
197    if ( executed > stats->max_cpu_time )
198      stats->max_cpu_time = executed;
199  #endif
200
201  /*
202   *  Update Wall time
203   */
204  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
205    _Timestamp_Add_to( &stats->total_wall_time, &since_last_period );
206
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
213
214    /* Sanity check wall time */
215    if ( since_last_period < executed )
216      since_last_period = executed;
217
218    stats->total_wall_time += since_last_period;
219
220    if ( since_last_period < stats->min_wall_time )
221      stats->min_wall_time = since_last_period;
222
223    if ( since_last_period > stats->max_wall_time )
224      stats->max_wall_time = since_last_period;
225  #endif
226}
227
228
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
241 *    error code       - if unsuccessful
242 */
243
244rtems_status_code rtems_rate_monotonic_period(
245  rtems_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
257  switch ( location ) {
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:
270          case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
271            return_value = RTEMS_TIMEOUT;
272            break;
273          case RATE_MONOTONIC_ACTIVE:
274          default:              /* unreached -- only to remove warnings */
275            return_value = RTEMS_SUCCESSFUL;
276            break;
277        }
278        _Thread_Enable_dispatch();
279        return( return_value );
280      }
281
282      _ISR_Disable( level );
283      if ( the_period->state == RATE_MONOTONIC_INACTIVE ) {
284        _ISR_Enable( level );
285
286        /*
287         *  Baseline statistics information for the beginning of a period.
288         */
289        _Rate_monotonic_Initiate_statistics( the_period );
290
291        the_period->state = RATE_MONOTONIC_ACTIVE;
292        _Watchdog_Initialize(
293          &the_period->Timer,
294          _Rate_monotonic_Timeout,
295          id,
296          NULL
297        );
298
299        the_period->next_length = length;
300
301        _Watchdog_Insert_ticks( &the_period->Timer, length );
302        _Thread_Enable_dispatch();
303        return RTEMS_SUCCESSFUL;
304      }
305
306      if ( the_period->state == RATE_MONOTONIC_ACTIVE ) {
307        /*
308         *  Update statistics from the concluding period.
309         */
310        _Rate_monotonic_Update_statistics( the_period );
311
312        /*
313         *  This tells the _Rate_monotonic_Timeout that this task is
314         *  in the process of blocking on the period and that we
315         *  may be changing the length of the next period.
316         */
317        the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
318        the_period->next_length = length;
319
320        _ISR_Enable( level );
321
322        _Thread_Executing->Wait.id = the_period->Object.id;
323        _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
324
325        /*
326         *  Did the watchdog timer expire while we were actually blocking
327         *  on it?
328         */
329        _ISR_Disable( level );
330          local_state = the_period->state;
331          the_period->state = RATE_MONOTONIC_ACTIVE;
332        _ISR_Enable( level );
333
334        /*
335         *  If it did, then we want to unblock ourself and continue as
336         *  if nothing happen.  The period was reset in the timeout routine.
337         */
338        if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
339          _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
340
341        _Thread_Enable_dispatch();
342        return RTEMS_SUCCESSFUL;
343      }
344
345      if ( the_period->state == RATE_MONOTONIC_EXPIRED ) {
346        /*
347         *  Update statistics from the concluding period
348         */
349        _Rate_monotonic_Update_statistics( the_period );
350
351        _ISR_Enable( level );
352
353        the_period->state = RATE_MONOTONIC_ACTIVE;
354        the_period->next_length = length;
355
356        _Watchdog_Insert_ticks( &the_period->Timer, length );
357        _Thread_Enable_dispatch();
358        return RTEMS_TIMEOUT;
359      }
360
361      /*
362       *  These should never happen so just return invalid Id.
363       *    - RATE_MONOTONIC_OWNER_IS_BLOCKING:
364       *    - RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
365       */
366#if defined(RTEMS_MULTIPROCESSING)
367    case OBJECTS_REMOTE:            /* should never return this */
368#endif
369    case OBJECTS_ERROR:
370      break;
371  }
372
373  return RTEMS_INVALID_ID;
374}
Note: See TracBrowser for help on using the repository browser.