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

4.104.114.84.95
Last change on this file since c3330a8 was c3330a8, checked in by Joel Sherrill <joel.sherrill@…>, on May 17, 2007 at 10:46:45 PM

2007-05-17 Joel Sherrill <joel.sherrill@…>

  • ChangeLog?, configure.ac, libcsupport/src/times.c, libmisc/cpuuse/cpuuse.c, libmisc/stackchk/check.c, rtems/include/rtems/rtems/ratemon.h, rtems/src/ratemongetstatus.c, rtems/src/ratemonperiod.c, rtems/src/ratemonreportstatistics.c, rtems/src/ratemonresetall.c, rtems/src/ratemontimeout.c, score/Makefile.am, score/include/rtems/score/thread.h, score/include/rtems/score/timespec.h, score/src/threaddispatch.c, score/src/threadinitialize.c, score/src/threadtickletimeslice.c, score/src/timespecdivide.c: Add nanoseconds granularity to the rate monotonic period statistics and CPU usage statistics. This capability is enabled by default although may be conditionally disabled by the user. It could be too much overhead on small targets but it does not appear to be bad in early testing. Its impact on code size has not been evaluated either. It is possible that both forms of statistics gathering could be disabled with further tweaking of the conditional compilation.
  • score/src/timespecdividebyinteger.c: New file.
  • Property mode set to 100644
File size: 10.0 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    the_period->time_at_period = uptime;
70    _Timespec_Subtract( &period_start, &uptime, &since_last_period );
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;
80       
81       /* executed = current cpu usage - value at start of period */
82      _Timespec_Subtract( 
83         &the_period->owner_executed_at_period,
84         &_Thread_Executing->cpu_time_used,
85         &executed
86      );
87
88      /* How much time time since last context switch */
89      _Timespec_Subtract(&_Thread_Time_of_last_context_switch, &uptime, &ran);
90
91      /* executed += ran */
92      _Timespec_Add_to( &executed, &ran );
93    }
94  #else
95      ticks_executed_since_last_period = the_period->owner->ticks_executed -
96        the_period->owner_ticks_executed_at_period;
97  #endif
98
99  /*
100   *  Now update the statistics
101   */
102
103  stats = &the_period->Statistics;
104  stats->count++;
105
106  if ( the_period->state == RATE_MONOTONIC_EXPIRED )
107    stats->missed_count++;
108
109  /*
110   *  Update CPU time
111   */
112
113  #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
114    _Timespec_Add_to( &stats->total_cpu_time, &executed );
115
116    if ( _Timespec_Less_than( &executed, &stats->min_cpu_time ) ) 
117      stats->min_cpu_time = executed;
118
119    if ( _Timespec_Greater_than( &executed, &stats->max_cpu_time ) ) 
120      stats->max_cpu_time = executed;
121
122  #else
123    stats->total_cpu_time  += ticks_executed_since_last_period;
124
125    if ( ticks_executed_since_last_period < stats->min_cpu_time )
126      stats->min_cpu_time = ticks_executed_since_last_period;
127
128    if ( ticks_executed_since_last_period > stats->max_cpu_time )
129      stats->max_cpu_time = ticks_executed_since_last_period;
130  #endif
131
132  /*
133   *  Update Wall time
134   */
135
136  #ifndef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
137    stats->total_wall_time += ticks_since_last_period;
138
139    if ( ticks_since_last_period < stats->min_wall_time )
140      stats->min_wall_time = ticks_since_last_period;
141
142    if ( ticks_since_last_period > stats->max_wall_time )
143      stats->max_wall_time = ticks_since_last_period;
144  #else
145    _Timespec_Add_to( &stats->total_wall_time, &since_last_period );
146
147    if ( _Timespec_Less_than( &since_last_period, &stats->min_wall_time ) ) 
148      stats->min_wall_time = since_last_period;
149
150    if ( _Timespec_Greater_than( &since_last_period, &stats->max_wall_time ) ) 
151      stats->max_wall_time = since_last_period;
152  #endif
153}
154
155
156/*PAGE
157 *
158 *  rtems_rate_monotonic_period
159 *
160 *  This directive allows a thread to manipulate a rate monotonic timer.
161 *
162 *  Input parameters:
163 *    id     - rate monotonic id
164 *    length - length of period (in ticks)
165 *
166 *  Output parameters:
167 *    RTEMS_SUCCESSFUL - if successful
168 *    error code       - if unsuccessful
169 */
170
171rtems_status_code rtems_rate_monotonic_period(
172  Objects_Id        id,
173  rtems_interval    length
174)
175{
176  Rate_monotonic_Control              *the_period;
177  Objects_Locations                    location;
178  rtems_status_code                    return_value;
179  rtems_rate_monotonic_period_states   local_state;
180  ISR_Level                            level;
181
182  the_period = _Rate_monotonic_Get( id, &location );
183  switch ( location ) {
184    case OBJECTS_REMOTE:            /* should never return this */
185      return RTEMS_INTERNAL_ERROR;
186
187    case OBJECTS_ERROR:
188      return RTEMS_INVALID_ID;
189
190    case OBJECTS_LOCAL:
191      if ( !_Thread_Is_executing( the_period->owner ) ) {
192        _Thread_Enable_dispatch();
193        return RTEMS_NOT_OWNER_OF_RESOURCE;
194      }
195
196      if ( length == RTEMS_PERIOD_STATUS ) {
197        switch ( the_period->state ) {
198          case RATE_MONOTONIC_INACTIVE:
199            return_value = RTEMS_NOT_DEFINED;
200            break;
201          case RATE_MONOTONIC_ACTIVE:
202            return_value = RTEMS_SUCCESSFUL;
203            break;
204          case RATE_MONOTONIC_EXPIRED:
205            return_value = RTEMS_TIMEOUT;
206            break;
207          default:              /* unreached -- only to remove warnings */
208            return_value = RTEMS_INTERNAL_ERROR;
209            break;
210        }
211        _Thread_Enable_dispatch();
212        return( return_value );
213      }
214
215      _ISR_Disable( level );
216      switch ( the_period->state ) {
217        case RATE_MONOTONIC_INACTIVE:
218          /*
219           *  No need to update statistics -- there are not a period active
220           */
221
222          _ISR_Enable( level );
223
224          #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
225            /*
226             * Since the statistics didn't update the starting time,
227             * we do it here.
228             */
229            _TOD_Get_uptime( &the_period->time_at_period );
230          #else
231            the_period->time_at_period = _Watchdog_Ticks_since_boot;
232          #endif
233
234          #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
235            { 
236              struct timespec ran, uptime;
237
238              _TOD_Get_uptime( &uptime );
239             
240              the_period->owner_executed_at_period = 
241                _Thread_Executing->cpu_time_used;
242
243              /* How much time time since last context switch */
244              _Timespec_Subtract(
245                &_Thread_Time_of_last_context_switch,
246                &uptime,
247                &ran
248              );
249
250              /* thread had executed before the last context switch also */
251              _Timespec_Add_to( &the_period->owner_executed_at_period, &ran );
252            }
253          #else
254            the_period->owner_ticks_executed_at_period =
255              _Thread_Executing->ticks_executed;
256          #endif
257
258          the_period->state = RATE_MONOTONIC_ACTIVE;
259          _Watchdog_Initialize(
260            &the_period->Timer,
261            _Rate_monotonic_Timeout,
262            id,
263            NULL
264          );
265
266          the_period->next_length = length;
267
268          _Watchdog_Insert_ticks( &the_period->Timer, length );
269          _Thread_Enable_dispatch();
270          return RTEMS_SUCCESSFUL;
271
272        case RATE_MONOTONIC_ACTIVE:
273
274          /*
275           *  Update statistics from the concluding period
276           */
277          _Rate_monotonic_Update_statistics( the_period );
278
279          /*
280           *  This tells the _Rate_monotonic_Timeout that this task is
281           *  in the process of blocking on the period and that we
282           *  may be changing the length of the next period.
283           */
284
285          the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
286          the_period->next_length = length;
287
288          _ISR_Enable( level );
289
290          _Thread_Executing->Wait.id = the_period->Object.id;
291          _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
292
293          /*
294           *  Did the watchdog timer expire while we were actually blocking
295           *  on it?
296           */
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
308          if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
309            _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
310
311          _Thread_Enable_dispatch();
312          return RTEMS_SUCCESSFUL;
313          break;
314
315        case RATE_MONOTONIC_EXPIRED:
316          /*
317           *  Update statistics from the concluding period
318           */
319          _Rate_monotonic_Update_statistics( the_period );
320
321          _ISR_Enable( level );
322
323          the_period->state = RATE_MONOTONIC_ACTIVE;
324          the_period->next_length = length;
325
326          _Watchdog_Insert_ticks( &the_period->Timer, length );
327          _Thread_Enable_dispatch();
328          return RTEMS_TIMEOUT;
329
330        case RATE_MONOTONIC_OWNER_IS_BLOCKING:
331        case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
332          /*
333           *  These should never happen.
334           */
335          break;
336      }
337  }
338
339  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
340}
Note: See TracBrowser for help on using the repository browser.