source: rtems/cpukit/rtems/src/ratemonperiod.c @ 11c16a64

4.104.114.9
Last change on this file since 11c16a64 was 11c16a64, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 22, 2008 at 9:19:18 PM

2008-01-22 Joel Sherrill <joel.sherrill@…>

  • rtems/src/eventsurrender.c, rtems/src/ratemonperiod.c, score/src/threadqdequeue.c, score/src/threadqdequeuefifo.c, score/src/threadqdequeuepriority.c: Fix bugs encountered while testing and clean up more code.
  • Property mode set to 100644
File size: 10.4 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
188    case OBJECTS_LOCAL:
189      if ( !_Thread_Is_executing( the_period->owner ) ) {
190        _Thread_Enable_dispatch();
191        return RTEMS_NOT_OWNER_OF_RESOURCE;
192      }
193
194      if ( length == RTEMS_PERIOD_STATUS ) {
195        switch ( the_period->state ) {
196          case RATE_MONOTONIC_INACTIVE:
197            return_value = RTEMS_NOT_DEFINED;
198            break;
199          case RATE_MONOTONIC_EXPIRED:
200          case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
201            return_value = RTEMS_TIMEOUT;
202            break;
203          case RATE_MONOTONIC_ACTIVE:
204          default:              /* unreached -- only to remove warnings */
205            return_value = RTEMS_SUCCESSFUL;
206            break;
207        }
208        _Thread_Enable_dispatch();
209        return( return_value );
210      }
211
212      _ISR_Disable( level );
213      switch ( the_period->state ) {
214        case RATE_MONOTONIC_INACTIVE: {
215          #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
216              defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
217            struct timespec uptime;
218          #endif
219
220          /*
221           *  No need to update statistics -- there are not a period active
222           */
223
224          _ISR_Enable( level );
225
226
227          #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
228              defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
229            _TOD_Get_uptime( &uptime );
230          #endif
231             
232          #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
233            /*
234             * Since the statistics didn't update the starting time,
235             * we do it here.
236             */
237            the_period->time_at_period = uptime;
238          #else
239            the_period->time_at_period = _Watchdog_Ticks_since_boot;
240          #endif
241
242          #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
243            { 
244              struct timespec ran;
245
246              the_period->owner_executed_at_period = 
247                _Thread_Executing->cpu_time_used;
248
249              /* How much time time since last context switch */
250              _Timespec_Subtract(
251                &_Thread_Time_of_last_context_switch,
252                &uptime,
253                &ran
254              );
255
256              /* The thread had executed before the last context switch also.
257               *   
258               *     the_period->owner_executed_at_period += ran
259               */
260              _Timespec_Add_to( &the_period->owner_executed_at_period, &ran );
261            }
262          #else
263            the_period->owner_ticks_executed_at_period =
264              _Thread_Executing->ticks_executed;
265          #endif
266
267          the_period->state = RATE_MONOTONIC_ACTIVE;
268          _Watchdog_Initialize(
269            &the_period->Timer,
270            _Rate_monotonic_Timeout,
271            id,
272            NULL
273          );
274
275          the_period->next_length = length;
276
277          _Watchdog_Insert_ticks( &the_period->Timer, length );
278          _Thread_Enable_dispatch();
279          return RTEMS_SUCCESSFUL;
280        }
281        case RATE_MONOTONIC_ACTIVE:
282
283          /*
284           *  Update statistics from the concluding period
285           */
286          _Rate_monotonic_Update_statistics( the_period );
287
288          /*
289           *  This tells the _Rate_monotonic_Timeout that this task is
290           *  in the process of blocking on the period and that we
291           *  may be changing the length of the next period.
292           */
293
294          the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
295          the_period->next_length = length;
296
297          _ISR_Enable( level );
298
299          _Thread_Executing->Wait.id = the_period->Object.id;
300          _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
301
302          /*
303           *  Did the watchdog timer expire while we were actually blocking
304           *  on it?
305           */
306
307          _ISR_Disable( level );
308            local_state = the_period->state;
309            the_period->state = RATE_MONOTONIC_ACTIVE;
310          _ISR_Enable( level );
311
312          /*
313           *  If it did, then we want to unblock ourself and continue as
314           *  if nothing happen.  The period was reset in the timeout routine.
315           */
316
317          if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
318            _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
319
320          _Thread_Enable_dispatch();
321          return RTEMS_SUCCESSFUL;
322          break;
323
324        case RATE_MONOTONIC_EXPIRED:
325          /*
326           *  Update statistics from the concluding period
327           */
328          _Rate_monotonic_Update_statistics( the_period );
329
330          _ISR_Enable( level );
331
332          the_period->state = RATE_MONOTONIC_ACTIVE;
333          the_period->next_length = length;
334
335          _Watchdog_Insert_ticks( &the_period->Timer, length );
336          _Thread_Enable_dispatch();
337          return RTEMS_TIMEOUT;
338
339        case RATE_MONOTONIC_OWNER_IS_BLOCKING:
340        case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
341          /*
342           *  These should never happen.
343           */
344          break;
345      }
346
347#if defined(RTEMS_MULTIPROCESSING)
348    case OBJECTS_REMOTE:            /* should never return this */
349#endif
350    case OBJECTS_ERROR:
351      break;
352  }
353
354  return RTEMS_INVALID_ID;
355}
Note: See TracBrowser for help on using the repository browser.