mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Power management updates for 4.18-rc1
These include a significant update of the generic power domains (genpd)
and Operating Performance Points (OPP) frameworks, mostly related to
the introduction of power domain performance levels, cpufreq updates
(new driver for Qualcomm Kryo processors, updates of the existing
drivers, some core fixes, schedutil governor improvements), PCI power
management fixes, ACPI workaround for EC-based wakeup events handling
on resume from suspend-to-idle, and major updates of the turbostat
and pm-graph utilities.
Specifics:
- Introduce power domain performance levels into the the generic
power domains (genpd) and Operating Performance Points (OPP)
frameworks (Viresh Kumar, Rajendra Nayak, Dan Carpenter).
- Fix two issues in the runtime PM framework related to the
initialization and removal of devices using device links (Ulf
Hansson).
- Clean up the initialization of drivers for devices in PM domains
(Ulf Hansson, Geert Uytterhoeven).
- Fix a cpufreq core issue related to the policy sysfs interface
causing CPU online to fail for CPUs sharing one cpufreq policy in
some situations (Tao Wang).
- Make it possible to use platform-specific suspend/resume hooks
in the cpufreq-dt driver and make the Armada 37xx DVFS use that
feature (Viresh Kumar, Miquel Raynal).
- Optimize policy transition notifications in cpufreq (Viresh Kumar).
- Improve the iowait boost mechanism in the schedutil cpufreq
governor (Patrick Bellasi).
- Improve the handling of deferred frequency updates in the
schedutil cpufreq governor (Joel Fernandes, Dietmar Eggemann,
Rafael Wysocki, Viresh Kumar).
- Add a new cpufreq driver for Qualcomm Kryo (Ilia Lin).
- Fix and clean up some cpufreq drivers (Colin Ian King, Dmitry
Osipenko, Doug Smythies, Luc Van Oostenryck, Simon Horman,
Viresh Kumar).
- Fix the handling of PCI devices with the DPM_SMART_SUSPEND flag
set and update stale comments in the PCI core PM code (Rafael
Wysocki).
- Work around an issue related to the handling of EC-based wakeup
events in the ACPI PM core during resume from suspend-to-idle if
the EC has been put into the low-power mode (Rafael Wysocki).
- Improve the handling of wakeup source objects in the PM core (Doug
Berger, Mahendran Ganesh, Rafael Wysocki).
- Update the driver core to prevent deferred probe from breaking
suspend/resume ordering (Feng Kan).
- Clean up the PM core somewhat (Bjorn Helgaas, Ulf Hansson, Rafael
Wysocki).
- Make the core suspend/resume code and cpufreq support the RT patch
(Sebastian Andrzej Siewior, Thomas Gleixner).
- Consolidate the PM QoS handling in cpuidle governors (Rafael
Wysocki).
- Fix a possible crash in the hibernation core (Tetsuo Handa).
- Update the rockchip-io Adaptive Voltage Scaling (AVS) driver
(David Wu).
- Update the turbostat utility (fixes, cleanups, new CPU IDs, new
command line options, built-in "Low Power Idle" counters support,
new POLL and POLL% columns) and add an entry for it to MAINTAINERS
(Len Brown, Artem Bityutskiy, Chen Yu, Laura Abbott, Matt Turner,
Prarit Bhargava, Srinivas Pandruvada).
- Update the pm-graph to version 5.1 (Todd Brandt).
- Update the intel_pstate_tracer utility (Doug Smythies).
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2
iQIcBAABCAAGBQJbFRzjAAoJEILEb/54YlRxREQQAKD7IjnLA86ZDkmwiwzFa9Cz
OJ0qlKAcMZGjeWH6LYq7lqWtaJ5PcFkBwNB4sRyKFdGPQOX3Ph8ZzILm2j8hhma4
Azn9632P6CoYHABa8Vof+A1BZ/j0aWtvtJEfqXhtF6rAYyWQlF0UmOIRsMs+54a+
Z/w4WuLaX8qYq3JlR60TogNtTIbdUjkjfvxMGrE9OSQ8n4oEhqoF/v0WoTHYLpWw
fu81M378axOu0Sgq1ZQ8GPUdblUqIO97iWwF7k2YUl7D9n5dm4wOhXDz3CLI8Cdb
RkoFFdp8bJIthbc5desKY2XFU1ClY8lxEVMXewFzTGwWMw0OyWgQP0/ZiG+Mujq3
CSbstg8GGpbwQoWU+VrluYa0FtqofV2UaGk1gOuPaojMqaIchRU4Nmbd2U6naNwp
XN7A1DzrOVGEt0ny8ztKH2Oqmj+NOCcRsChlYzdhLQ1wlqG54iCGwAML2ZJF9/Nw
0Sx8hm6eyWLzjSa0L384Msb+v5oqCoac66gPHCl2x7W+3F+jmqx1KbmkI2SRNUAL
7CS9lcImpvC4uZB54Aqya104vfqHiDse7WP0GrKqOmNVucD7hYCPiq/pycLwez+b
V3zLyvly8PsuBIa4AOQGGiK45HGpaKuB4TkRqRyFO0Fb5uL1M+Ld6kJiWlacl4az
STEUjY/90SRQvX3ocGyB
=wqBV
-----END PGP SIGNATURE-----
Merge tag 'pm-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management updates from Rafael Wysocki:
"These include a significant update of the generic power domains
(genpd) and Operating Performance Points (OPP) frameworks, mostly
related to the introduction of power domain performance levels,
cpufreq updates (new driver for Qualcomm Kryo processors, updates of
the existing drivers, some core fixes, schedutil governor
improvements), PCI power management fixes, ACPI workaround for
EC-based wakeup events handling on resume from suspend-to-idle, and
major updates of the turbostat and pm-graph utilities.
Specifics:
- Introduce power domain performance levels into the the generic
power domains (genpd) and Operating Performance Points (OPP)
frameworks (Viresh Kumar, Rajendra Nayak, Dan Carpenter).
- Fix two issues in the runtime PM framework related to the
initialization and removal of devices using device links (Ulf
Hansson).
- Clean up the initialization of drivers for devices in PM domains
(Ulf Hansson, Geert Uytterhoeven).
- Fix a cpufreq core issue related to the policy sysfs interface
causing CPU online to fail for CPUs sharing one cpufreq policy in
some situations (Tao Wang).
- Make it possible to use platform-specific suspend/resume hooks in
the cpufreq-dt driver and make the Armada 37xx DVFS use that
feature (Viresh Kumar, Miquel Raynal).
- Optimize policy transition notifications in cpufreq (Viresh Kumar).
- Improve the iowait boost mechanism in the schedutil cpufreq
governor (Patrick Bellasi).
- Improve the handling of deferred frequency updates in the schedutil
cpufreq governor (Joel Fernandes, Dietmar Eggemann, Rafael Wysocki,
Viresh Kumar).
- Add a new cpufreq driver for Qualcomm Kryo (Ilia Lin).
- Fix and clean up some cpufreq drivers (Colin Ian King, Dmitry
Osipenko, Doug Smythies, Luc Van Oostenryck, Simon Horman, Viresh
Kumar).
- Fix the handling of PCI devices with the DPM_SMART_SUSPEND flag set
and update stale comments in the PCI core PM code (Rafael Wysocki).
- Work around an issue related to the handling of EC-based wakeup
events in the ACPI PM core during resume from suspend-to-idle if
the EC has been put into the low-power mode (Rafael Wysocki).
- Improve the handling of wakeup source objects in the PM core (Doug
Berger, Mahendran Ganesh, Rafael Wysocki).
- Update the driver core to prevent deferred probe from breaking
suspend/resume ordering (Feng Kan).
- Clean up the PM core somewhat (Bjorn Helgaas, Ulf Hansson, Rafael
Wysocki).
- Make the core suspend/resume code and cpufreq support the RT patch
(Sebastian Andrzej Siewior, Thomas Gleixner).
- Consolidate the PM QoS handling in cpuidle governors (Rafael
Wysocki).
- Fix a possible crash in the hibernation core (Tetsuo Handa).
- Update the rockchip-io Adaptive Voltage Scaling (AVS) driver (David
Wu).
- Update the turbostat utility (fixes, cleanups, new CPU IDs, new
command line options, built-in "Low Power Idle" counters support,
new POLL and POLL% columns) and add an entry for it to MAINTAINERS
(Len Brown, Artem Bityutskiy, Chen Yu, Laura Abbott, Matt Turner,
Prarit Bhargava, Srinivas Pandruvada).
- Update the pm-graph to version 5.1 (Todd Brandt).
- Update the intel_pstate_tracer utility (Doug Smythies)"
* tag 'pm-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (128 commits)
tools/power turbostat: update version number
tools/power turbostat: Add Node in output
tools/power turbostat: add node information into turbostat calculations
tools/power turbostat: remove num_ from cpu_topology struct
tools/power turbostat: rename num_cores_per_pkg to num_cores_per_node
tools/power turbostat: track thread ID in cpu_topology
tools/power turbostat: Calculate additional node information for a package
tools/power turbostat: Fix node and siblings lookup data
tools/power turbostat: set max_num_cpus equal to the cpumask length
tools/power turbostat: if --num_iterations, print for specific number of iterations
tools/power turbostat: Add Cannon Lake support
tools/power turbostat: delete duplicate #defines
x86: msr-index.h: Correct SNB_C1/C3_AUTO_UNDEMOTE defines
tools/power turbostat: Correct SNB_C1/C3_AUTO_UNDEMOTE defines
tools/power turbostat: add POLL and POLL% column
tools/power turbostat: Fix --hide Pk%pc10
tools/power turbostat: Build-in "Low Power Idle" counters support
tools/power turbostat: Don't make man pages executable
tools/power turbostat: remove blank lines
tools/power turbostat: a small C-states dump readability immprovement
...
This commit is contained in:
commit
3c89adb0d1
78 changed files with 3235 additions and 1192 deletions
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# Tool for analyzing boot timing
|
||||
# Copyright (c) 2013, Intel Corporation.
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ Create a summary page of all tests in \fIindir\fR. Creates summary.html
|
|||
in the current folder. The output page is a table of tests with
|
||||
suspend and resume values sorted by suspend mode, host, and kernel.
|
||||
Includes test averages by mode and links to the test html files.
|
||||
Use -genhtml to include tests with missing html.
|
||||
.TP
|
||||
\fB-modes\fR
|
||||
List available suspend modes.
|
||||
|
|
@ -179,6 +180,9 @@ with any options you intend to use to see if they will work.
|
|||
\fB-fpdt\fR
|
||||
Print out the contents of the ACPI Firmware Performance Data Table.
|
||||
.TP
|
||||
\fB-battery\fR
|
||||
Print out battery status and current charge.
|
||||
.TP
|
||||
\fB-sysinfo\fR
|
||||
Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/python2
|
||||
#
|
||||
# Tool for analyzing suspend/resume timing
|
||||
# Copyright (c) 2013, Intel Corporation.
|
||||
|
|
@ -69,7 +69,7 @@ from subprocess import call, Popen, PIPE
|
|||
# store system values and test parameters
|
||||
class SystemValues:
|
||||
title = 'SleepGraph'
|
||||
version = '5.0'
|
||||
version = '5.1'
|
||||
ansi = False
|
||||
rs = 0
|
||||
display = 0
|
||||
|
|
@ -240,7 +240,7 @@ class SystemValues:
|
|||
kprobes = dict()
|
||||
timeformat = '%.3f'
|
||||
cmdline = '%s %s' % \
|
||||
(os.path.basename(sys.argv[0]), string.join(sys.argv[1:], ' '))
|
||||
(os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:]))
|
||||
def __init__(self):
|
||||
self.archargs = 'args_'+platform.machine()
|
||||
self.hostname = platform.node()
|
||||
|
|
@ -917,12 +917,18 @@ class Data:
|
|||
self.devicegroups.append([phase])
|
||||
self.errorinfo = {'suspend':[],'resume':[]}
|
||||
def extractErrorInfo(self):
|
||||
elist = {
|
||||
'HWERROR' : '.*\[ *Hardware Error *\].*',
|
||||
'FWBUG' : '.*\[ *Firmware Bug *\].*',
|
||||
'BUG' : '.*BUG.*',
|
||||
'ERROR' : '.*ERROR.*',
|
||||
'WARNING' : '.*WARNING.*',
|
||||
'IRQ' : '.*genirq: .*',
|
||||
'TASKFAIL': '.*Freezing of tasks failed.*',
|
||||
}
|
||||
lf = sysvals.openlog(sysvals.dmesgfile, 'r')
|
||||
i = 0
|
||||
list = []
|
||||
# sl = start line, et = error time, el = error line
|
||||
type = 'ERROR'
|
||||
sl = et = el = -1
|
||||
for line in lf:
|
||||
i += 1
|
||||
m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
|
||||
|
|
@ -931,43 +937,13 @@ class Data:
|
|||
t = float(m.group('ktime'))
|
||||
if t < self.start or t > self.end:
|
||||
continue
|
||||
if t < self.tSuspended:
|
||||
dir = 'suspend'
|
||||
else:
|
||||
dir = 'resume'
|
||||
dir = 'suspend' if t < self.tSuspended else 'resume'
|
||||
msg = m.group('msg')
|
||||
if re.match('-*\[ *cut here *\]-*', msg):
|
||||
type = 'WARNING'
|
||||
sl = i
|
||||
elif re.match('genirq: .*', msg):
|
||||
type = 'IRQ'
|
||||
sl = i
|
||||
elif re.match('BUG: .*', msg) or re.match('kernel BUG .*', msg):
|
||||
type = 'BUG'
|
||||
sl = i
|
||||
elif re.match('-*\[ *end trace .*\]-*', msg) or \
|
||||
re.match('R13: .*', msg):
|
||||
if et >= 0 and sl >= 0:
|
||||
list.append((type, dir, et, sl, i))
|
||||
for err in elist:
|
||||
if re.match(elist[err], msg):
|
||||
list.append((err, dir, t, i, i))
|
||||
self.kerror = True
|
||||
sl = et = el = -1
|
||||
type = 'ERROR'
|
||||
elif 'Call Trace:' in msg:
|
||||
if el >= 0 and et >= 0:
|
||||
list.append((type, dir, et, el, el))
|
||||
self.kerror = True
|
||||
et, el = t, i
|
||||
if sl < 0 or type == 'BUG':
|
||||
slval = i
|
||||
if sl >= 0:
|
||||
slval = sl
|
||||
list.append((type, dir, et, slval, i))
|
||||
self.kerror = True
|
||||
sl = et = el = -1
|
||||
type = 'ERROR'
|
||||
if el >= 0 and et >= 0:
|
||||
list.append((type, dir, et, el, el))
|
||||
self.kerror = True
|
||||
break
|
||||
for e in list:
|
||||
type, dir, t, idx1, idx2 = e
|
||||
sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
|
||||
|
|
@ -2331,12 +2307,14 @@ class TestProps:
|
|||
sv.suspendmode = data.stamp['mode']
|
||||
if sv.suspendmode == 'command' and sv.ftracefile != '':
|
||||
modes = ['on', 'freeze', 'standby', 'mem', 'disk']
|
||||
out = Popen(['grep', 'machine_suspend', sv.ftracefile],
|
||||
stderr=PIPE, stdout=PIPE).stdout.read()
|
||||
m = re.match('.* machine_suspend\[(?P<mode>.*)\]', out)
|
||||
if m and m.group('mode') in ['1', '2', '3', '4']:
|
||||
sv.suspendmode = modes[int(m.group('mode'))]
|
||||
data.stamp['mode'] = sv.suspendmode
|
||||
fp = sysvals.openlog(sv.ftracefile, 'r')
|
||||
for line in fp:
|
||||
m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line)
|
||||
if m and m.group('mode') in ['1', '2', '3', '4']:
|
||||
sv.suspendmode = modes[int(m.group('mode'))]
|
||||
data.stamp['mode'] = sv.suspendmode
|
||||
break
|
||||
fp.close()
|
||||
m = re.match(self.cmdlinefmt, self.cmdline)
|
||||
if m:
|
||||
sv.cmdline = m.group('cmd')
|
||||
|
|
@ -2413,7 +2391,7 @@ class ProcessMonitor:
|
|||
# markers, and/or kprobes required for primary parsing.
|
||||
def doesTraceLogHaveTraceEvents():
|
||||
kpcheck = ['_cal: (', '_cpu_down()']
|
||||
techeck = sysvals.traceevents[:]
|
||||
techeck = ['suspend_resume']
|
||||
tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
|
||||
sysvals.usekprobes = False
|
||||
fp = sysvals.openlog(sysvals.ftracefile, 'r')
|
||||
|
|
@ -2808,7 +2786,7 @@ def parseTraceLog(live=False):
|
|||
# -- phase changes --
|
||||
# start of kernel suspend
|
||||
if(re.match('suspend_enter\[.*', t.name)):
|
||||
if(isbegin):
|
||||
if(isbegin and data.start == data.tKernSus):
|
||||
data.dmesg[phase]['start'] = t.time
|
||||
data.tKernSus = t.time
|
||||
continue
|
||||
|
|
@ -3072,13 +3050,20 @@ def parseTraceLog(live=False):
|
|||
sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name))
|
||||
cg.newActionFromFunction(data)
|
||||
if sysvals.suspendmode == 'command':
|
||||
return testdata
|
||||
return (testdata, '')
|
||||
|
||||
# fill in any missing phases
|
||||
error = []
|
||||
for data in testdata:
|
||||
tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1))
|
||||
terr = ''
|
||||
lp = data.phases[0]
|
||||
for p in data.phases:
|
||||
if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0):
|
||||
if not terr:
|
||||
print 'TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp)
|
||||
terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp)
|
||||
error.append(terr)
|
||||
sysvals.vprint('WARNING: phase "%s" is missing!' % p)
|
||||
if(data.dmesg[p]['start'] < 0):
|
||||
data.dmesg[p]['start'] = data.dmesg[lp]['end']
|
||||
|
|
@ -3106,7 +3091,7 @@ def parseTraceLog(live=False):
|
|||
for j in range(i + 1, tc):
|
||||
testdata[j].mergeOverlapDevices(devlist)
|
||||
testdata[0].stitchTouchingThreads(testdata[1:])
|
||||
return testdata
|
||||
return (testdata, ', '.join(error))
|
||||
|
||||
# Function: loadKernelLog
|
||||
# Description:
|
||||
|
|
@ -3173,7 +3158,7 @@ def loadKernelLog():
|
|||
if data:
|
||||
testruns.append(data)
|
||||
if len(testruns) < 1:
|
||||
doError(' dmesg log has no suspend/resume data: %s' \
|
||||
print('ERROR: dmesg log has no suspend/resume data: %s' \
|
||||
% sysvals.dmesgfile)
|
||||
|
||||
# fix lines with same timestamp/function with the call and return swapped
|
||||
|
|
@ -3521,68 +3506,144 @@ def createHTMLSummarySimple(testruns, htmlfile, folder):
|
|||
.summary {border:1px solid;}\n\
|
||||
th {border: 1px solid black;background:#222;color:white;}\n\
|
||||
td {font: 16px "Times New Roman";text-align: center;}\n\
|
||||
tr.alt td {background:#ddd;}\n\
|
||||
tr.avg td {background:#aaa;}\n\
|
||||
tr.head td {border: 1px solid black;background:#aaa;}\n\
|
||||
tr.alt {background-color:#ddd;}\n\
|
||||
tr.notice {color:red;}\n\
|
||||
.minval {background-color:#BBFFBB;}\n\
|
||||
.medval {background-color:#BBBBFF;}\n\
|
||||
.maxval {background-color:#FFBBBB;}\n\
|
||||
.head a {color:#000;text-decoration: none;}\n\
|
||||
</style>\n</head>\n<body>\n'
|
||||
|
||||
# extract the test data into list
|
||||
list = dict()
|
||||
tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []]
|
||||
iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
|
||||
num = 0
|
||||
lastmode = ''
|
||||
cnt = {'pass':0, 'fail':0, 'hang':0}
|
||||
for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
|
||||
mode = data['mode']
|
||||
if mode not in list:
|
||||
list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]}
|
||||
if lastmode and lastmode != mode and num > 0:
|
||||
for i in range(2):
|
||||
s = sorted(tMed[i])
|
||||
list[lastmode]['med'][i] = s[int(len(s)/2)]
|
||||
iMed[i] = tMed[i].index(list[lastmode]['med'][i])
|
||||
list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
|
||||
list[lastmode]['min'] = tMin
|
||||
list[lastmode]['max'] = tMax
|
||||
list[lastmode]['idx'] = (iMin, iMed, iMax)
|
||||
tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []]
|
||||
iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
|
||||
num = 0
|
||||
tVal = [float(data['suspend']), float(data['resume'])]
|
||||
list[mode]['data'].append([data['host'], data['kernel'],
|
||||
data['time'], tVal[0], tVal[1], data['url'], data['result'],
|
||||
data['issues']])
|
||||
idx = len(list[mode]['data']) - 1
|
||||
if data['result'] == 'pass':
|
||||
cnt['pass'] += 1
|
||||
for i in range(2):
|
||||
tMed[i].append(tVal[i])
|
||||
tAvg[i] += tVal[i]
|
||||
if tMin[i] == 0 or tVal[i] < tMin[i]:
|
||||
iMin[i] = idx
|
||||
tMin[i] = tVal[i]
|
||||
if tMax[i] == 0 or tVal[i] > tMax[i]:
|
||||
iMax[i] = idx
|
||||
tMax[i] = tVal[i]
|
||||
num += 1
|
||||
elif data['result'] == 'hang':
|
||||
cnt['hang'] += 1
|
||||
elif data['result'] == 'fail':
|
||||
cnt['fail'] += 1
|
||||
lastmode = mode
|
||||
if lastmode and num > 0:
|
||||
for i in range(2):
|
||||
s = sorted(tMed[i])
|
||||
list[lastmode]['med'][i] = s[int(len(s)/2)]
|
||||
iMed[i] = tMed[i].index(list[lastmode]['med'][i])
|
||||
list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
|
||||
list[lastmode]['min'] = tMin
|
||||
list[lastmode]['max'] = tMax
|
||||
list[lastmode]['idx'] = (iMin, iMed, iMax)
|
||||
|
||||
# group test header
|
||||
html += '<div class="stamp">%s (%d tests)</div>\n' % (folder, len(testruns))
|
||||
desc = []
|
||||
for ilk in sorted(cnt, reverse=True):
|
||||
if cnt[ilk] > 0:
|
||||
desc.append('%d %s' % (cnt[ilk], ilk))
|
||||
html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (folder, len(testruns), ', '.join(desc))
|
||||
th = '\t<th>{0}</th>\n'
|
||||
td = '\t<td>{0}</td>\n'
|
||||
tdh = '\t<td{1}>{0}</td>\n'
|
||||
tdlink = '\t<td><a href="{0}">html</a></td>\n'
|
||||
|
||||
# table header
|
||||
html += '<table class="summary">\n<tr>\n' + th.format('#') +\
|
||||
th.format('Mode') + th.format('Host') + th.format('Kernel') +\
|
||||
th.format('Test Time') + th.format('Suspend') + th.format('Resume') +\
|
||||
th.format('Detail') + '</tr>\n'
|
||||
th.format('Test Time') + th.format('Result') + th.format('Issues') +\
|
||||
th.format('Suspend') + th.format('Resume') + th.format('Detail') + '</tr>\n'
|
||||
|
||||
# test data, 1 row per test
|
||||
avg = '<tr class="avg"><td></td><td></td><td></td><td></td>'+\
|
||||
'<td>Average of {0} {1} tests</td><td>{2}</td><td>{3}</td><td></td></tr>\n'
|
||||
sTimeAvg = rTimeAvg = 0.0
|
||||
mode = ''
|
||||
num = 0
|
||||
for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
|
||||
if mode != data['mode']:
|
||||
# test average line
|
||||
if(num > 0):
|
||||
sTimeAvg /= (num - 1)
|
||||
rTimeAvg /= (num - 1)
|
||||
html += avg.format('%d' % (num - 1), mode,
|
||||
'%3.3f ms' % sTimeAvg, '%3.3f ms' % rTimeAvg)
|
||||
sTimeAvg = rTimeAvg = 0.0
|
||||
mode = data['mode']
|
||||
num = 1
|
||||
# alternate row color
|
||||
if num % 2 == 1:
|
||||
html += '<tr class="alt">\n'
|
||||
# export list into html
|
||||
head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\
|
||||
'<td colspan=8 class="sus">Suspend Avg={2} '+\
|
||||
'<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\
|
||||
'<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\
|
||||
'<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\
|
||||
'Resume Avg={6} '+\
|
||||
'<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\
|
||||
'<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\
|
||||
'<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\
|
||||
'</tr>\n'
|
||||
headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan=8></td></tr>\n'
|
||||
for mode in list:
|
||||
# header line for each suspend mode
|
||||
num = 0
|
||||
tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\
|
||||
list[mode]['max'], list[mode]['med']
|
||||
count = len(list[mode]['data'])
|
||||
if 'idx' in list[mode]:
|
||||
iMin, iMed, iMax = list[mode]['idx']
|
||||
html += head.format('%d' % count, mode.upper(),
|
||||
'%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0],
|
||||
'%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1],
|
||||
mode.lower()
|
||||
)
|
||||
else:
|
||||
html += '<tr>\n'
|
||||
html += td.format("%d" % num)
|
||||
num += 1
|
||||
# basic info
|
||||
for item in ['mode', 'host', 'kernel', 'time']:
|
||||
val = "unknown"
|
||||
if(item in data):
|
||||
val = data[item]
|
||||
html += td.format(val)
|
||||
# suspend time
|
||||
sTime = float(data['suspend'])
|
||||
sTimeAvg += sTime
|
||||
html += td.format('%.3f ms' % sTime)
|
||||
# resume time
|
||||
rTime = float(data['resume'])
|
||||
rTimeAvg += rTime
|
||||
html += td.format('%.3f ms' % rTime)
|
||||
# link to the output html
|
||||
html += tdlink.format(data['url']) + '</tr>\n'
|
||||
# last test average line
|
||||
if(num > 0):
|
||||
sTimeAvg /= (num - 1)
|
||||
rTimeAvg /= (num - 1)
|
||||
html += avg.format('%d' % (num - 1), mode,
|
||||
'%3.3f ms' % sTimeAvg, '%3.3f ms' % rTimeAvg)
|
||||
iMin = iMed = iMax = [-1, -1, -1]
|
||||
html += headnone.format('%d' % count, mode.upper())
|
||||
for d in list[mode]['data']:
|
||||
# row classes - alternate row color
|
||||
rcls = ['alt'] if num % 2 == 1 else []
|
||||
if d[6] != 'pass':
|
||||
rcls.append('notice')
|
||||
html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
|
||||
# figure out if the line has sus or res highlighted
|
||||
idx = list[mode]['data'].index(d)
|
||||
tHigh = ['', '']
|
||||
for i in range(2):
|
||||
tag = 's%s' % mode if i == 0 else 'r%s' % mode
|
||||
if idx == iMin[i]:
|
||||
tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag
|
||||
elif idx == iMax[i]:
|
||||
tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag
|
||||
elif idx == iMed[i]:
|
||||
tHigh[i] = ' id="%smed" class=medval title="Median"' % tag
|
||||
html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row
|
||||
html += td.format(mode) # mode
|
||||
html += td.format(d[0]) # host
|
||||
html += td.format(d[1]) # kernel
|
||||
html += td.format(d[2]) # time
|
||||
html += td.format(d[6]) # result
|
||||
html += td.format(d[7]) # issues
|
||||
html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('') # suspend
|
||||
html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('') # resume
|
||||
html += tdlink.format(d[5]) if d[5] else td.format('') # url
|
||||
html += '</tr>\n'
|
||||
num += 1
|
||||
|
||||
# flush the data to file
|
||||
hf = open(htmlfile, 'w')
|
||||
|
|
@ -3607,7 +3668,7 @@ def ordinal(value):
|
|||
# testruns: array of Data objects from parseKernelLog or parseTraceLog
|
||||
# Output:
|
||||
# True if the html file was created, false if it failed
|
||||
def createHTML(testruns):
|
||||
def createHTML(testruns, testfail):
|
||||
if len(testruns) < 1:
|
||||
print('ERROR: Not enough test data to build a timeline')
|
||||
return
|
||||
|
|
@ -3641,6 +3702,7 @@ def createHTML(testruns):
|
|||
'<td class="purple">{4}Firmware Resume: {2} ms</td>'\
|
||||
'<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\
|
||||
'</tr>\n</table>\n'
|
||||
html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n'
|
||||
|
||||
# html format variables
|
||||
scaleH = 20
|
||||
|
|
@ -3708,6 +3770,9 @@ def createHTML(testruns):
|
|||
resume_time, testdesc, stitle, rtitle)
|
||||
devtl.html += thtml
|
||||
|
||||
if testfail:
|
||||
devtl.html += html_fail.format(testfail)
|
||||
|
||||
# time scale for potentially multiple datasets
|
||||
t0 = testruns[0].start
|
||||
tMax = testruns[-1].end
|
||||
|
|
@ -4006,6 +4071,7 @@ def addCSS(hf, sv, testcount=1, kerror=False, extra=''):
|
|||
.blue {background:rgba(169,208,245,0.4);}\n\
|
||||
.time1 {font:22px Arial;border:1px solid;}\n\
|
||||
.time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\
|
||||
.testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\
|
||||
td {text-align:center;}\n\
|
||||
r {color:#500000;font:15px Tahoma;}\n\
|
||||
n {color:#505050;font:15px Tahoma;}\n\
|
||||
|
|
@ -4927,6 +4993,25 @@ def dmidecode(mempath, fatal=False):
|
|||
count += 1
|
||||
return out
|
||||
|
||||
def getBattery():
|
||||
p = '/sys/class/power_supply'
|
||||
bat = dict()
|
||||
for d in os.listdir(p):
|
||||
type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower()
|
||||
if type != 'battery':
|
||||
continue
|
||||
for v in ['status', 'energy_now', 'capacity_now']:
|
||||
bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower()
|
||||
break
|
||||
ac = True
|
||||
if 'status' in bat and 'discharging' in bat['status']:
|
||||
ac = False
|
||||
charge = 0
|
||||
for v in ['energy_now', 'capacity_now']:
|
||||
if v in bat and bat[v]:
|
||||
charge = int(bat[v])
|
||||
return (ac, charge)
|
||||
|
||||
# Function: getFPDT
|
||||
# Description:
|
||||
# Read the acpi bios tables and pull out FPDT, the firmware data
|
||||
|
|
@ -5202,8 +5287,9 @@ def getArgFloat(name, args, min, max, main=True):
|
|||
|
||||
def processData(live=False):
|
||||
print('PROCESSING DATA')
|
||||
error = ''
|
||||
if(sysvals.usetraceevents):
|
||||
testruns = parseTraceLog(live)
|
||||
testruns, error = parseTraceLog(live)
|
||||
if sysvals.dmesgfile:
|
||||
for data in testruns:
|
||||
data.extractErrorInfo()
|
||||
|
|
@ -5220,15 +5306,18 @@ def processData(live=False):
|
|||
for data in testruns:
|
||||
data.debugPrint()
|
||||
sys.exit()
|
||||
|
||||
if len(testruns) < 1:
|
||||
return (testruns, {'error': 'timeline generation failed'})
|
||||
sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile)
|
||||
createHTML(testruns)
|
||||
createHTML(testruns, error)
|
||||
print('DONE')
|
||||
data = testruns[0]
|
||||
stamp = data.stamp
|
||||
stamp['suspend'], stamp['resume'] = data.getTimeValues()
|
||||
if data.fwValid:
|
||||
stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume
|
||||
if error:
|
||||
stamp['error'] = error
|
||||
return (testruns, stamp)
|
||||
|
||||
# Function: rerunTest
|
||||
|
|
@ -5268,58 +5357,88 @@ def runTest(n=0):
|
|||
sysvals.sudouser(sysvals.testdir)
|
||||
sysvals.outputResult(stamp, n)
|
||||
|
||||
def find_in_html(html, strs, div=False):
|
||||
for str in strs:
|
||||
l = len(str)
|
||||
i = html.find(str)
|
||||
if i >= 0:
|
||||
def find_in_html(html, start, end, firstonly=True):
|
||||
n, out = 0, []
|
||||
while n < len(html):
|
||||
m = re.search(start, html[n:])
|
||||
if not m:
|
||||
break
|
||||
if i < 0:
|
||||
i = m.end()
|
||||
m = re.search(end, html[n+i:])
|
||||
if not m:
|
||||
break
|
||||
j = m.start()
|
||||
str = html[n+i:n+i+j]
|
||||
if end == 'ms':
|
||||
num = re.search(r'[-+]?\d*\.\d+|\d+', str)
|
||||
str = num.group() if num else 'NaN'
|
||||
if firstonly:
|
||||
return str
|
||||
out.append(str)
|
||||
n += i+j
|
||||
if firstonly:
|
||||
return ''
|
||||
if not div:
|
||||
return re.search(r'[-+]?\d*\.\d+|\d+', html[i+l:i+l+50]).group()
|
||||
n = html[i+l:].find('</div>')
|
||||
if n < 0:
|
||||
return ''
|
||||
return html[i+l:i+l+n]
|
||||
return out
|
||||
|
||||
# Function: runSummary
|
||||
# Description:
|
||||
# create a summary of tests in a sub-directory
|
||||
def runSummary(subdir, local=True):
|
||||
def runSummary(subdir, local=True, genhtml=False):
|
||||
inpath = os.path.abspath(subdir)
|
||||
outpath = inpath
|
||||
if local:
|
||||
outpath = os.path.abspath('.')
|
||||
print('Generating a summary of folder "%s"' % inpath)
|
||||
if genhtml:
|
||||
for dirname, dirnames, filenames in os.walk(subdir):
|
||||
sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
|
||||
for filename in filenames:
|
||||
if(re.match('.*_dmesg.txt', filename)):
|
||||
sysvals.dmesgfile = os.path.join(dirname, filename)
|
||||
elif(re.match('.*_ftrace.txt', filename)):
|
||||
sysvals.ftracefile = os.path.join(dirname, filename)
|
||||
sysvals.setOutputFile()
|
||||
if sysvals.ftracefile and sysvals.htmlfile and \
|
||||
not os.path.exists(sysvals.htmlfile):
|
||||
print('FTRACE: %s' % sysvals.ftracefile)
|
||||
if sysvals.dmesgfile:
|
||||
print('DMESG : %s' % sysvals.dmesgfile)
|
||||
rerunTest()
|
||||
testruns = []
|
||||
for dirname, dirnames, filenames in os.walk(subdir):
|
||||
for filename in filenames:
|
||||
if(not re.match('.*.html', filename)):
|
||||
continue
|
||||
file = os.path.join(dirname, filename)
|
||||
html = open(file, 'r').read(10000)
|
||||
suspend = find_in_html(html,
|
||||
['Kernel Suspend: ', 'Kernel Suspend Time: '])
|
||||
resume = find_in_html(html,
|
||||
['Kernel Resume: ', 'Kernel Resume Time: '])
|
||||
line = find_in_html(html, ['<div class="stamp">'], True)
|
||||
html = open(file, 'r').read()
|
||||
suspend = find_in_html(html, 'Kernel Suspend', 'ms')
|
||||
resume = find_in_html(html, 'Kernel Resume', 'ms')
|
||||
line = find_in_html(html, '<div class="stamp">', '</div>')
|
||||
stmp = line.split()
|
||||
if not suspend or not resume or len(stmp) < 4:
|
||||
if not suspend or not resume or len(stmp) != 8:
|
||||
continue
|
||||
try:
|
||||
dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p')
|
||||
except:
|
||||
continue
|
||||
tstr = dt.strftime('%Y/%m/%d %H:%M:%S')
|
||||
error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>')
|
||||
result = 'fail' if error else 'pass'
|
||||
ilist = []
|
||||
e = find_in_html(html, 'class="err"[\w=":;\.%\- ]*>', '→</div>', False)
|
||||
for i in list(set(e)):
|
||||
ilist.append('%sx%d' % (i, e.count(i)) if e.count(i) > 1 else i)
|
||||
data = {
|
||||
'mode': stmp[2],
|
||||
'host': stmp[0],
|
||||
'kernel': stmp[1],
|
||||
'mode': stmp[2],
|
||||
'time': string.join(stmp[3:], ' '),
|
||||
'time': tstr,
|
||||
'result': result,
|
||||
'issues': ','.join(ilist),
|
||||
'suspend': suspend,
|
||||
'resume': resume,
|
||||
'url': os.path.relpath(file, outpath),
|
||||
}
|
||||
if len(stmp) == 7:
|
||||
data['kernel'] = 'unknown'
|
||||
data['mode'] = stmp[1]
|
||||
data['time'] = string.join(stmp[2:], ' ')
|
||||
testruns.append(data)
|
||||
outfile = os.path.join(outpath, 'summary.html')
|
||||
print('Summary file: %s' % outfile)
|
||||
|
|
@ -5609,11 +5728,12 @@ def printHelp():
|
|||
print(' -modes List available suspend modes')
|
||||
print(' -status Test to see if the system is enabled to run this tool')
|
||||
print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table')
|
||||
print(' -battery Print out battery info (if available)')
|
||||
print(' -sysinfo Print out system info extracted from BIOS')
|
||||
print(' -devinfo Print out the pm settings of all devices which support runtime suspend')
|
||||
print(' -flist Print the list of functions currently being captured in ftrace')
|
||||
print(' -flistall Print all functions capable of being captured in ftrace')
|
||||
print(' -summary directory Create a summary of all test in this dir')
|
||||
print(' -summary dir Create a summary of tests in this dir [-genhtml builds missing html]')
|
||||
print(' [redo]')
|
||||
print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)')
|
||||
print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)')
|
||||
|
|
@ -5623,8 +5743,9 @@ def printHelp():
|
|||
# ----------------- MAIN --------------------
|
||||
# exec start (skipped if script is loaded as library)
|
||||
if __name__ == '__main__':
|
||||
genhtml = False
|
||||
cmd = ''
|
||||
simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status']
|
||||
simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status', '-battery']
|
||||
if '-f' in sys.argv:
|
||||
sysvals.cgskip = sysvals.configFile('cgskip.txt')
|
||||
# loop through the command line arguments
|
||||
|
|
@ -5660,6 +5781,8 @@ if __name__ == '__main__':
|
|||
sysvals.skiphtml = True
|
||||
elif(arg == '-cgdump'):
|
||||
sysvals.cgdump = True
|
||||
elif(arg == '-genhtml'):
|
||||
genhtml = True
|
||||
elif(arg == '-addlogs'):
|
||||
sysvals.dmesglog = sysvals.ftracelog = True
|
||||
elif(arg == '-verbose'):
|
||||
|
|
@ -5856,6 +5979,8 @@ if __name__ == '__main__':
|
|||
statusCheck(True)
|
||||
elif(cmd == 'fpdt'):
|
||||
getFPDT(True)
|
||||
elif(cmd == 'battery'):
|
||||
print 'AC Connect: %s\nCharge: %d' % getBattery()
|
||||
elif(cmd == 'sysinfo'):
|
||||
sysvals.printSystemInfo(True)
|
||||
elif(cmd == 'devinfo'):
|
||||
|
|
@ -5867,7 +5992,7 @@ if __name__ == '__main__':
|
|||
elif(cmd == 'flistall'):
|
||||
sysvals.getFtraceFilterFunctions(False)
|
||||
elif(cmd == 'summary'):
|
||||
runSummary(sysvals.outdir, True)
|
||||
runSummary(sysvals.outdir, True, genhtml)
|
||||
sys.exit()
|
||||
|
||||
# if instructed, re-analyze existing data files
|
||||
|
|
@ -5920,7 +6045,7 @@ if __name__ == '__main__':
|
|||
print('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count']))
|
||||
sysvals.logmsg = ''
|
||||
if not sysvals.skiphtml:
|
||||
runSummary(sysvals.outdir, False)
|
||||
runSummary(sysvals.outdir, False, False)
|
||||
sysvals.sudouser(sysvals.outdir)
|
||||
else:
|
||||
if sysvals.outdir:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import subprocess
|
|||
import os
|
||||
import time
|
||||
import re
|
||||
import signal
|
||||
import sys
|
||||
import getopt
|
||||
import Gnuplot
|
||||
|
|
@ -78,11 +79,12 @@ def print_help():
|
|||
print(' Or')
|
||||
print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
|
||||
print(' To generate trace file, parse and plot, use (sudo required):')
|
||||
print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name>')
|
||||
print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>')
|
||||
print(' Or')
|
||||
print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name>')
|
||||
print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>')
|
||||
print(' Optional argument:')
|
||||
print(' cpus: comma separated list of CPUs')
|
||||
print(' cpus: comma separated list of CPUs')
|
||||
print(' kbytes: Kilo bytes of memory per CPU to allocate to the trace buffer. Default: 10240')
|
||||
print(' Output:')
|
||||
print(' If not already present, creates a "results/test_name" folder in the current working directory with:')
|
||||
print(' cpu.csv - comma seperated values file with trace contents and some additional calculations.')
|
||||
|
|
@ -379,7 +381,7 @@ def clear_trace_file():
|
|||
f_handle.close()
|
||||
except:
|
||||
print('IO error clearing trace file ')
|
||||
quit()
|
||||
sys.exit(2)
|
||||
|
||||
def enable_trace():
|
||||
""" Enable trace """
|
||||
|
|
@ -389,7 +391,7 @@ def enable_trace():
|
|||
, 'w').write("1")
|
||||
except:
|
||||
print('IO error enabling trace ')
|
||||
quit()
|
||||
sys.exit(2)
|
||||
|
||||
def disable_trace():
|
||||
""" Disable trace """
|
||||
|
|
@ -399,17 +401,17 @@ def disable_trace():
|
|||
, 'w').write("0")
|
||||
except:
|
||||
print('IO error disabling trace ')
|
||||
quit()
|
||||
sys.exit(2)
|
||||
|
||||
def set_trace_buffer_size():
|
||||
""" Set trace buffer size """
|
||||
|
||||
try:
|
||||
open('/sys/kernel/debug/tracing/buffer_size_kb'
|
||||
, 'w').write("10240")
|
||||
with open('/sys/kernel/debug/tracing/buffer_size_kb', 'w') as fp:
|
||||
fp.write(memory)
|
||||
except:
|
||||
print('IO error setting trace buffer size ')
|
||||
quit()
|
||||
print('IO error setting trace buffer size ')
|
||||
sys.exit(2)
|
||||
|
||||
def free_trace_buffer():
|
||||
""" Free the trace buffer memory """
|
||||
|
|
@ -418,8 +420,8 @@ def free_trace_buffer():
|
|||
open('/sys/kernel/debug/tracing/buffer_size_kb'
|
||||
, 'w').write("1")
|
||||
except:
|
||||
print('IO error setting trace buffer size ')
|
||||
quit()
|
||||
print('IO error freeing trace buffer ')
|
||||
sys.exit(2)
|
||||
|
||||
def read_trace_data(filename):
|
||||
""" Read and parse trace data """
|
||||
|
|
@ -431,7 +433,7 @@ def read_trace_data(filename):
|
|||
data = open(filename, 'r').read()
|
||||
except:
|
||||
print('Error opening ', filename)
|
||||
quit()
|
||||
sys.exit(2)
|
||||
|
||||
for line in data.splitlines():
|
||||
search_obj = \
|
||||
|
|
@ -489,10 +491,22 @@ def read_trace_data(filename):
|
|||
# Now seperate the main overall csv file into per CPU csv files.
|
||||
split_csv()
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
print(' SIGINT: Forcing cleanup before exit.')
|
||||
if interval:
|
||||
disable_trace()
|
||||
clear_trace_file()
|
||||
# Free the memory
|
||||
free_trace_buffer()
|
||||
sys.exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
interval = ""
|
||||
filename = ""
|
||||
cpu_list = ""
|
||||
testname = ""
|
||||
memory = "10240"
|
||||
graph_data_present = False;
|
||||
|
||||
valid1 = False
|
||||
|
|
@ -501,7 +515,7 @@ valid2 = False
|
|||
cpu_mask = zeros((MAX_CPUS,), dtype=int)
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:",["help","trace_file=","interval=","cpu=","name="])
|
||||
opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
|
||||
except getopt.GetoptError:
|
||||
print_help()
|
||||
sys.exit(2)
|
||||
|
|
@ -521,6 +535,8 @@ for opt, arg in opts:
|
|||
elif opt in ("-n", "--name"):
|
||||
valid2 = True
|
||||
testname = arg
|
||||
elif opt in ("-m", "--memory"):
|
||||
memory = arg
|
||||
|
||||
if not (valid1 and valid2):
|
||||
print_help()
|
||||
|
|
@ -569,6 +585,11 @@ current_max_cpu = 0
|
|||
|
||||
read_trace_data(filename)
|
||||
|
||||
clear_trace_file()
|
||||
# Free the memory
|
||||
if interval:
|
||||
free_trace_buffer()
|
||||
|
||||
if graph_data_present == False:
|
||||
print('No valid data to plot')
|
||||
sys.exit(2)
|
||||
|
|
@ -593,9 +614,4 @@ for root, dirs, files in os.walk('.'):
|
|||
for f in files:
|
||||
fix_ownership(f)
|
||||
|
||||
clear_trace_file()
|
||||
# Free the memory
|
||||
if interval:
|
||||
free_trace_buffer()
|
||||
|
||||
os.chdir('../../')
|
||||
|
|
|
|||
|
|
@ -25,4 +25,4 @@ install : turbostat
|
|||
install -d $(DESTDIR)$(PREFIX)/bin
|
||||
install $(BUILD_OUTPUT)/turbostat $(DESTDIR)$(PREFIX)/bin/turbostat
|
||||
install -d $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
install turbostat.8 $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
install -m 644 turbostat.8 $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
|
|
|
|||
|
|
@ -54,9 +54,12 @@ name as necessary to disambiguate it from others is necessary. Note that option
|
|||
.PP
|
||||
\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44
|
||||
.PP
|
||||
\fB--hide column\fP do not show the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
|
||||
\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
|
||||
.PP
|
||||
\fB--show column\fP show only the specified columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
|
||||
\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec" and "Time_Of_Day_Seconds".
|
||||
The column name "all" can be used to enable all disabled-by-default built-in counters.
|
||||
.PP
|
||||
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
|
||||
.PP
|
||||
\fB--Dump\fP displays the raw counter values.
|
||||
.PP
|
||||
|
|
@ -64,6 +67,8 @@ name as necessary to disambiguate it from others is necessary. Note that option
|
|||
.PP
|
||||
\fB--interval seconds\fP overrides the default 5.0 second measurement interval.
|
||||
.PP
|
||||
\fB--num_iterations num\fP number of the measurement iterations.
|
||||
.PP
|
||||
\fB--out output_file\fP turbostat output is written to the specified output_file.
|
||||
The file is truncated if it already exists, and it is created if it does not exist.
|
||||
.PP
|
||||
|
|
@ -86,6 +91,8 @@ displays the statistics gathered since it was forked.
|
|||
The system configuration dump (if --quiet is not used) is followed by statistics. The first row of the statistics labels the content of each column (below). The second row of statistics is the system summary line. The system summary line has a '-' in the columns for the Package, Core, and CPU. The contents of the system summary line depends on the type of column. Columns that count items (eg. IRQ) show the sum across all CPUs in the system. Columns that show a percentage show the average across all CPUs in the system. Columns that dump raw MSR values simply show 0 in the summary. After the system summary row, each row describes a specific Package/Core/CPU. Note that if the --cpu parameter is used to limit which specific CPUs are displayed, turbostat will still collect statistics for all CPUs in the system and will still show the system summary for all CPUs in the system.
|
||||
.SH COLUMN DESCRIPTIONS
|
||||
.nf
|
||||
\fBusec\fP For each CPU, the number of microseconds elapsed during counter collection, including thread migration -- if any. This counter is disabled by default, and is enabled with "--enable usec", or --debug. On the summary row, usec refers to the total elapsed time to collect the counters on all cpus.
|
||||
\fBTime_Of_Day_Seconds\fP For each CPU, the gettimeofday(2) value (seconds.subsec since Epoch) when the counters ending the measurement interval were collected. This column is disabled by default, and can be enabled with "--enable Time_Of_Day_Seconds" or "--debug". On the summary row, Time_Of_Day_Seconds refers to the timestamp following collection of counters on the last CPU.
|
||||
\fBCore\fP processor core number. Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
|
||||
\fBCPU\fP Linux CPU (logical processor) number. Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together.
|
||||
\fBPackage\fP processor package number -- not present on systems with a single processor package.
|
||||
|
|
@ -262,6 +269,21 @@ CPU PRF_CTRL
|
|||
|
||||
.fi
|
||||
|
||||
.SH INPUT
|
||||
|
||||
For interval-mode, turbostat will immediately end the current interval
|
||||
when it sees a newline on standard input.
|
||||
turbostat will then start the next interval.
|
||||
Control-C will be send a SIGINT to turbostat,
|
||||
which will immediately abort the program with no further processing.
|
||||
.SH SIGNALS
|
||||
|
||||
SIGINT will interrupt interval-mode.
|
||||
The end-of-interval data will be collected and displayed before turbostat exits.
|
||||
|
||||
SIGUSR1 will end current interval,
|
||||
end-of-interval data will be collected and displayed before turbostat
|
||||
starts a new interval.
|
||||
.SH NOTES
|
||||
|
||||
.B "turbostat "
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -24,5 +24,5 @@ install : x86_energy_perf_policy
|
|||
install -d $(DESTDIR)$(PREFIX)/bin
|
||||
install $(BUILD_OUTPUT)/x86_energy_perf_policy $(DESTDIR)$(PREFIX)/bin/x86_energy_perf_policy
|
||||
install -d $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
install x86_energy_perf_policy.8 $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
install -m 644 x86_energy_perf_policy.8 $(DESTDIR)$(PREFIX)/share/man/man8
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue