source: rtems/cpukit/rtems/src/ratemonperiod.c @ 8677cf7

4.104.114.84.95
Last change on this file since 8677cf7 was 8677cf7, checked in by Joel Sherrill <joel.sherrill@…>, on 09/06/07 at 22:09:18

2007-09-06 Joel Sherrill <joel.sherrill@…>

  • rtems/src/ratemonperiod.c: Clean up.
  • rtems/src/ratemonreportstatistics.c: Clarify period statistics output.
  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*
2 *  Rate Monotonic Manager - Period Blocking and Status
3 *
4 *  COPYRIGHT (c) 1989-2007.
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#if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
26    defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
27  #include <rtems/score/timespec.h>
28  extern struct timespec _Thread_Time_of_last_context_switch;
29#endif
30
31void _Rate_monotonic_Update_statistics(
32  Rate_monotonic_Control    *the_period
33)
34{
35  rtems_rate_monotonic_period_statistics *stats;
36  #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
37    struct timespec                       executed;
38  #else
39    uint32_t                              ticks_executed_since_last_period;
40  #endif
41  #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
42    struct timespec                       period_start;
43    struct timespec                       since_last_period;
44  #else
45    uint32_t                              ticks_since_last_period;
46  #endif
47  #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
48      defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
49    struct timespec  uptime;
50
51    /*
52     * Obtain the current time since boot
53     */
54    _TOD_Get_uptime( &uptime );
55  #endif
56
57  /*
58   *  Assume we are only called in states where it is appropriate
59   *  to update the statistics.  This should only be RATE_MONOTONIC_ACTIVE
60   *  and RATE_MONOTONIC_EXPIRED.
61   */
62
63  /*
64   *  Grab basic information
65   */
66
67  #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
68    period_start               = the_period->time_at_period;
69    _Timespec_Subtract( &period_start, &uptime, &since_last_period );
70    the_period->time_at_period = uptime;
71  #else
72    ticks_since_last_period =
73        _Watchdog_Ticks_since_boot - the_period->time_at_period;
74    the_period->time_at_period = _Watchdog_Ticks_since_boot;
75  #endif
76
77  #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
78    {
79      struct timespec ran, used;
80       
81      /* Grab CPU usage when the thread got switched in */
82      used = _Thread_Executing->cpu_time_used;
83
84      /* How much time time since last context switch */
85      _Timespec_Subtract(&_Thread_Time_of_last_context_switch, &uptime, &ran);
86
87      /* executed += ran */
88      _Timespec_Add_to( &used, &ran );
89
90       /* executed = current cpu usage - value at start of period */
91      _Timespec_Subtract(
92         &the_period->owner_executed_at_period,
93         &used,
94         &executed
95      );
96    }
97  #else
98      ticks_executed_since_last_period = the_period->owner->ticks_executed -
99        the_period->owner_ticks_executed_at_period;
100  #endif
101
102  /*
103   *  Now update the statistics
104   */
105
106  stats = &the_period->Statistics;
107  stats->count++;
108
109
110  if ( the_period->state == RATE_MONOTONIC_EXPIRED )
111    stats->missed_count++;
112
113  /*
114   *  Update CPU time
115   */
116
117  #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
118    _Timespec_Add_to( &stats->total_cpu_time, &executed );
119
120    if ( _Timespec_Less_than( &executed, &stats->min_cpu_time ) )
121      stats->min_cpu_time = executed;
122
123    if ( _Timespec_Greater_than( &executed, &stats->max_cpu_time ) )
124      stats->max_cpu_time = executed;
125  #else
126    stats->total_cpu_time  += ticks_executed_since_last_period;
127
128    if ( ticks_executed_since_last_period < stats->min_cpu_time )
129      stats->min_cpu_time = ticks_executed_since_last_period;
130
131    if ( ticks_executed_since_last_period > stats->max_cpu_time )
132      stats->max_cpu_time = ticks_executed_since_last_period;
133  #endif
134
135  /*
136   *  Update Wall time
137   */
138
139  #ifndef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
140    stats->total_wall_time += ticks_since_last_period;
141
142    if ( ticks_since_last_period < stats->min_wall_time )
143      stats->min_wall_time = ticks_since_last_period;
144
145    if ( ticks_since_last_period > stats->max_wall_time )
146      stats->max_wall_time = ticks_since_last_period;
147  #else
148    _Timespec_Add_to( &stats->total_wall_time, &since_last_period );
149
150    if ( _Timespec_Less_than( &since_last_period, &stats->min_wall_time ) )
151      stats->min_wall_time = since_last_period;
152
153    if ( _Timespec_Greater_than( &since_last_period, &stats->max_wall_time ) )
154      stats->max_wall_time = since_last_period;
155  #endif
156}
157
158
159/*PAGE
160 *
161 *  rtems_rate_monotonic_period
162 *
163 *  This directive allows a thread to manipulate a rate monotonic timer.
164 *
165 *  Input parameters:
166 *    id     - rate monotonic id
167 *    length - length of period (in ticks)
168 *
169 *  Output parameters:
170 *    RTEMS_SUCCESSFUL - if successful
171 *    error code       - if unsuccessful
172 */
173
174rtems_status_code rtems_rate_monotonic_period(
175  Objects_Id        id,
176  rtems_interval    length
177)
178{
179  Rate_monotonic_Control              *the_period;
180  Objects_Locations                    location;
181  rtems_status_code                    return_value;
182  rtems_rate_monotonic_period_states   local_state;
183  ISR_Level                            level;
184
185  the_period = _Rate_monotonic_Get( id, &location );
186  switch ( location ) {
187    case OBJECTS_REMOTE:            /* should never return this */
188      return RTEMS_INTERNAL_ERROR;
189
190    case OBJECTS_ERROR:
191      return RTEMS_INVALID_ID;
192
193    case OBJECTS_LOCAL:
194      if ( !_Thread_Is_executing( the_period->owner ) ) {
195        _Thread_Enable_dispatch();
196        return RTEMS_NOT_OWNER_OF_RESOURCE;
197      }
198
199      if ( length == RTEMS_PERIOD_STATUS ) {
200        switch ( the_period->state ) {
201          case RATE_MONOTONIC_INACTIVE:
202            return_value = RTEMS_NOT_DEFINED;
203            break;
204          case RATE_MONOTONIC_ACTIVE:
205            return_value = RTEMS_SUCCESSFUL;
206            break;
207          case RATE_MONOTONIC_EXPIRED:
208            return_value = RTEMS_TIMEOUT;
209            break;
210          default:              /* unreached -- only to remove warnings */
211            return_value = RTEMS_INTERNAL_ERROR;
212            break;
213        }
214        _Thread_Enable_dispatch();
215        return( return_value );
216      }
217
218      _ISR_Disable( level );
219      switch ( the_period->state ) {
220        case RATE_MONOTONIC_INACTIVE: {
221          #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
222              defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
223            struct timespec uptime;
224          #endif
225
226          /*
227           *  No need to update statistics -- there are not a period active
228           */
229
230          _ISR_Enable( level );
231
232
233          #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
234              defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
235            _TOD_Get_uptime( &uptime );
236          #endif
237             
238          #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
239            /*
240             * Since the statistics didn't update the starting time,
241             * we do it here.
242             */
243            the_period->time_at_period = uptime;
244          #else
245            the_period->time_at_period = _Watchdog_Ticks_since_boot;
246          #endif
247
248          #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
249            {
250              struct timespec ran;
251
252              the_period->owner_executed_at_period =
253                _Thread_Executing->cpu_time_used;
254
255              /* How much time time since last context switch */
256              _Timespec_Subtract(
257                &_Thread_Time_of_last_context_switch,
258                &uptime,
259                &ran
260              );
261
262              /* The thread had executed before the last context switch also.
263               *   
264               *     the_period->owner_executed_at_period += ran
265               */
266              _Timespec_Add_to( &the_period->owner_executed_at_period, &ran );
267            }
268          #else
269            the_period->owner_ticks_executed_at_period =
270              _Thread_Executing->ticks_executed;
271          #endif
272
273          the_period->state = RATE_MONOTONIC_ACTIVE;
274          _Watchdog_Initialize(
275            &the_period->Timer,
276            _Rate_monotonic_Timeout,
277            id,
278            NULL
279          );
280
281          the_period->next_length = length;
282
283          _Watchdog_Insert_ticks( &the_period->Timer, length );
284          _Thread_Enable_dispatch();
285          return RTEMS_SUCCESSFUL;
286        }
287        case RATE_MONOTONIC_ACTIVE:
288
289          /*
290           *  Update statistics from the concluding period
291           */
292          _Rate_monotonic_Update_statistics( the_period );
293
294          /*
295           *  This tells the _Rate_monotonic_Timeout that this task is
296           *  in the process of blocking on the period and that we
297           *  may be changing the length of the next period.
298           */
299
300          the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
301          the_period->next_length = length;
302
303          _ISR_Enable( level );
304
305          _Thread_Executing->Wait.id = the_period->Object.id;
306          _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
307
308          /*
309           *  Did the watchdog timer expire while we were actually blocking
310           *  on it?
311           */
312
313          _ISR_Disable( level );
314            local_state = the_period->state;
315            the_period->state = RATE_MONOTONIC_ACTIVE;
316          _ISR_Enable( level );
317
318          /*
319           *  If it did, then we want to unblock ourself and continue as
320           *  if nothing happen.  The period was reset in the timeout routine.
321           */
322
323          if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
324            _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
325
326          _Thread_Enable_dispatch();
327          return RTEMS_SUCCESSFUL;
328          break;
329
330        case RATE_MONOTONIC_EXPIRED:
331          /*
332           *  Update statistics from the concluding period
333           */
334          _Rate_monotonic_Update_statistics( the_period );
335
336          _ISR_Enable( level );
337
338          the_period->state = RATE_MONOTONIC_ACTIVE;
339          the_period->next_length = length;
340
341          _Watchdog_Insert_ticks( &the_period->Timer, length );
342          _Thread_Enable_dispatch();
343          return RTEMS_TIMEOUT;
344
345        case RATE_MONOTONIC_OWNER_IS_BLOCKING:
346        case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
347          /*
348           *  These should never happen.
349           */
350          break;
351      }
352  }
353
354  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
355}
Note: See TracBrowser for help on using the repository browser.