source: rtems/cpukit/libmisc/cpuuse/cpuusagereport.c @ baef6771

4.115
Last change on this file since baef6771 was baef6771, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 15, 2011 at 2:34:21 PM

2011-09-15 Sebastian Huber <sebastian.huber@…>

  • cpukit/libmisc/cpuuse/cpuuse.h, cpukit/libmisc/cpuuse/cpuusagedata.c, cpukit/libmisc/cpuuse/cpuusagereport.c, cpukit/libmisc/cpuuse/cpuusagereset.c: Fixed timestamp usage.
  • Property mode set to 100644
File size: 6.6 KB
Line 
1/*
2 *  CPU Usage Reporter
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#ifdef HAVE_CONFIG_H
15#include "config.h"
16#endif
17
18#include <string.h>
19#include <stdlib.h>
20#include <stdio.h>
21#include <ctype.h>
22#include <inttypes.h>
23
24#include <rtems/cpuuse.h>
25
26#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
27  static bool is_executing_on_a_core(
28    Thread_Control    *the_thread,
29    Timestamp_Control *time_of_context_switch
30  )
31  {
32    #ifndef RTEMS_SMP
33      if ( _Thread_Executing->Object.id == the_thread->Object.id ) {
34        *time_of_context_switch = _Thread_Time_of_last_context_switch;
35        return true;
36      }
37    #else
38      int  cpu;
39      for ( cpu=0 ; cpu < rtems_smp_get_number_of_processors() ; cpu++ ) {
40        Per_CPU_Control *p = &_Per_CPU_Information[cpu];
41        if ( p->executing->Object.id == the_thread->Object.id ) {
42          *time_of_context_switch = p->time_of_last_context_switch;
43          return true;
44        }
45      }
46    #endif
47    return false;
48  }
49#endif
50
51/*
52 *  rtems_cpu_usage_report
53 */
54void rtems_cpu_usage_report_with_plugin(
55  void                  *context,
56  rtems_printk_plugin_t  print
57)
58{
59  uint32_t             i;
60  uint32_t             api_index;
61  Thread_Control      *the_thread;
62  Objects_Information *information;
63  char                 name[13];
64  uint32_t             ival, fval;
65  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
66    Timestamp_Control  uptime, total, ran, uptime_at_last_reset;
67    uint32_t seconds, nanoseconds;
68  #else
69    uint32_t           total_units = 0;
70  #endif
71
72  if ( !print )
73    return;
74
75  /*
76   *  When not using nanosecond CPU usage resolution, we have to count
77   *  the number of "ticks" we gave credit for to give the user a rough
78   *  guideline as to what each number means proportionally.
79   */
80  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
81    _Timestamp_Set_to_zero( &total );
82    uptime_at_last_reset = CPU_usage_Uptime_at_last_reset;
83  #else
84    for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
85      #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG)
86        if ( !_Objects_Information_table[ api_index ] )
87          continue;
88      #endif
89
90      information = _Objects_Information_table[ api_index ][ 1 ];
91      if ( information ) {
92        for ( i=1 ; i <= information->maximum ; i++ ) {
93          the_thread = (Thread_Control *)information->local_table[ i ];
94
95          if ( the_thread )
96            total_units += the_thread->cpu_time_used;
97        }
98      }
99    }
100  #endif
101
102  (*print)(
103     context,
104     "-------------------------------------------------------------------------------\n"
105     "                              CPU USAGE BY THREAD\n"
106     "------------+----------------------------------------+---------------+---------\n"
107     #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
108       " ID         | NAME                                   | SECONDS       | PERCENT\n"
109     #else
110       " ID         | NAME                                   | TICKS         | PERCENT\n"
111     #endif
112     "------------+----------------------------------------+---------------+---------\n"
113  );
114
115  for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
116    #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG)
117      if ( !_Objects_Information_table[ api_index ] )
118        continue;
119    #endif
120
121    information = _Objects_Information_table[ api_index ][ 1 ];
122    if ( information ) {
123      for ( i=1 ; i <= information->maximum ; i++ ) {
124        the_thread = (Thread_Control *)information->local_table[ i ];
125
126        if ( !the_thread )
127          continue;
128
129        rtems_object_get_name( the_thread->Object.id, sizeof(name), name );
130
131        (*print)(
132          context,
133          " 0x%08" PRIx32 " | %-38s |",
134          the_thread->Object.id,
135          name
136        );
137
138        #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
139        {
140          Timestamp_Control last;
141
142          /*
143           * If this is the currently executing thread, account for time
144           * since the last context switch.
145           */
146          ran = the_thread->cpu_time_used;
147          if ( is_executing_on_a_core( the_thread, &last ) ) {
148            Timestamp_Control used;
149            _TOD_Get_uptime( &uptime );
150            _Timestamp_Subtract( &last, &uptime, &used );
151            _Timestamp_Add_to( &ran, &used );
152          } else {
153            _TOD_Get_uptime( &uptime );
154          }
155          _Timestamp_Subtract( &uptime_at_last_reset, &uptime, &total );
156          _Timestamp_Divide( &ran, &total, &ival, &fval );
157
158          /*
159           * Print the information
160           */
161
162          seconds = _Timestamp_Get_seconds( &ran );
163          nanoseconds = _Timestamp_Get_nanoseconds( &ran ) /
164            TOD_NANOSECONDS_PER_MICROSECOND;
165          (*print)( context,
166            "%7" PRIu32 ".%06" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",
167            seconds, nanoseconds,
168            ival, fval
169          );
170        }
171        #else
172         if (total_units) {
173            uint64_t ival_64;
174
175            ival_64 = the_thread->cpu_time_used;
176            ival_64 *= 100000;
177            ival = ival_64 / total_units;
178          } else {
179            ival = 0;
180          }
181
182          fval = ival % 1000;
183          ival /= 1000;
184          (*print)( context,
185            "%14" PRIu32 " |%4" PRIu32 ".%03" PRIu32 "\n",
186            the_thread->cpu_time_used,
187            ival,
188            fval
189          );
190        #endif
191      }
192    }
193  }
194
195  #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
196    seconds = _Timestamp_Get_seconds( &total );
197    nanoseconds = _Timestamp_Get_nanoseconds( &total ) /
198      TOD_NANOSECONDS_PER_MICROSECOND;
199    (*print)(
200       context,
201       "------------+----------------------------------------+---------------+---------\n"
202       " TIME SINCE LAST CPU USAGE RESET IN SECONDS:                    %7" PRIu32 ".%06" PRIu32 "\n"
203       "-------------------------------------------------------------------------------\n",
204       seconds, nanoseconds
205    );
206  #else
207    (*print)(
208       context,
209       "------------+----------------------------------------+---------------+---------\n"
210       " TICKS SINCE LAST SYSTEM RESET:                                 %14" PRIu32 "\n"
211       " TOTAL UNITS:                                                   %14" PRIu32 "\n"
212       "-------------------------------------------------------------------------------\n",
213       _Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset,
214       total_units
215    );
216  #endif
217}
218
219void rtems_cpu_usage_report( void )
220{
221  rtems_cpu_usage_report_with_plugin( NULL, printk_plugin );
222}
Note: See TracBrowser for help on using the repository browser.