1#!/bin/sh
2
3debug=false;args=;time=true
4
5# temporary files used by this script
6my_awk=/tmp/.uptime.$$.awk
7my_log=/tmp/.uptime.$$.log
8
9# check for arguments - to override temporary file names
10yes=true
11while $yes && [ $# -gt 1 ]
12do
13  case $1 in
14    -v)
15      # verbose mode: print collected info
16      debug=true
17      shift
18      ;;
19    -vv)
20      # super verbose mode: print collected info and debug awk script
21      debug=true
22      args="$args debug=1"
23      shift
24      ;;
25    -notime)
26      # do not use time
27      time=false
28      shift
29      ;;
30    -CPU=*)
31      # CPU speed
32      args="$args `echo "$1" | cut -c2-`"
33      shift
34      ;;
35    *)
36      yes=false
37      ;;
38  esac
39done
40
41cat >$my_awk <<"AWKSCRIPT"
42
43BEGIN {
44   FS=" "
45   factor=0;           # we are measuring after-before as (-before) + (after),
46                       # so the factor before the test is -1, after the test is
47                       # +1.
48   uptime_total = 0;   # total system uptime (before/after)
49   uptime_idle  = 0;   # total idle uptime (before/after)
50   proctime_total = 0; # total time the test was running
51   proctime_work  = 0; # total CPU time that the test was using
52   cpu_time = 0;       # total time the CPU stats were measured on
53   cpu_MHz = 0;        # total kHz work for the CPU
54   cpu_eMHz = 0;       # effective CPU operating point
55   delete MHZtime;     # total time spent in various power states
56   kernel = 0;         # don't print separate kernel time statistics
57
58   # get variable assignments from ARGV
59   for (i=1; i<ARGC; i++)
60   {
61      arg = ARGV[i];
62      if      (gsub("^CPU=",     "",arg)) { cpu_eMHz = arg; }
63      else if (gsub("^debug=",   "",arg)) { debug    = arg; }
64      else if (arg == "kernel")           { kernel   = 1; }
65      else continue;
66      delete ARGV[i]; # we can do this is AWK, and we don't need to decrement i
67   }
68}
69
70/^[0-9]+\./ {  # /proc/uptime lines
71   # the first time an uptime line is encountered factor should be -1, the
72   # second time it should be 1.  We set it to 0 at the beginning, so we use
73   # that to decide if it is the 1st uptime line
74   factor = factor ? 1 : -1
75   # get uptime stats (for beginning or end)
76   uptime_total += factor * $1
77   uptime_idle  += factor * $2
78   if (debug)
79   {
80      print "got(/proc/uptime):", $0, "=>", factor, uptime_total, uptime_idle
81   }
82}
83
84/^[0-9]+ / {   # /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state lines
85   # get time spent in various power states (in 10ms)
86   MHZtime[$1] += factor * $2 * 0.01
87   cpu_time += factor * $2 * 0.01
88   cpu_MHz += factor * $1 * $2 / 100000 # (CPU freq is in kHz)
89   if (debug)
90   {
91      print "got(/sys/..time_in_state):", $0, "=>", factor, cpu_time, cpu_MHz, MHZtime[$1]
92   }
93}
94
95/^(real|user|sys)/ {
96   # test has run
97   factor=1
98   # get time (from h m s notation to seconds)
99   time=0
100   for (i = 2; i <= NF; i++)
101   {
102      if ($i ~ /h/)
103      {
104         time += 3600 * $i
105      }
106      else if ($i ~ /m/)
107      {
108         time += 60 * $i
109      }
110      else
111      {  # this works for both POSIX and normal output
112         time += 1 * $i
113      }
114      if (debug)
115      {
116         print "got (" $i ") =>", time
117      }
118   }
119
120   if ($1 ~ /real/)
121   {
122      proctime_total = time
123   }
124   else
125   {
126      proctime_work += time;
127      if (kernel && ($1 ~ /sys/))
128      {
129         proctime_kernel += time;
130      }
131   }
132
133   if (debug)
134   {
135      print "got(time)", $0, "=>", proctime_total, proctime_work
136   }
137}
138
139END {
140   print "ARMtime Results"
141
142   if (proctime_total)
143   {
144      dur_time = ", " proctime_total " (time)"
145   }
146   if (cpu_time)
147   {
148      dur_cpu = ", " cpu_time " (cpu-stats)"
149   }
150
151   print " Test duration:", uptime_total, "(uptime)" dur_time dur_cpu
152
153   # calculate CPU MHz for test
154   cpu_states = 0
155   for (i in MHZtime)
156   {
157      if (MHZtime[i] > 0)
158      {
159         print " ARM-CPU time at", i/1000, "MHz: ", MHZtime[i], "s"
160         cpu_states ++;
161      }
162   }
163
164   if (cpu_time)
165   {
166      cpu_eMHz = cpu_MHz/cpu_time
167   }
168   else if (cpu_states)
169   {
170      cpu_eMHz /= cpu_states
171   }
172   else if (cpu_eMHz == 0)
173   {
174      "grep mpu /proc/omap_clocks /proc/ckomap24xx" | getline clock_speed
175      split(clock_speed, clock_speeds)
176      if (debug) {
177         print "got", clock_speed
178         print "got", clock_speeds[1], clock_speeds[2], clock_speeds[3]
179      }
180      cpu_eMHz = clock_speeds[3] / 1000000
181   }
182
183   # mark ~ if we are not sure about the CPU-speed (e.g. if we had more than one
184   # power states during the test run)
185   cpu_sureness = (cpu_states == 1) ? "" : "~"
186
187   cpu_eMHz /= 100  # so we can multiply with the %-s
188   if (uptime_total > 0)
189   {
190      # WE always will use uptime total
191      uptime_idle -= uptime_total
192      util = int(0.5 - 1000 * uptime_idle/uptime_total) / 10
193
194      # don't let utilization be negative (because it is infact 0)
195      if (util < 0)
196      {
197         util = 0
198      }
199
200      print " Total ARM-CPU utilization:", util "% =", cpu_sureness (util * cpu_eMHz), "eMHz"
201      if (proctime_total)
202      {
203         util = int(0.5 + 1000 * proctime_work/uptime_total) / 10
204         print " Test  ARM-CPU utilization:", util "% =", cpu_sureness (util * cpu_eMHz), "eMHz"
205
206         if (kernel)
207         {
208            util = int(0.5 + 1000 * proctime_kernel/uptime_total) / 10
209            proc_util = int(0.5 + 1000 * proctime_kernel/proctime_work) / 10
210            print " Test's kernel space util.:", util "% =", cpu_sureness (util * cpu_eMHz), "eMHz (" proc_util "% of test thread)"
211         }
212      }
213   }
214}
215AWKSCRIPT
216
217# run measurement
218cat /proc/uptime /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state >$my_log
219if $time
220then
221  time -p $* 2>>$my_log
222else
223  $*
224fi
225cat /proc/uptime /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state >>$my_log
226
227# evaluate and debug
228$debug && cat $my_log
229awk -f $my_awk $args $my_log
230
231# remove temporary files
232rm $my_log $my_awk
233
234