xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-rt/rt-tests/files/rt_bmark.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/usr/bin/env python3
2*4882a593Smuzhiyun# -*- coding: utf-8 -*-
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun# SPDX-License-Identifier:     BSD-3-Clause
5*4882a593Smuzhiyun# Copyright (C) 2015 Enea Software AB
6*4882a593Smuzhiyun# Author: Thomas Lundström <thomas.lundstrom@enea.com>
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun# The script measures interrupt latency together with different types of
9*4882a593Smuzhiyun# system load. This is done using the programs cyclictest and stress.
10*4882a593Smuzhiyun#
11*4882a593Smuzhiyun# The main output is:
12*4882a593Smuzhiyun#
13*4882a593Smuzhiyun#   Best case (min) latency
14*4882a593Smuzhiyun#     This has very limited value, but is presented since it can be done
15*4882a593Smuzhiyun#     easily
16*4882a593Smuzhiyun#
17*4882a593Smuzhiyun#   Average latency
18*4882a593Smuzhiyun#     This value is of interrest for throughput oriented systems. Limited
19*4882a593Smuzhiyun#     value for a real-time system. Also presented because it is easy to do.
20*4882a593Smuzhiyun#
21*4882a593Smuzhiyun#   Worst case (max) latency
22*4882a593Smuzhiyun#     This is the interesting number for a real-time system. The number
23*4882a593Smuzhiyun#     presented is (of cource) the largest number observed. The challenge
24*4882a593Smuzhiyun#     is to know how the observed worst case relates to the actual worst case.
25*4882a593Smuzhiyun#
26*4882a593Smuzhiyun#     To get an indication of the confidence, the following method is used:
27*4882a593Smuzhiyun#     1) Instead of one long run, the measurement is made as a set of shorter
28*4882a593Smuzhiyun#        runs. The number of runs must be a power of 2 for reasons that will
29*4882a593Smuzhiyun#        shorlty be obvious
30*4882a593Smuzhiyun#
31*4882a593Smuzhiyun#     2) First, a list of the max values are created.
32*4882a593Smuzhiyun#
33*4882a593Smuzhiyun#     3) The smallest value in that list is recorded.
34*4882a593Smuzhiyun#
35*4882a593Smuzhiyun#     4) Then a new list is create by taking the max value of each pair of
36*4882a593Smuzhiyun#        values in the original list. In this list the smallest value is
37*4882a593Smuzhiyun#        recorded.
38*4882a593Smuzhiyun#
39*4882a593Smuzhiyun#     5) Step 3 is repeated until there is only one value in the list. See
40*4882a593Smuzhiyun#        example below:
41*4882a593Smuzhiyun#
42*4882a593Smuzhiyun#        Samples:
43*4882a593Smuzhiyun#          |  44 |     |     |     |     |
44*4882a593Smuzhiyun#          |  77 |  77 |     |     |     |
45*4882a593Smuzhiyun#          | 118 |     |     |     |     |
46*4882a593Smuzhiyun#          | 119 | 119 | 119 |     |     |
47*4882a593Smuzhiyun#          | 138 |     |     |     |     |
48*4882a593Smuzhiyun#          |  57 | 138 |     |     |     |
49*4882a593Smuzhiyun#          | 175 |     |     |     |     |
50*4882a593Smuzhiyun#          | 130 | 175 | 175 | 175 |     |
51*4882a593Smuzhiyun#          |  54 |     |     |     |     |
52*4882a593Smuzhiyun#          | 150 | 150 |     |     |     |
53*4882a593Smuzhiyun#          |  47 |     |     |     |     |
54*4882a593Smuzhiyun#          |  59 |  59 | 150 |     |     |
55*4882a593Smuzhiyun#          | 199 |     |     |     |     |
56*4882a593Smuzhiyun#          | 115 | 199 |     |     |     |
57*4882a593Smuzhiyun#          | 177 |     |     |     |     |
58*4882a593Smuzhiyun#          | 129 | 177 | 199 | 199 | 199 |
59*4882a593Smuzhiyun#
60*4882a593Smuzhiyun#        Smallest value:
61*4882a593Smuzhiyun#          |  44 |  59 | 119 | 175 | 199 |
62*4882a593Smuzhiyun#
63*4882a593Smuzhiyun#     6) The generated list of smallest values is analyzed. In this case, it
64*4882a593Smuzhiyun#        can be observed that the values are increasing significantly through
65*4882a593Smuzhiyun#        the entire list, which leads to the conclusion that the number of
66*4882a593Smuzhiyun#        samples is too small.
67*4882a593Smuzhiyun#        If instead the list had been (167, 191, 196, 199, 199), there had
68*4882a593Smuzhiyun#        been a very small, or no, increase at the end of the list. We might
69*4882a593Smuzhiyun#        then suspect that the number of samples is probably large enough.
70*4882a593Smuzhiyun#        There is however no guarantee for that.
71*4882a593Smuzhiyun#
72*4882a593Smuzhiyun#     Steps 1-2 are done in run_cyclictest_suite
73*4882a593Smuzhiyun#     Steps 3-5 are done in gen_minmax_list.
74*4882a593Smuzhiyun#     Step 6 needs to be done manually since there is (yet) no well defined
75*4882a593Smuzhiyun#     FAIL criterion and a theoretically solid PASS criterion may never be
76*4882a593Smuzhiyun#     available.
77*4882a593Smuzhiyun
78*4882a593Smuzhiyunimport multiprocessing
79*4882a593Smuzhiyunimport os
80*4882a593Smuzhiyunimport re
81*4882a593Smuzhiyunimport signal
82*4882a593Smuzhiyunimport subprocess
83*4882a593Smuzhiyunimport time
84*4882a593Smuzhiyunimport traceback
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun# See comment on the function set_hung_tmo
87*4882a593Smuzhiyunhas_hung_task_detection = True
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun#-------------------------------------------------------------------------------
90*4882a593Smuzhiyun
91*4882a593Smuzhiyunclass TestFail(Exception):
92*4882a593Smuzhiyun        def __init__(self, msg):
93*4882a593Smuzhiyun                self.msg = msg
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun        def __str__(self):
96*4882a593Smuzhiyun                return "Test failure: (" + self.msg + ")"
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun#-------------------------------------------------------------------------------
99*4882a593Smuzhiyun
100*4882a593Smuzhiyundef tc_name(sub_name):
101*4882a593Smuzhiyun        return "rt_bmark.intlat." + sub_name
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun#-------------------------------------------------------------------------------
104*4882a593Smuzhiyun# log() does the same job as print except that a '#' is added at the beginning
105*4882a593Smuzhiyun# of each line. This causes TEFEL to ignore it
106*4882a593Smuzhiyun
107*4882a593Smuzhiyundef log(*msg):
108*4882a593Smuzhiyun        tmp = "".join(map(str, msg)) # 'map(str, ...' allows numbers
109*4882a593Smuzhiyun        for line in tmp.splitlines():
110*4882a593Smuzhiyun                print("#", line)
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun#-------------------------------------------------------------------------------
113*4882a593Smuzhiyun# Like log(), but with a timestamp added
114*4882a593Smuzhiyun
115*4882a593Smuzhiyundef log_ts(*msg):
116*4882a593Smuzhiyun        ts = time.localtime()
117*4882a593Smuzhiyun        stamp = "%2d:%02d:%02d: " % (ts.tm_hour, ts.tm_min, ts.tm_sec)
118*4882a593Smuzhiyun        log(stamp, *msg)
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun#-------------------------------------------------------------------------------
121*4882a593Smuzhiyun
122*4882a593Smuzhiyundef log_test_header(seq_no, nr_of_tests, name):
123*4882a593Smuzhiyun        log("=" * 78)
124*4882a593Smuzhiyun        log()
125*4882a593Smuzhiyun        log("  Test case (%d/%d): %s" % (seq_no, nr_of_tests, tc_name(name)))
126*4882a593Smuzhiyun        log()
127*4882a593Smuzhiyun        log("." * 78)
128*4882a593Smuzhiyun        log()
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun#-------------------------------------------------------------------------------
131*4882a593Smuzhiyun
132*4882a593Smuzhiyundef start_stress(*args):
133*4882a593Smuzhiyun        stress_cmd         = [ "stress-ng" ]
134*4882a593Smuzhiyun        added_stress_types = []
135*4882a593Smuzhiyun        req_stress_types   = set(args)
136*4882a593Smuzhiyun        cpu_cnt            = str(multiprocessing.cpu_count())
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun        # The function cond_add_stress appends the options to the stress
139*4882a593Smuzhiyun        # command if the stress type is in the set of requested stress types
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun        def cond_add_stress(stress_type, options):
142*4882a593Smuzhiyun                if stress_type in req_stress_types:
143*4882a593Smuzhiyun                        req_stress_types.remove(stress_type)
144*4882a593Smuzhiyun                        added_stress_types.append(stress_type)
145*4882a593Smuzhiyun                        stress_cmd.extend(options)
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun        #----------
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun        cond_add_stress("io",  ["-i", cpu_cnt])
150*4882a593Smuzhiyun        cond_add_stress("cpu", ["-c", cpu_cnt])
151*4882a593Smuzhiyun        cond_add_stress("hdd", ["-d", cpu_cnt, "--hdd-bytes", "20M"])
152*4882a593Smuzhiyun        cond_add_stress("vm",  ["-m", cpu_cnt, "--vm-bytes", "10M"])
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun        unknown = ", ".join(req_stress_types)
155*4882a593Smuzhiyun        if unknown != "":
156*4882a593Smuzhiyun            raise TestFail("Unknown stress type(s): %s" % unknown)
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun        if not added_stress_types:
159*4882a593Smuzhiyun                log("No stress requested")
160*4882a593Smuzhiyun                return None
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun        added          = "+".join(added_stress_types)
163*4882a593Smuzhiyun        stress_cmd_str = " ".join(stress_cmd)
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun        log("Starting stress(", added, ")")
166*4882a593Smuzhiyun        log("  Command: '", stress_cmd_str, "'")
167*4882a593Smuzhiyun        log()
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun        # start_new_session causes stress to be executed in a separate
170*4882a593Smuzhiyun        # session, => it gets a new process group (incl. children). It
171*4882a593Smuzhiyun        # can then be terminated using os.killpg in end_stress without
172*4882a593Smuzhiyun        # terminating this script.
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun        p = subprocess.Popen(stress_cmd, start_new_session=True)
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun        return p
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun#-------------------------------------------------------------------------------
179*4882a593Smuzhiyun
180*4882a593Smuzhiyundef end_stress(p):
181*4882a593Smuzhiyun        if p is None:
182*4882a593Smuzhiyun                # The value None indicates that no stress scenario was started
183*4882a593Smuzhiyun                return
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun        if p.poll() is not None:
186*4882a593Smuzhiyun                raise TestFail("stress prematurely terminated.")
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun        os.killpg(os.getpgid(p.pid), signal.SIGTERM)
189*4882a593Smuzhiyun        log("Terminated stress")
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun#-------------------------------------------------------------------------------
192*4882a593Smuzhiyun
193*4882a593Smuzhiyundef us2hms_str(us):
194*4882a593Smuzhiyun        s = (us+500000) // 1000000 # Round microseconds to s
195*4882a593Smuzhiyun        m = s//60
196*4882a593Smuzhiyun        s -= 60*m;
197*4882a593Smuzhiyun        h = m//60
198*4882a593Smuzhiyun        m -= 60*h
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun        return "%d:%02d:%02d" % (h, m, s)
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun#-------------------------------------------------------------------------------
203*4882a593Smuzhiyun# Sometime the hung task supervision is triggered during execution of
204*4882a593Smuzhiyun# cyclictest (cyclictest starves stress). To avoid that, the supervision
205*4882a593Smuzhiyun# is temporarily disabled
206*4882a593Smuzhiyun
207*4882a593Smuzhiyundef set_hung_tmo(new_tmo):
208*4882a593Smuzhiyun        global has_hung_task_detection
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun        tmo_file = "/proc/sys/kernel/hung_task_timeout_secs"
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun        if not has_hung_task_detection:
213*4882a593Smuzhiyun                return
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun        if not os.access(tmo_file, os.W_OK):
216*4882a593Smuzhiyun                log("Hung task detection not supported")
217*4882a593Smuzhiyun                log("  (File ", tmo_file, " not found)")
218*4882a593Smuzhiyun                has_hung_task_detection = False
219*4882a593Smuzhiyun                return
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun        orig_tmo = int(subprocess.check_output(["cat", tmo_file]).strip())
222*4882a593Smuzhiyun        if new_tmo != orig_tmo:
223*4882a593Smuzhiyun                cmd = ( "echo " + str(new_tmo) + " > " + tmo_file )
224*4882a593Smuzhiyun                subprocess.check_output(cmd, shell=True)
225*4882a593Smuzhiyun                log("Changed timeout for detection of hung tasks: ",
226*4882a593Smuzhiyun                    orig_tmo, " -> ", new_tmo)
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun        return orig_tmo
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun#-------------------------------------------------------------------------------
231*4882a593Smuzhiyun
232*4882a593Smuzhiyundef gen_minmax_list(max_list):
233*4882a593Smuzhiyun        res = [min(max_list)]
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun        while True:
236*4882a593Smuzhiyun                tmp = max_list
237*4882a593Smuzhiyun                max_list = []
238*4882a593Smuzhiyun                while tmp:
239*4882a593Smuzhiyun                        max_list.append(max(tmp.pop(0), tmp.pop(0)))
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun                res.append(min(max_list))
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun                if len(max_list) < 2:
244*4882a593Smuzhiyun                        return res
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun#-------------------------------------------------------------------------------
247*4882a593Smuzhiyun# Parameters for cyclictest:
248*4882a593Smuzhiyun#
249*4882a593Smuzhiyun# On the -S option (from cyclictest.c):
250*4882a593Smuzhiyun#  -S implies options -a -t -n and same priority of all threads
251*4882a593Smuzhiyun#    -a: One thread per core
252*4882a593Smuzhiyun#    -n: use clock_nanosleep instead of posix interval timers
253*4882a593Smuzhiyun#    -t: (without argument) Set number of threads to the number
254*4882a593Smuzhiyun#         of cpus
255*4882a593Smuzhiyun
256*4882a593Smuzhiyuninterval_core_0 = 100     # Timer interval on core 0 [us]
257*4882a593Smuzhiyuninterval_delta  = 20      # Interval increment for each core [us]
258*4882a593Smuzhiyunloop_count      = 30000   # Number of loops (on core 0).
259*4882a593Smuzhiyun
260*4882a593Smuzhiyuncmd = ("cyclictest",
261*4882a593Smuzhiyun       "-S",             # Standard SMP testing. See below
262*4882a593Smuzhiyun       "-p", "99",       # RT priority 99
263*4882a593Smuzhiyun       "-q",             # Quiet mode, i.e. print only a summary
264*4882a593Smuzhiyun       "-i", str(interval_core_0),
265*4882a593Smuzhiyun       "-d", str(interval_delta),
266*4882a593Smuzhiyun       "-l", str(loop_count)
267*4882a593Smuzhiyun       )
268*4882a593Smuzhiyunrex = re.compile(b"C:\s*(\d+).*Min:\s*(\d+).*Avg:\s*(\d+).*Max:\s*(\d+)")
269*4882a593Smuzhiyun
270*4882a593Smuzhiyundef run_cyclictest_once():
271*4882a593Smuzhiyun        res = subprocess.check_output(cmd)
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun        # minlist and maxlist are lists with the extremes for each core
274*4882a593Smuzhiyun        # avg_cnt is the sum of cycles for all cores
275*4882a593Smuzhiyun        # avg_sum is the sum of (cycle count*average) for each core
276*4882a593Smuzhiyun        #     Since cyclictest runs different number of cycles on
277*4882a593Smuzhiyun        #     different cores, avg_sum/avg_cnt gives a more accurate
278*4882a593Smuzhiyun        #     value of the overall average than just taking the average
279*4882a593Smuzhiyun        #     of each core's averages
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun        minlist = []
282*4882a593Smuzhiyun        maxlist = []
283*4882a593Smuzhiyun        avg_sum = 0
284*4882a593Smuzhiyun        avg_cnt = 0
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun        for line in res.splitlines():
287*4882a593Smuzhiyun                m = rex.search(line)
288*4882a593Smuzhiyun                if m is not None:
289*4882a593Smuzhiyun                        minlist.append(int(m.group(2)))
290*4882a593Smuzhiyun                        maxlist.append(int(m.group(4)))
291*4882a593Smuzhiyun                        n = int(m.group(1))
292*4882a593Smuzhiyun                        avg_sum += n * int(m.group(3))
293*4882a593Smuzhiyun                        avg_cnt += n
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun        return min(minlist), [avg_sum, avg_cnt], max(maxlist)
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun#-------------------------------------------------------------------------------
298*4882a593Smuzhiyun# A precondition for the tracking of min-max values is that
299*4882a593Smuzhiyun# the suite size os a power of 2.
300*4882a593Smuzhiyun
301*4882a593SmuzhiyunN          = 5
302*4882a593Smuzhiyunsuite_size = 2**N
303*4882a593Smuzhiyun
304*4882a593Smuzhiyunest_exec_time_once  = interval_core_0 * loop_count
305*4882a593Smuzhiyunest_exec_time_suite = suite_size * est_exec_time_once
306*4882a593Smuzhiyun
307*4882a593Smuzhiyundef run_cyclictest_suite():
308*4882a593Smuzhiyun        log("Starting cyclictest")
309*4882a593Smuzhiyun        log("  Command          : ", " ".join(cmd))
310*4882a593Smuzhiyun        log("  Number of cycles : ", loop_count*suite_size,
311*4882a593Smuzhiyun            " (", suite_size, " sets of ", loop_count, " cycles)")
312*4882a593Smuzhiyun        log("  Exec. time (est) : ", us2hms_str(est_exec_time_suite))
313*4882a593Smuzhiyun        log()
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun        orig_tmo = set_hung_tmo(0) # 0 => Disable
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun        # float('inf') emulates infinity. At least in the sense that it is
318*4882a593Smuzhiyun        # guaranteed to be larger than any actual number.
319*4882a593Smuzhiyun        ack_min = float('inf')
320*4882a593Smuzhiyun        ack_avg = [0, 0]
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun        log()
323*4882a593Smuzhiyun        log_ts("Start of execution")
324*4882a593Smuzhiyun        t = time.time()
325*4882a593Smuzhiyun        max_list = []
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun        for i in range(0, suite_size):
328*4882a593Smuzhiyun                tmp_min, tmp_avg, tmp_max = run_cyclictest_once()
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun                msg = "%2d/%2d:" % (i+1, suite_size)
331*4882a593Smuzhiyun                msg += " min: %4d" % tmp_min
332*4882a593Smuzhiyun                msg += " avg: %5.1f" % (float(tmp_avg[0])/tmp_avg[1])
333*4882a593Smuzhiyun                msg += " max: %4d" % tmp_max
334*4882a593Smuzhiyun                log_ts(msg)
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun                # Track minimum value
337*4882a593Smuzhiyun                if tmp_min < ack_min:
338*4882a593Smuzhiyun                        ack_min = tmp_min
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun                # Track smallest max value
341*4882a593Smuzhiyun                max_list.append(tmp_max)
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun                ack_avg[0] += tmp_avg[0]
344*4882a593Smuzhiyun                ack_avg[1] += tmp_avg[1]
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun        t = time.time()-t
347*4882a593Smuzhiyun        log_ts("Cyclictest completed. Actual execution time:",
348*4882a593Smuzhiyun               us2hms_str(t*1000000))
349*4882a593Smuzhiyun        log()
350*4882a593Smuzhiyun        set_hung_tmo(orig_tmo)
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun        return ack_min, float(ack_avg[0])/ack_avg[1], gen_minmax_list(max_list)
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun#-------------------------------------------------------------------------------
355*4882a593Smuzhiyun
356*4882a593Smuzhiyunclass cyclictest_runner:
357*4882a593Smuzhiyun        def run_test(self, seq_no, nr_of_tests, name, stressparams):
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun                try:
360*4882a593Smuzhiyun                        log_test_header(seq_no, nr_of_tests, name)
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun                        p = start_stress(*stressparams)
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun                        bm_min, bm_avg, bm_max_list = run_cyclictest_suite()
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun                        end_stress(p)
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun                        bm_max = bm_max_list[-1]
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun                        log()
371*4882a593Smuzhiyun                        log("Min: %d us" % bm_min)
372*4882a593Smuzhiyun                        log("Avg: %.1f us" % bm_avg)
373*4882a593Smuzhiyun                        log("Max: %d us" % bm_max)
374*4882a593Smuzhiyun                        log()
375*4882a593Smuzhiyun                        log("Max list: ", bm_max_list)
376*4882a593Smuzhiyun                        log()
377*4882a593Smuzhiyun                        log("PASS")
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun                        print()
380*4882a593Smuzhiyun                        print(tc_name(name), "[Min/us,Avg/us,Max/us]:",)
381*4882a593Smuzhiyun                        print("%d,%.1f,%d" % (bm_min,bm_avg, bm_max))
382*4882a593Smuzhiyun                        print("PASS:", tc_name(name))
383*4882a593Smuzhiyun                        print()
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun                except Exception:
386*4882a593Smuzhiyun                        log()
387*4882a593Smuzhiyun                        log("Exception!")
388*4882a593Smuzhiyun                        log()
389*4882a593Smuzhiyun                        log("Traceback:", traceback.format_exc())
390*4882a593Smuzhiyun                        log()
391*4882a593Smuzhiyun                        log("WD: ", os.getcwd())
392*4882a593Smuzhiyun                        log()
393*4882a593Smuzhiyun                        log("FAIL")
394*4882a593Smuzhiyun                        print()
395*4882a593Smuzhiyun                        print("FAIL:", tc_name(name))
396*4882a593Smuzhiyun                        print()
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun#-------------------------------------------------------------------------------
399*4882a593Smuzhiyun
400*4882a593Smuzhiyunrunner = cyclictest_runner()
401*4882a593Smuzhiyun
402*4882a593Smuzhiyuntests = (("no_stress", []),
403*4882a593Smuzhiyun         ("cpu",  ["cpu"]),
404*4882a593Smuzhiyun         ("hdd",  ["hdd"]),
405*4882a593Smuzhiyun         ("io",   ["io"]),
406*4882a593Smuzhiyun         ("vm",   ["vm"]),
407*4882a593Smuzhiyun         ("full", ["io", "cpu", "hdd", "vm"]),
408*4882a593Smuzhiyun         )
409*4882a593Smuzhiyun
410*4882a593Smuzhiyunnr_of_tests = len(tests)
411*4882a593Smuzhiyunfor seq_no, params in enumerate(tests, start=1):
412*4882a593Smuzhiyun        runner.run_test(seq_no, nr_of_tests, *params)
413