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

4.104.114.95
Last change on this file since ebe61382 was ebe61382, checked in by Joel Sherrill <joel.sherrill@…>, on 11/30/07 at 21:49:41

2007-11-30 Joel Sherrill <joel.sherrill@…>

  • rtems/src/barrierdelete.c, rtems/src/barrierrelease.c, rtems/src/barriertranslatereturncode.c, rtems/src/barrierwait.c, rtems/src/clockget.c, rtems/src/dpmemdelete.c, rtems/src/dpmemexternal2internal.c, rtems/src/dpmeminternal2external.c, rtems/src/eventsend.c, rtems/src/eventtimeout.c, rtems/src/msgqbroadcast.c, rtems/src/msgqdelete.c, rtems/src/msgqflush.c, rtems/src/msgqgetnumberpending.c, rtems/src/msgqreceive.c, rtems/src/msgqsend.c, rtems/src/msgqurgent.c, rtems/src/partdelete.c, rtems/src/partgetbuffer.c, rtems/src/partreturnbuffer.c, rtems/src/ratemoncancel.c, rtems/src/ratemondelete.c, rtems/src/ratemongetstatistics.c, rtems/src/ratemongetstatus.c, rtems/src/ratemonperiod.c, rtems/src/ratemonresetstatistics.c, rtems/src/ratemontimeout.c, rtems/src/semdelete.c, rtems/src/semflush.c, rtems/src/semobtain.c, rtems/src/semrelease.c, rtems/src/semtranslatereturncode.c, rtems/src/signalsend.c, rtems/src/taskdelete.c, rtems/src/taskgetnote.c, rtems/src/taskissuspended.c, rtems/src/taskrestart.c, rtems/src/taskresume.c, rtems/src/tasksetnote.c, rtems/src/tasksetpriority.c, rtems/src/taskstart.c, rtems/src/tasksuspend.c, rtems/src/taskvariableadd.c, rtems/src/taskvariabledelete.c, rtems/src/taskvariableget.c, rtems/src/timercancel.c, rtems/src/timerdelete.c, rtems/src/timerfirewhen.c, rtems/src/timergetinfo.c, rtems/src/timerreset.c, rtems/src/timerserverfireafter.c, rtems/src/timerserverfirewhen.c: Restructured all code with the switch (location) pattern so that OBJECTS_LOCAL is first and we can fall into it and the OBJECTS_ERROR case breaks to a return RTEMS_INVALID_ID. This eliminates the return RTEMS_INTERNAL_ERROR at the bottom of each of these files which was unreachable and untestable code. This resulted in a code savings of approximately 20 bytes per file on the SPARC/ERC32.
  • 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            return_value = RTEMS_TIMEOUT;
201            break;
202          case RATE_MONOTONIC_ACTIVE:
203          default:              /* unreached -- only to remove warnings */
204            return_value = RTEMS_SUCCESSFUL;
205            break;
206        }
207        _Thread_Enable_dispatch();
208        return( return_value );
209      }
210
211      _ISR_Disable( level );
212      switch ( the_period->state ) {
213        case RATE_MONOTONIC_INACTIVE: {
214          #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
215              defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
216            struct timespec uptime;
217          #endif
218
219          /*
220           *  No need to update statistics -- there are not a period active
221           */
222
223          _ISR_Enable( level );
224
225
226          #if defined(RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS) || \
227              defined(RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS)
228            _TOD_Get_uptime( &uptime );
229          #endif
230             
231          #ifdef RTEMS_ENABLE_NANOSECOND_RATE_MONOTONIC_STATISTICS
232            /*
233             * Since the statistics didn't update the starting time,
234             * we do it here.
235             */
236            the_period->time_at_period = uptime;
237          #else
238            the_period->time_at_period = _Watchdog_Ticks_since_boot;
239          #endif
240
241          #ifdef RTEMS_ENABLE_NANOSECOND_CPU_USAGE_STATISTICS
242            {
243              struct timespec ran;
244
245              the_period->owner_executed_at_period =
246                _Thread_Executing->cpu_time_used;
247
248              /* How much time time since last context switch */
249              _Timespec_Subtract(
250                &_Thread_Time_of_last_context_switch,
251                &uptime,
252                &ran
253              );
254
255              /* The thread had executed before the last context switch also.
256               *   
257               *     the_period->owner_executed_at_period += ran
258               */
259              _Timespec_Add_to( &the_period->owner_executed_at_period, &ran );
260            }
261          #else
262            the_period->owner_ticks_executed_at_period =
263              _Thread_Executing->ticks_executed;
264          #endif
265
266          the_period->state = RATE_MONOTONIC_ACTIVE;
267          _Watchdog_Initialize(
268            &the_period->Timer,
269            _Rate_monotonic_Timeout,
270            id,
271            NULL
272          );
273
274          the_period->next_length = length;
275
276          _Watchdog_Insert_ticks( &the_period->Timer, length );
277          _Thread_Enable_dispatch();
278          return RTEMS_SUCCESSFUL;
279        }
280        case RATE_MONOTONIC_ACTIVE:
281
282          /*
283           *  Update statistics from the concluding period
284           */
285          _Rate_monotonic_Update_statistics( the_period );
286
287          /*
288           *  This tells the _Rate_monotonic_Timeout that this task is
289           *  in the process of blocking on the period and that we
290           *  may be changing the length of the next period.
291           */
292
293          the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
294          the_period->next_length = length;
295
296          _ISR_Enable( level );
297
298          _Thread_Executing->Wait.id = the_period->Object.id;
299          _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
300
301          /*
302           *  Did the watchdog timer expire while we were actually blocking
303           *  on it?
304           */
305
306          _ISR_Disable( level );
307            local_state = the_period->state;
308            the_period->state = RATE_MONOTONIC_ACTIVE;
309          _ISR_Enable( level );
310
311          /*
312           *  If it did, then we want to unblock ourself and continue as
313           *  if nothing happen.  The period was reset in the timeout routine.
314           */
315
316          if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
317            _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
318
319          _Thread_Enable_dispatch();
320          return RTEMS_SUCCESSFUL;
321          break;
322
323        case RATE_MONOTONIC_EXPIRED:
324          /*
325           *  Update statistics from the concluding period
326           */
327          _Rate_monotonic_Update_statistics( the_period );
328
329          _ISR_Enable( level );
330
331          the_period->state = RATE_MONOTONIC_ACTIVE;
332          the_period->next_length = length;
333
334          _Watchdog_Insert_ticks( &the_period->Timer, length );
335          _Thread_Enable_dispatch();
336          return RTEMS_TIMEOUT;
337
338        case RATE_MONOTONIC_OWNER_IS_BLOCKING:
339        case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
340          /*
341           *  These should never happen.
342           */
343          break;
344      }
345
346#if defined(RTEMS_MULTIPROCESSING)
347    case OBJECTS_REMOTE:            /* should never return this */
348#endif
349    case OBJECTS_ERROR:
350      break;
351  }
352
353  return RTEMS_INVALID_ID;
354}
Note: See TracBrowser for help on using the repository browser.