summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems/src/ratemonreportstatistics.c
blob: f3610baae0160cebbccfec850bc47217bc9efffc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
 * @file
 *
 * @ingroup RTEMSImplClassicRateMonotonic
 *
 * @brief This source file contains the implementation of
 *   rtems_rate_monotonic_report_statistics_with_plugin().
 */

/*
 *  COPYRIGHT (c) 1989-2010.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <rtems/rtems/ratemonimpl.h>
#include <rtems/rtems/object.h>
#include <rtems/printer.h>

#include <inttypes.h>
#include <rtems/inttypes.h>

/* We print to 1/10's of milliseconds */
#define NANOSECONDS_DIVIDER 1000L
#define PERCENT_FMT     "%04" PRId32
#define NANOSECONDS_FMT "%06ld"

void rtems_rate_monotonic_report_statistics_with_plugin(
  const rtems_printer *printer
)
{
  rtems_status_code                      status;
  rtems_id                               maximum_id;
  rtems_id                               id;
  rtems_rate_monotonic_period_statistics the_stats;
  rtems_rate_monotonic_period_status     the_status;
  char                                   name[5];

  rtems_printf( printer, "Period information by period\n" );
  rtems_printf( printer, "--- CPU times are in seconds ---\n" );
  rtems_printf( printer, "--- Wall times are in seconds ---\n" );
/*
Layout by columns -- in memory of Hollerith :)

1234567890123456789012345678901234567890123456789012345678901234567890123456789\
   ID     OWNER COUNT MISSED X
ididididid NNNN ccccc mmmmmm X

  Uncomment the following if you are tinkering with the formatting.
  Be sure to test the various cases.
  (*print)( context,"\
1234567890123456789012345678901234567890123456789012345678901234567890123456789\
\n");
*/
  rtems_printf( printer,
      "   ID     OWNER COUNT MISSED     "
      "     CPU TIME                  WALL TIME\n"
      "                               "
      "     MIN/MAX/AVG                MIN/MAX/AVG\n"
  );

  /*
   * Cycle through all possible ids and try to report on each one.  If it
   * is a period that is inactive, we just get an error back.  No big deal.
   */
  maximum_id = _Rate_monotonic_Information.maximum_id;
  for (
    id = _Objects_Get_minimum_id( maximum_id ) ;
    id <= maximum_id ;
    ++id
  ) {
    status = rtems_rate_monotonic_get_statistics( id, &the_stats );
    if ( status != RTEMS_SUCCESSFUL )
      continue;

    /* If the above passed, so should this but check it anyway */
    #if defined(RTEMS_DEBUG)
      status = rtems_rate_monotonic_get_status( id, &the_status );
      if ( status != RTEMS_SUCCESSFUL )
        continue;
    #else
      (void) rtems_rate_monotonic_get_status( id, &the_status );
    #endif

    rtems_object_get_name( the_status.owner, sizeof(name), name );

    /*
     *  Print part of report line that is not dependent on granularity
     */
    rtems_printf( printer,
      "0x%08" PRIx32 " %4s %5" PRId32 " %6" PRId32 " ",
      id, name,
      the_stats.count, the_stats.missed_count
    );

    /*
     *  If the count is zero, don't print statistics
     */
    if (the_stats.count == 0) {
      rtems_printf( printer, "\n" );
      continue;
    }

    /*
     *  print CPU Usage part of statistics
     */
    {
      struct timespec  cpu_average;
      struct timespec *min_cpu = &the_stats.min_cpu_time;
      struct timespec *max_cpu = &the_stats.max_cpu_time;
      struct timespec *total_cpu = &the_stats.total_cpu_time;

      _Timespec_Divide_by_integer( total_cpu, the_stats.count, &cpu_average );
      rtems_printf( printer,
        "%" PRIdtime_t "."  NANOSECONDS_FMT "/"        /* min cpu time */
        "%" PRIdtime_t "."  NANOSECONDS_FMT "/"        /* max cpu time */
        "%" PRIdtime_t "."  NANOSECONDS_FMT " ",       /* avg cpu time */
        _Timespec_Get_seconds( min_cpu ),
	  _Timespec_Get_nanoseconds( min_cpu ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( max_cpu ),
	  _Timespec_Get_nanoseconds( max_cpu ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( &cpu_average ),
	  _Timespec_Get_nanoseconds( &cpu_average ) / NANOSECONDS_DIVIDER
       );
    }

    /*
     *  print wall time part of statistics
     */
    {
      struct timespec  wall_average;
      struct timespec *min_wall = &the_stats.min_wall_time;
      struct timespec *max_wall = &the_stats.max_wall_time;
      struct timespec *total_wall = &the_stats.total_wall_time;

      _Timespec_Divide_by_integer(total_wall, the_stats.count, &wall_average);
      rtems_printf( printer,
        "%" PRIdtime_t "." NANOSECONDS_FMT "/"        /* min wall time */
        "%" PRIdtime_t "." NANOSECONDS_FMT "/"        /* max wall time */
        "%" PRIdtime_t "." NANOSECONDS_FMT "\n",      /* avg wall time */
        _Timespec_Get_seconds( min_wall ),
          _Timespec_Get_nanoseconds( min_wall ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( max_wall ),
          _Timespec_Get_nanoseconds( max_wall ) / NANOSECONDS_DIVIDER,
        _Timespec_Get_seconds( &wall_average ),
          _Timespec_Get_nanoseconds( &wall_average ) / NANOSECONDS_DIVIDER
      );
    }
  }
}

void rtems_rate_monotonic_report_statistics( void )
{
  rtems_printer printer;
  rtems_print_printer_printk( &printer );
  rtems_rate_monotonic_report_statistics_with_plugin( &printer );
}