1 #!/usr/bin/env python3 !! 1 #!/usr/bin/python2 2 # SPDX-License-Identifier: GPL-2.0-only << 3 # 2 # 4 # Tool for analyzing suspend/resume timing 3 # Tool for analyzing suspend/resume timing 5 # Copyright (c) 2013, Intel Corporation. 4 # Copyright (c) 2013, Intel Corporation. 6 # 5 # 7 # This program is free software; you can redis 6 # This program is free software; you can redistribute it and/or modify it 8 # under the terms and conditions of the GNU Ge 7 # under the terms and conditions of the GNU General Public License, 9 # version 2, as published by the Free Software 8 # version 2, as published by the Free Software Foundation. 10 # 9 # 11 # This program is distributed in the hope it w 10 # This program is distributed in the hope it will be useful, but WITHOUT 12 # ANY WARRANTY; without even the implied warra 11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 # FITNESS FOR A PARTICULAR PURPOSE. See the G 12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 # more details. 13 # more details. 15 # 14 # 16 # Authors: 15 # Authors: 17 # Todd Brandt <todd.e.brandt@linux.intel 16 # Todd Brandt <todd.e.brandt@linux.intel.com> 18 # 17 # 19 # Links: 18 # Links: 20 # Home Page 19 # Home Page 21 # https://01.org/pm-graph !! 20 # https://01.org/suspendresume 22 # Source repo 21 # Source repo 23 # git@github.com:intel/pm-graph !! 22 # git@github.com:01org/pm-graph 24 # 23 # 25 # Description: 24 # Description: 26 # This tool is designed to assist kerne 25 # This tool is designed to assist kernel and OS developers in optimizing 27 # their linux stack's suspend/resume ti 26 # their linux stack's suspend/resume time. Using a kernel image built 28 # with a few extra options enabled, the 27 # with a few extra options enabled, the tool will execute a suspend and 29 # will capture dmesg and ftrace data un 28 # will capture dmesg and ftrace data until resume is complete. This data 30 # is transformed into a device timeline 29 # is transformed into a device timeline and a callgraph to give a quick 31 # and detailed view of which devices an 30 # and detailed view of which devices and callbacks are taking the most 32 # time in suspend/resume. The output is 31 # time in suspend/resume. The output is a single html file which can be 33 # viewed in firefox or chrome. 32 # viewed in firefox or chrome. 34 # 33 # 35 # The following kernel build options ar 34 # The following kernel build options are required: 36 # CONFIG_DEVMEM=y << 37 # CONFIG_PM_DEBUG=y 35 # CONFIG_PM_DEBUG=y 38 # CONFIG_PM_SLEEP_DEBUG=y 36 # CONFIG_PM_SLEEP_DEBUG=y 39 # CONFIG_FTRACE=y 37 # CONFIG_FTRACE=y 40 # CONFIG_FUNCTION_TRACER=y 38 # CONFIG_FUNCTION_TRACER=y 41 # CONFIG_FUNCTION_GRAPH_TRACER= 39 # CONFIG_FUNCTION_GRAPH_TRACER=y 42 # CONFIG_KPROBES=y 40 # CONFIG_KPROBES=y 43 # CONFIG_KPROBES_ON_FTRACE=y 41 # CONFIG_KPROBES_ON_FTRACE=y 44 # 42 # 45 # For kernel versions older than 3.15: 43 # For kernel versions older than 3.15: 46 # The following additional kernel param 44 # The following additional kernel parameters are required: 47 # (e.g. in file /etc/default/gr 45 # (e.g. in file /etc/default/grub) 48 # GRUB_CMDLINE_LINUX_DEFAULT=". 46 # GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=16M ..." 49 # 47 # 50 48 51 # ----------------- LIBRARIES ---------------- 49 # ----------------- LIBRARIES -------------------- 52 50 53 import sys 51 import sys 54 import time 52 import time 55 import os 53 import os 56 import string 54 import string 57 import re 55 import re 58 import platform 56 import platform 59 import signal !! 57 from datetime import datetime 60 import codecs << 61 from datetime import datetime, timedelta << 62 import struct 58 import struct 63 import configparser !! 59 import ConfigParser 64 import gzip 60 import gzip 65 from threading import Thread 61 from threading import Thread 66 from subprocess import call, Popen, PIPE 62 from subprocess import call, Popen, PIPE 67 import base64 << 68 << 69 debugtiming = False << 70 mystarttime = time.time() << 71 def pprint(msg): << 72 if debugtiming: << 73 print('[%09.3f] %s' % (time.ti << 74 else: << 75 print(msg) << 76 sys.stdout.flush() << 77 << 78 def ascii(text): << 79 return text.decode('ascii', 'ignore') << 80 63 81 # ----------------- CLASSES ------------------ 64 # ----------------- CLASSES -------------------- 82 65 83 # Class: SystemValues 66 # Class: SystemValues 84 # Description: 67 # Description: 85 # A global, single-instance container u 68 # A global, single-instance container used to 86 # store system values and test paramete 69 # store system values and test parameters 87 class SystemValues: 70 class SystemValues: 88 title = 'SleepGraph' 71 title = 'SleepGraph' 89 version = '5.12' !! 72 version = '5.1' 90 ansi = False 73 ansi = False 91 rs = 0 74 rs = 0 92 display = '' !! 75 display = 0 93 gzip = False 76 gzip = False 94 sync = False 77 sync = False 95 wifi = False << 96 netfix = False << 97 verbose = False 78 verbose = False 98 testlog = True 79 testlog = True 99 dmesglog = True !! 80 dmesglog = False 100 ftracelog = False 81 ftracelog = False 101 acpidebug = True !! 82 mindevlen = 0.0 102 tstat = True << 103 wifitrace = False << 104 mindevlen = 0.0001 << 105 mincglen = 0.0 83 mincglen = 0.0 106 cgphase = '' 84 cgphase = '' 107 cgtest = -1 85 cgtest = -1 108 cgskip = '' 86 cgskip = '' 109 maxfail = 0 !! 87 multitest = {'run': False, 'count': 0, 'delay': 0} 110 multitest = {'run': False, 'count': 10 << 111 max_graph_depth = 0 88 max_graph_depth = 0 112 callloopmaxgap = 0.0001 89 callloopmaxgap = 0.0001 113 callloopmaxlen = 0.005 90 callloopmaxlen = 0.005 114 bufsize = 0 91 bufsize = 0 115 cpucount = 0 92 cpucount = 0 116 memtotal = 204800 93 memtotal = 204800 117 memfree = 204800 94 memfree = 204800 118 osversion = '' << 119 srgap = 0 95 srgap = 0 120 cgexp = False 96 cgexp = False 121 testdir = '' 97 testdir = '' 122 outdir = '' 98 outdir = '' 123 tpath = '/sys/kernel/tracing/' !! 99 tpath = '/sys/kernel/debug/tracing/' 124 fpdtpath = '/sys/firmware/acpi/tables/ 100 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 125 epath = '/sys/kernel/tracing/events/po !! 101 epath = '/sys/kernel/debug/tracing/events/power/' 126 pmdpath = '/sys/power/pm_debug_message << 127 s0ixpath = '/sys/module/intel_pmc_core << 128 s0ixres = '/sys/devices/system/cpu/cpu << 129 acpipath='/sys/module/acpi/parameters/ << 130 traceevents = [ 102 traceevents = [ 131 'suspend_resume', 103 'suspend_resume', 132 'wakeup_source_activate', << 133 'wakeup_source_deactivate', << 134 'device_pm_callback_end', 104 'device_pm_callback_end', 135 'device_pm_callback_start' 105 'device_pm_callback_start' 136 ] 106 ] 137 logmsg = '' 107 logmsg = '' 138 testcommand = '' 108 testcommand = '' 139 mempath = '/dev/mem' 109 mempath = '/dev/mem' 140 powerfile = '/sys/power/state' 110 powerfile = '/sys/power/state' 141 mempowerfile = '/sys/power/mem_sleep' 111 mempowerfile = '/sys/power/mem_sleep' 142 diskpowerfile = '/sys/power/disk' << 143 suspendmode = 'mem' 112 suspendmode = 'mem' 144 memmode = '' 113 memmode = '' 145 diskmode = '' << 146 hostname = 'localhost' 114 hostname = 'localhost' 147 prefix = 'test' 115 prefix = 'test' 148 teststamp = '' 116 teststamp = '' 149 sysstamp = '' 117 sysstamp = '' 150 dmesgstart = 0.0 118 dmesgstart = 0.0 151 dmesgfile = '' 119 dmesgfile = '' 152 ftracefile = '' 120 ftracefile = '' 153 htmlfile = 'output.html' 121 htmlfile = 'output.html' 154 result = '' 122 result = '' 155 rtcwake = True 123 rtcwake = True 156 rtcwaketime = 15 124 rtcwaketime = 15 157 rtcpath = '' 125 rtcpath = '' 158 devicefilter = [] 126 devicefilter = [] 159 cgfilter = [] 127 cgfilter = [] 160 stamp = 0 128 stamp = 0 161 execcount = 1 129 execcount = 1 162 x2delay = 0 130 x2delay = 0 163 skiphtml = False 131 skiphtml = False 164 usecallgraph = False 132 usecallgraph = False 165 ftopfunc = 'pm_suspend' << 166 ftop = False << 167 usetraceevents = False 133 usetraceevents = False 168 usetracemarkers = True 134 usetracemarkers = True 169 useftrace = True << 170 usekprobes = True 135 usekprobes = True 171 usedevsrc = False 136 usedevsrc = False 172 useprocmon = False 137 useprocmon = False 173 notestrun = False 138 notestrun = False 174 cgdump = False 139 cgdump = False 175 devdump = False << 176 mixedphaseheight = True 140 mixedphaseheight = True 177 devprops = dict() 141 devprops = dict() 178 cfgdef = dict() << 179 platinfo = [] << 180 predelay = 0 142 predelay = 0 181 postdelay = 0 143 postdelay = 0 182 tmstart = 'SUSPEND START %Y%m%d-%H:%M: !! 144 procexecfmt = 'ps - (?P<ps>.*)$' 183 tmend = 'RESUME COMPLETE %Y%m%d-%H:%M: !! 145 devpropfmt = '# Device Properties: .*' >> 146 tracertypefmt = '# tracer: (?P<t>.*)' >> 147 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 184 tracefuncs = { 148 tracefuncs = { 185 'async_synchronize_full': {}, << 186 'sys_sync': {}, 149 'sys_sync': {}, 187 'ksys_sync': {}, << 188 '__pm_notifier_call_chain': {} 150 '__pm_notifier_call_chain': {}, 189 'pm_prepare_console': {}, 151 'pm_prepare_console': {}, 190 'pm_notifier_call_chain': {}, 152 'pm_notifier_call_chain': {}, 191 'freeze_processes': {}, 153 'freeze_processes': {}, 192 'freeze_kernel_threads': {}, 154 'freeze_kernel_threads': {}, 193 'pm_restrict_gfp_mask': {}, 155 'pm_restrict_gfp_mask': {}, 194 'acpi_suspend_begin': {}, 156 'acpi_suspend_begin': {}, 195 'acpi_hibernation_begin': {}, 157 'acpi_hibernation_begin': {}, 196 'acpi_hibernation_enter': {}, 158 'acpi_hibernation_enter': {}, 197 'acpi_hibernation_leave': {}, 159 'acpi_hibernation_leave': {}, 198 'acpi_pm_freeze': {}, 160 'acpi_pm_freeze': {}, 199 'acpi_pm_thaw': {}, 161 'acpi_pm_thaw': {}, 200 'acpi_s2idle_end': {}, << 201 'acpi_s2idle_sync': {}, << 202 'acpi_s2idle_begin': {}, << 203 'acpi_s2idle_prepare': {}, << 204 'acpi_s2idle_prepare_late': {} << 205 'acpi_s2idle_wake': {}, << 206 'acpi_s2idle_wakeup': {}, << 207 'acpi_s2idle_restore': {}, << 208 'acpi_s2idle_restore_early': { << 209 'hibernate_preallocate_memory' 162 'hibernate_preallocate_memory': {}, 210 'create_basic_memory_bitmaps': 163 'create_basic_memory_bitmaps': {}, 211 'swsusp_write': {}, 164 'swsusp_write': {}, 212 'suspend_console': {}, 165 'suspend_console': {}, 213 'acpi_pm_prepare': {}, 166 'acpi_pm_prepare': {}, 214 'syscore_suspend': {}, 167 'syscore_suspend': {}, 215 'arch_enable_nonboot_cpus_end' 168 'arch_enable_nonboot_cpus_end': {}, 216 'syscore_resume': {}, 169 'syscore_resume': {}, 217 'acpi_pm_finish': {}, 170 'acpi_pm_finish': {}, 218 'resume_console': {}, 171 'resume_console': {}, 219 'acpi_pm_end': {}, 172 'acpi_pm_end': {}, 220 'pm_restore_gfp_mask': {}, 173 'pm_restore_gfp_mask': {}, 221 'thaw_processes': {}, 174 'thaw_processes': {}, 222 'pm_restore_console': {}, 175 'pm_restore_console': {}, 223 'CPU_OFF': { 176 'CPU_OFF': { 224 'func':'_cpu_down', 177 'func':'_cpu_down', 225 'args_x86_64': {'cpu': 178 'args_x86_64': {'cpu':'%di:s32'}, 226 'format': 'CPU_OFF[{cp 179 'format': 'CPU_OFF[{cpu}]' 227 }, 180 }, 228 'CPU_ON': { 181 'CPU_ON': { 229 'func':'_cpu_up', 182 'func':'_cpu_up', 230 'args_x86_64': {'cpu': 183 'args_x86_64': {'cpu':'%di:s32'}, 231 'format': 'CPU_ON[{cpu 184 'format': 'CPU_ON[{cpu}]' 232 }, 185 }, 233 } 186 } 234 dev_tracefuncs = { 187 dev_tracefuncs = { 235 # general wait/delay/sleep 188 # general wait/delay/sleep 236 'msleep': { 'args_x86_64': {'t 189 'msleep': { 'args_x86_64': {'time':'%di:s32'}, 'ub': 1 }, >> 190 'schedule_timeout_uninterruptible': { 'args_x86_64': {'timeout':'%di:s32'}, 'ub': 1 }, 237 'schedule_timeout': { 'args_x8 191 'schedule_timeout': { 'args_x86_64': {'timeout':'%di:s32'}, 'ub': 1 }, 238 'udelay': { 'func':'__const_ud 192 'udelay': { 'func':'__const_udelay', 'args_x86_64': {'loops':'%di:s32'}, 'ub': 1 }, 239 'usleep_range': { 'args_x86_64 193 'usleep_range': { 'args_x86_64': {'min':'%di:s32', 'max':'%si:s32'}, 'ub': 1 }, 240 'mutex_lock_slowpath': { 'func 194 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 }, 241 'acpi_os_stall': {'ub': 1}, 195 'acpi_os_stall': {'ub': 1}, 242 'rt_mutex_slowlock': {'ub': 1} << 243 # ACPI 196 # ACPI 244 'acpi_resume_power_resources': 197 'acpi_resume_power_resources': {}, 245 'acpi_ps_execute_method': { 'a !! 198 'acpi_ps_parse_aml': {}, 246 'fullpath':'+0(+40(%di << 247 }}, << 248 # mei_me << 249 'mei_reset': {}, << 250 # filesystem 199 # filesystem 251 'ext4_sync_fs': {}, 200 'ext4_sync_fs': {}, 252 # 80211 201 # 80211 253 'ath10k_bmi_read_memory': { 'a << 254 'ath10k_bmi_write_memory': { ' << 255 'ath10k_bmi_fast_download': { << 256 'iwlagn_mac_start': {}, 202 'iwlagn_mac_start': {}, 257 'iwlagn_alloc_bcast_station': 203 'iwlagn_alloc_bcast_station': {}, 258 'iwl_trans_pcie_start_hw': {}, 204 'iwl_trans_pcie_start_hw': {}, 259 'iwl_trans_pcie_start_fw': {}, 205 'iwl_trans_pcie_start_fw': {}, 260 'iwl_run_init_ucode': {}, 206 'iwl_run_init_ucode': {}, 261 'iwl_load_ucode_wait_alive': { 207 'iwl_load_ucode_wait_alive': {}, 262 'iwl_alive_start': {}, 208 'iwl_alive_start': {}, 263 'iwlagn_mac_stop': {}, 209 'iwlagn_mac_stop': {}, 264 'iwlagn_mac_suspend': {}, 210 'iwlagn_mac_suspend': {}, 265 'iwlagn_mac_resume': {}, 211 'iwlagn_mac_resume': {}, 266 'iwlagn_mac_add_interface': {} 212 'iwlagn_mac_add_interface': {}, 267 'iwlagn_mac_remove_interface': 213 'iwlagn_mac_remove_interface': {}, 268 'iwlagn_mac_change_interface': 214 'iwlagn_mac_change_interface': {}, 269 'iwlagn_mac_config': {}, 215 'iwlagn_mac_config': {}, 270 'iwlagn_configure_filter': {}, 216 'iwlagn_configure_filter': {}, 271 'iwlagn_mac_hw_scan': {}, 217 'iwlagn_mac_hw_scan': {}, 272 'iwlagn_bss_info_changed': {}, 218 'iwlagn_bss_info_changed': {}, 273 'iwlagn_mac_channel_switch': { 219 'iwlagn_mac_channel_switch': {}, 274 'iwlagn_mac_flush': {}, 220 'iwlagn_mac_flush': {}, 275 # ATA 221 # ATA 276 'ata_eh_recover': { 'args_x86_ 222 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} }, 277 # i915 223 # i915 278 'i915_gem_resume': {}, 224 'i915_gem_resume': {}, 279 'i915_restore_state': {}, 225 'i915_restore_state': {}, 280 'intel_opregion_setup': {}, 226 'intel_opregion_setup': {}, 281 'g4x_pre_enable_dp': {}, 227 'g4x_pre_enable_dp': {}, 282 'vlv_pre_enable_dp': {}, 228 'vlv_pre_enable_dp': {}, 283 'chv_pre_enable_dp': {}, 229 'chv_pre_enable_dp': {}, 284 'g4x_enable_dp': {}, 230 'g4x_enable_dp': {}, 285 'vlv_enable_dp': {}, 231 'vlv_enable_dp': {}, 286 'intel_hpd_init': {}, 232 'intel_hpd_init': {}, 287 'intel_opregion_register': {}, 233 'intel_opregion_register': {}, 288 'intel_dp_detect': {}, 234 'intel_dp_detect': {}, 289 'intel_hdmi_detect': {}, 235 'intel_hdmi_detect': {}, 290 'intel_opregion_init': {}, 236 'intel_opregion_init': {}, 291 'intel_fbdev_set_suspend': {}, 237 'intel_fbdev_set_suspend': {}, 292 } 238 } 293 infocmds = [ << 294 [0, 'sysinfo', 'uname', '-a'], << 295 [0, 'cpuinfo', 'head', '-7', ' << 296 [0, 'kparams', 'cat', '/proc/c << 297 [0, 'mcelog', 'mcelog'], << 298 [0, 'pcidevices', 'lspci', '-t << 299 [0, 'usbdevices', 'lsusb', '-t << 300 [0, 'acpidevices', 'sh', '-c', << 301 [0, 's0ix_require', 'cat', '/s << 302 [0, 's0ix_debug', 'cat', '/sys << 303 [0, 'ethtool', 'ethtool', '{et << 304 [1, 's0ix_residency', 'cat', ' << 305 [1, 'interrupts', 'cat', '/pro << 306 [1, 'wakeups', 'cat', '/sys/ke << 307 [2, 'gpecounts', 'sh', '-c', ' << 308 [2, 'suspendstats', 'sh', '-c' << 309 [2, 'cpuidle', 'sh', '-c', 'gr << 310 [2, 'battery', 'sh', '-c', 'gr << 311 [2, 'thermal', 'sh', '-c', 'gr << 312 ] << 313 cgblacklist = [] 239 cgblacklist = [] 314 kprobes = dict() 240 kprobes = dict() 315 timeformat = '%.3f' 241 timeformat = '%.3f' 316 cmdline = '%s %s' % \ 242 cmdline = '%s %s' % \ 317 (os.path.basename(sys. 243 (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:])) 318 sudouser = '' << 319 def __init__(self): 244 def __init__(self): 320 self.archargs = 'args_'+platfo 245 self.archargs = 'args_'+platform.machine() 321 self.hostname = platform.node( 246 self.hostname = platform.node() 322 if(self.hostname == ''): 247 if(self.hostname == ''): 323 self.hostname = 'local 248 self.hostname = 'localhost' 324 rtc = "rtc0" 249 rtc = "rtc0" 325 if os.path.exists('/dev/rtc'): 250 if os.path.exists('/dev/rtc'): 326 rtc = os.readlink('/de 251 rtc = os.readlink('/dev/rtc') 327 rtc = '/sys/class/rtc/'+rtc 252 rtc = '/sys/class/rtc/'+rtc 328 if os.path.exists(rtc) and os. 253 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \ 329 os.path.exists(rtc+'/t 254 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'): 330 self.rtcpath = rtc 255 self.rtcpath = rtc 331 if (hasattr(sys.stdout, 'isatt 256 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 332 self.ansi = True 257 self.ansi = True 333 self.testdir = datetime.now(). 258 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S') 334 if os.getuid() == 0 and 'SUDO_ << 335 os.environ['SUDO_USER' << 336 self.sudouser = os.env << 337 def resetlog(self): << 338 self.logmsg = '' << 339 self.platinfo = [] << 340 def vprint(self, msg): 259 def vprint(self, msg): 341 self.logmsg += msg+'\n' 260 self.logmsg += msg+'\n' 342 if self.verbose or msg.startsw !! 261 if(self.verbose): 343 pprint(msg) !! 262 print(msg) 344 def signalHandler(self, signum, frame) << 345 if not self.result: << 346 return << 347 signame = self.signames[signum << 348 msg = 'Signal %s caused a tool << 349 self.outputResult({'error':msg << 350 sys.exit(3) << 351 def signalHandlerInit(self): << 352 capture = ['BUS', 'SYS', 'XCPU << 353 'ILL', 'ABRT', 'FPE', << 354 self.signames = dict() << 355 for i in capture: << 356 s = 'SIG'+i << 357 try: << 358 signum = getat << 359 signal.signal( << 360 except: << 361 continue << 362 self.signames[signum] << 363 def rootCheck(self, fatal=True): 263 def rootCheck(self, fatal=True): 364 if(os.access(self.powerfile, o 264 if(os.access(self.powerfile, os.W_OK)): 365 return True 265 return True 366 if fatal: 266 if fatal: 367 msg = 'This command re 267 msg = 'This command requires sysfs mount and root access' 368 pprint('ERROR: %s\n' % !! 268 print('ERROR: %s\n') % msg 369 self.outputResult({'er 269 self.outputResult({'error':msg}) 370 sys.exit(1) !! 270 sys.exit() 371 return False 271 return False 372 def rootUser(self, fatal=False): 272 def rootUser(self, fatal=False): 373 if 'USER' in os.environ and os 273 if 'USER' in os.environ and os.environ['USER'] == 'root': 374 return True 274 return True 375 if fatal: 275 if fatal: 376 msg = 'This command mu 276 msg = 'This command must be run as root' 377 pprint('ERROR: %s\n' % !! 277 print('ERROR: %s\n') % msg 378 self.outputResult({'er 278 self.outputResult({'error':msg}) 379 sys.exit(1) !! 279 sys.exit() 380 return False 280 return False 381 def usable(self, file, ishtml=False): << 382 if not os.path.exists(file) or << 383 return False << 384 if ishtml: << 385 try: << 386 fp = open(file << 387 res = fp.read( << 388 fp.close() << 389 except: << 390 return False << 391 if '<html>' not in res << 392 return False << 393 return True << 394 def getExec(self, cmd): 281 def getExec(self, cmd): 395 try: !! 282 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin', 396 fp = Popen(['which', c !! 283 '/usr/local/sbin', '/usr/local/bin'] 397 out = ascii(fp.read()) !! 284 for path in dirlist: 398 fp.close() << 399 except: << 400 out = '' << 401 if out: << 402 return out << 403 for path in ['/sbin', '/bin', << 404 '/usr/local/sbin', '/u << 405 cmdfull = os.path.join 285 cmdfull = os.path.join(path, cmd) 406 if os.path.exists(cmdf 286 if os.path.exists(cmdfull): 407 return cmdfull 287 return cmdfull 408 return out !! 288 return '' 409 def setPrecision(self, num): 289 def setPrecision(self, num): 410 if num < 0 or num > 6: 290 if num < 0 or num > 6: 411 return 291 return 412 self.timeformat = '%.{0}f'.for 292 self.timeformat = '%.{0}f'.format(num) 413 def setOutputFolder(self, value): 293 def setOutputFolder(self, value): 414 args = dict() 294 args = dict() 415 n = datetime.now() 295 n = datetime.now() 416 args['date'] = n.strftime('%y% 296 args['date'] = n.strftime('%y%m%d') 417 args['time'] = n.strftime('%H% 297 args['time'] = n.strftime('%H%M%S') 418 args['hostname'] = args['host' 298 args['hostname'] = args['host'] = self.hostname 419 args['mode'] = self.suspendmod << 420 return value.format(**args) 299 return value.format(**args) 421 def setOutputFile(self): 300 def setOutputFile(self): 422 if self.dmesgfile != '': 301 if self.dmesgfile != '': 423 m = re.match(r'(?P<nam !! 302 m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile) 424 if(m): 303 if(m): 425 self.htmlfile 304 self.htmlfile = m.group('name')+'.html' 426 if self.ftracefile != '': 305 if self.ftracefile != '': 427 m = re.match(r'(?P<nam !! 306 m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile) 428 if(m): 307 if(m): 429 self.htmlfile 308 self.htmlfile = m.group('name')+'.html' 430 def systemInfo(self, info): 309 def systemInfo(self, info): 431 p = m = '' !! 310 p = c = m = b = '' 432 if 'baseboard-manufacturer' in 311 if 'baseboard-manufacturer' in info: 433 m = info['baseboard-ma 312 m = info['baseboard-manufacturer'] 434 elif 'system-manufacturer' in 313 elif 'system-manufacturer' in info: 435 m = info['system-manuf 314 m = info['system-manufacturer'] 436 if 'system-product-name' in in !! 315 if 'baseboard-product-name' in info: 437 p = info['system-produ << 438 elif 'baseboard-product-name' << 439 p = info['baseboard-pr << 440 if m[:5].lower() == 'intel' an << 441 p = info['baseboard-pr 316 p = info['baseboard-product-name'] 442 c = info['processor-version'] !! 317 elif 'system-product-name' in info: 443 b = info['bios-version'] if 'b !! 318 p = info['system-product-name'] 444 r = info['bios-release-date'] !! 319 if 'processor-version' in info: 445 self.sysstamp = '# sysinfo | m !! 320 c = info['processor-version'] 446 (m, p, c, b, r, self.c !! 321 if 'bios-version' in info: 447 if self.osversion: !! 322 b = info['bios-version'] 448 self.sysstamp += ' | o !! 323 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d | memfr:%d' % \ >> 324 (m, p, c, b, self.cpucount, self.memtotal, self.memfree) 449 def printSystemInfo(self, fatal=False) 325 def printSystemInfo(self, fatal=False): 450 self.rootCheck(True) 326 self.rootCheck(True) 451 out = dmidecode(self.mempath, 327 out = dmidecode(self.mempath, fatal) 452 if len(out) < 1: 328 if len(out) < 1: 453 return 329 return 454 fmt = '%-24s: %s' 330 fmt = '%-24s: %s' 455 if self.osversion: << 456 print(fmt % ('os-versi << 457 for name in sorted(out): 331 for name in sorted(out): 458 print(fmt % (name, out !! 332 print fmt % (name, out[name]) 459 print(fmt % ('cpucount', ('%d' !! 333 print fmt % ('cpucount', ('%d' % self.cpucount)) 460 print(fmt % ('memtotal', ('%d !! 334 print fmt % ('memtotal', ('%d kB' % self.memtotal)) 461 print(fmt % ('memfree', ('%d k !! 335 print fmt % ('memfree', ('%d kB' % self.memfree)) 462 def cpuInfo(self): 336 def cpuInfo(self): 463 self.cpucount = 0 337 self.cpucount = 0 464 if os.path.exists('/proc/cpuin !! 338 fp = open('/proc/cpuinfo', 'r') 465 with open('/proc/cpuin !! 339 for line in fp: 466 for line in fp !! 340 if re.match('^processor[ \t]*:[ \t]*[0-9]*', line): 467 if re. !! 341 self.cpucount += 1 468 !! 342 fp.close() 469 if os.path.exists('/proc/memin !! 343 fp = open('/proc/meminfo', 'r') 470 with open('/proc/memin !! 344 for line in fp: 471 for line in fp !! 345 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 472 m = re !! 346 if m: 473 if m: !! 347 self.memtotal = int(m.group('sz')) 474 !! 348 m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line) 475 m = re !! 349 if m: 476 if m: !! 350 self.memfree = int(m.group('sz')) 477 !! 351 fp.close() 478 if os.path.exists('/etc/os-rel << 479 with open('/etc/os-rel << 480 for line in fp << 481 if lin << 482 << 483 def initTestOutput(self, name): 352 def initTestOutput(self, name): 484 self.prefix = self.hostname 353 self.prefix = self.hostname 485 v = open('/proc/version', 'r') 354 v = open('/proc/version', 'r').read().strip() 486 kver = v.split()[2] !! 355 kver = string.split(v)[2] 487 fmt = name+'-%m%d%y-%H%M%S' 356 fmt = name+'-%m%d%y-%H%M%S' 488 testtime = datetime.now().strf 357 testtime = datetime.now().strftime(fmt) 489 self.teststamp = \ 358 self.teststamp = \ 490 '# '+testtime+' '+self 359 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 491 ext = '' 360 ext = '' 492 if self.gzip: 361 if self.gzip: 493 ext = '.gz' 362 ext = '.gz' 494 self.dmesgfile = \ 363 self.dmesgfile = \ 495 self.testdir+'/'+self. 364 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext 496 self.ftracefile = \ 365 self.ftracefile = \ 497 self.testdir+'/'+self. 366 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext 498 self.htmlfile = \ 367 self.htmlfile = \ 499 self.testdir+'/'+self. 368 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' 500 if not os.path.isdir(self.test 369 if not os.path.isdir(self.testdir): 501 os.makedirs(self.testd !! 370 os.mkdir(self.testdir) 502 self.sudoUserchown(self.testdi << 503 def getValueList(self, value): 371 def getValueList(self, value): 504 out = [] 372 out = [] 505 for i in value.split(','): 373 for i in value.split(','): 506 if i.strip(): 374 if i.strip(): 507 out.append(i.s 375 out.append(i.strip()) 508 return out 376 return out 509 def setDeviceFilter(self, value): 377 def setDeviceFilter(self, value): 510 self.devicefilter = self.getVa 378 self.devicefilter = self.getValueList(value) 511 def setCallgraphFilter(self, value): 379 def setCallgraphFilter(self, value): 512 self.cgfilter = self.getValueL 380 self.cgfilter = self.getValueList(value) 513 def skipKprobes(self, value): << 514 for k in self.getValueList(val << 515 if k in self.tracefunc << 516 del self.trace << 517 if k in self.dev_trace << 518 del self.dev_t << 519 def setCallgraphBlacklist(self, file): 381 def setCallgraphBlacklist(self, file): 520 self.cgblacklist = self.listFr 382 self.cgblacklist = self.listFromFile(file) 521 def rtcWakeAlarmOn(self): 383 def rtcWakeAlarmOn(self): 522 call('echo 0 > '+self.rtcpath+ 384 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True) 523 nowtime = open(self.rtcpath+'/ 385 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip() 524 if nowtime: 386 if nowtime: 525 nowtime = int(nowtime) 387 nowtime = int(nowtime) 526 else: 388 else: 527 # if hardware time fai 389 # if hardware time fails, use the software time 528 nowtime = int(datetime 390 nowtime = int(datetime.now().strftime('%s')) 529 alarm = nowtime + self.rtcwake 391 alarm = nowtime + self.rtcwaketime 530 call('echo %d > %s/wakealarm' 392 call('echo %d > %s/wakealarm' % (alarm, self.rtcpath), shell=True) 531 def rtcWakeAlarmOff(self): 393 def rtcWakeAlarmOff(self): 532 call('echo 0 > %s/wakealarm' % 394 call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True) 533 def initdmesg(self): 395 def initdmesg(self): 534 # get the latest time stamp fr 396 # get the latest time stamp from the dmesg log 535 lines = Popen('dmesg', stdout= !! 397 fp = Popen('dmesg', stdout=PIPE).stdout 536 ktime = '0' 398 ktime = '0' 537 for line in reversed(lines): !! 399 for line in fp: 538 line = ascii(line).rep !! 400 line = line.replace('\r\n', '') 539 idx = line.find('[') 401 idx = line.find('[') 540 if idx > 1: 402 if idx > 1: 541 line = line[id 403 line = line[idx:] 542 m = re.match(r'[ \t]*( !! 404 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 543 if(m): 405 if(m): 544 ktime = m.grou 406 ktime = m.group('ktime') 545 break !! 407 fp.close() 546 self.dmesgstart = float(ktime) 408 self.dmesgstart = float(ktime) 547 def getdmesg(self, testdata): !! 409 def getdmesg(self, fwdata=[]): 548 op = self.writeDatafileHeader( !! 410 op = self.writeDatafileHeader(sysvals.dmesgfile, fwdata) 549 # store all new dmesg lines si 411 # store all new dmesg lines since initdmesg was called 550 fp = Popen('dmesg', stdout=PIP 412 fp = Popen('dmesg', stdout=PIPE).stdout 551 for line in fp: 413 for line in fp: 552 line = ascii(line).rep !! 414 line = line.replace('\r\n', '') 553 idx = line.find('[') 415 idx = line.find('[') 554 if idx > 1: 416 if idx > 1: 555 line = line[id 417 line = line[idx:] 556 m = re.match(r'[ \t]*( !! 418 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 557 if(not m): 419 if(not m): 558 continue 420 continue 559 ktime = float(m.group( 421 ktime = float(m.group('ktime')) 560 if ktime > self.dmesgs 422 if ktime > self.dmesgstart: 561 op.write(line) 423 op.write(line) 562 fp.close() 424 fp.close() 563 op.close() 425 op.close() 564 def listFromFile(self, file): 426 def listFromFile(self, file): 565 list = [] 427 list = [] 566 fp = open(file) 428 fp = open(file) 567 for i in fp.read().split('\n') 429 for i in fp.read().split('\n'): 568 i = i.strip() 430 i = i.strip() 569 if i and i[0] != '#': 431 if i and i[0] != '#': 570 list.append(i) 432 list.append(i) 571 fp.close() 433 fp.close() 572 return list 434 return list 573 def addFtraceFilterFunctions(self, fil 435 def addFtraceFilterFunctions(self, file): 574 for i in self.listFromFile(fil 436 for i in self.listFromFile(file): 575 if len(i) < 2: 437 if len(i) < 2: 576 continue 438 continue 577 self.tracefuncs[i] = d 439 self.tracefuncs[i] = dict() 578 def getFtraceFilterFunctions(self, cur 440 def getFtraceFilterFunctions(self, current): 579 self.rootCheck(True) 441 self.rootCheck(True) 580 if not current: 442 if not current: 581 call('cat '+self.tpath 443 call('cat '+self.tpath+'available_filter_functions', shell=True) 582 return 444 return 583 master = self.listFromFile(sel 445 master = self.listFromFile(self.tpath+'available_filter_functions') 584 for i in sorted(self.tracefunc !! 446 for i in self.tracefuncs: 585 if 'func' in self.trac 447 if 'func' in self.tracefuncs[i]: 586 i = self.trace 448 i = self.tracefuncs[i]['func'] 587 if i in master: 449 if i in master: 588 print(i) !! 450 print i 589 else: 451 else: 590 print(self.col !! 452 print self.colorText(i) 591 def setFtraceFilterFunctions(self, lis 453 def setFtraceFilterFunctions(self, list): 592 master = self.listFromFile(sel 454 master = self.listFromFile(self.tpath+'available_filter_functions') 593 flist = '' 455 flist = '' 594 for i in list: 456 for i in list: 595 if i not in master: 457 if i not in master: 596 continue 458 continue 597 if ' [' in i: 459 if ' [' in i: 598 flist += i.spl 460 flist += i.split(' ')[0]+'\n' 599 else: 461 else: 600 flist += i+'\n 462 flist += i+'\n' 601 fp = open(self.tpath+'set_grap 463 fp = open(self.tpath+'set_graph_function', 'w') 602 fp.write(flist) 464 fp.write(flist) 603 fp.close() 465 fp.close() 604 def basicKprobe(self, name): 466 def basicKprobe(self, name): 605 self.kprobes[name] = {'name': 467 self.kprobes[name] = {'name': name,'func': name,'args': dict(),'format': name} 606 def defaultKprobe(self, name, kdata): 468 def defaultKprobe(self, name, kdata): 607 k = kdata 469 k = kdata 608 for field in ['name', 'format' 470 for field in ['name', 'format', 'func']: 609 if field not in k: 471 if field not in k: 610 k[field] = nam 472 k[field] = name 611 if self.archargs in k: 473 if self.archargs in k: 612 k['args'] = k[self.arc 474 k['args'] = k[self.archargs] 613 else: 475 else: 614 k['args'] = dict() 476 k['args'] = dict() 615 k['format'] = name 477 k['format'] = name 616 self.kprobes[name] = k 478 self.kprobes[name] = k 617 def kprobeColor(self, name): 479 def kprobeColor(self, name): 618 if name not in self.kprobes or 480 if name not in self.kprobes or 'color' not in self.kprobes[name]: 619 return '' 481 return '' 620 return self.kprobes[name]['col 482 return self.kprobes[name]['color'] 621 def kprobeDisplayName(self, name, data 483 def kprobeDisplayName(self, name, dataraw): 622 if name not in self.kprobes: 484 if name not in self.kprobes: 623 self.basicKprobe(name) 485 self.basicKprobe(name) 624 data = '' 486 data = '' 625 quote=0 487 quote=0 626 # first remvoe any spaces insi 488 # first remvoe any spaces inside quotes, and the quotes 627 for c in dataraw: 489 for c in dataraw: 628 if c == '"': 490 if c == '"': 629 quote = (quote 491 quote = (quote + 1) % 2 630 if quote and c == ' ': 492 if quote and c == ' ': 631 data += '_' 493 data += '_' 632 elif c != '"': 494 elif c != '"': 633 data += c 495 data += c 634 fmt, args = self.kprobes[name] 496 fmt, args = self.kprobes[name]['format'], self.kprobes[name]['args'] 635 arglist = dict() 497 arglist = dict() 636 # now process the args 498 # now process the args 637 for arg in sorted(args): 499 for arg in sorted(args): 638 arglist[arg] = '' 500 arglist[arg] = '' 639 m = re.match(r'.* '+ar !! 501 m = re.match('.* '+arg+'=(?P<arg>.*) ', data); 640 if m: 502 if m: 641 arglist[arg] = 503 arglist[arg] = m.group('arg') 642 else: 504 else: 643 m = re.match(r !! 505 m = re.match('.* '+arg+'=(?P<arg>.*)', data); 644 if m: 506 if m: 645 arglis 507 arglist[arg] = m.group('arg') 646 out = fmt.format(**arglist) 508 out = fmt.format(**arglist) 647 out = out.replace(' ', '_').re 509 out = out.replace(' ', '_').replace('"', '') 648 return out 510 return out 649 def kprobeText(self, kname, kprobe): 511 def kprobeText(self, kname, kprobe): 650 name = fmt = func = kname 512 name = fmt = func = kname 651 args = dict() 513 args = dict() 652 if 'name' in kprobe: 514 if 'name' in kprobe: 653 name = kprobe['name'] 515 name = kprobe['name'] 654 if 'format' in kprobe: 516 if 'format' in kprobe: 655 fmt = kprobe['format'] 517 fmt = kprobe['format'] 656 if 'func' in kprobe: 518 if 'func' in kprobe: 657 func = kprobe['func'] 519 func = kprobe['func'] 658 if self.archargs in kprobe: 520 if self.archargs in kprobe: 659 args = kprobe[self.arc 521 args = kprobe[self.archargs] 660 if 'args' in kprobe: 522 if 'args' in kprobe: 661 args = kprobe['args'] 523 args = kprobe['args'] 662 if re.findall('{(?P<n>[a-z,A-Z 524 if re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', func): 663 doError('Kprobe "%s" h 525 doError('Kprobe "%s" has format info in the function name "%s"' % (name, func)) 664 for arg in re.findall('{(?P<n> 526 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', fmt): 665 if arg not in args: 527 if arg not in args: 666 doError('Kprob 528 doError('Kprobe "%s" is missing argument "%s"' % (name, arg)) 667 val = 'p:%s_cal %s' % (name, f 529 val = 'p:%s_cal %s' % (name, func) 668 for i in sorted(args): 530 for i in sorted(args): 669 val += ' %s=%s' % (i, 531 val += ' %s=%s' % (i, args[i]) 670 val += '\nr:%s_ret %s $retval\ 532 val += '\nr:%s_ret %s $retval\n' % (name, func) 671 return val 533 return val 672 def addKprobes(self, output=False): 534 def addKprobes(self, output=False): 673 if len(self.kprobes) < 1: 535 if len(self.kprobes) < 1: 674 return 536 return 675 if output: 537 if output: 676 pprint(' kprobe fun !! 538 print(' kprobe functions in this kernel:') 677 # first test each kprobe 539 # first test each kprobe 678 rejects = [] 540 rejects = [] 679 # sort kprobes: trace, ub-dev, 541 # sort kprobes: trace, ub-dev, custom, dev 680 kpl = [[], [], [], []] 542 kpl = [[], [], [], []] 681 linesout = len(self.kprobes) 543 linesout = len(self.kprobes) 682 for name in sorted(self.kprobe 544 for name in sorted(self.kprobes): 683 res = self.colorText(' 545 res = self.colorText('YES', 32) 684 if not self.testKprobe 546 if not self.testKprobe(name, self.kprobes[name]): 685 res = self.col 547 res = self.colorText('NO') 686 rejects.append 548 rejects.append(name) 687 else: 549 else: 688 if name in sel 550 if name in self.tracefuncs: 689 kpl[0] 551 kpl[0].append(name) 690 elif name in s 552 elif name in self.dev_tracefuncs: 691 if 'ub 553 if 'ub' in self.dev_tracefuncs[name]: 692 554 kpl[1].append(name) 693 else: 555 else: 694 556 kpl[3].append(name) 695 else: 557 else: 696 kpl[2] 558 kpl[2].append(name) 697 if output: 559 if output: 698 pprint(' !! 560 print(' %s: %s' % (name, res)) 699 kplist = kpl[0] + kpl[1] + kpl 561 kplist = kpl[0] + kpl[1] + kpl[2] + kpl[3] 700 # remove all failed ones from 562 # remove all failed ones from the list 701 for name in rejects: 563 for name in rejects: 702 self.kprobes.pop(name) 564 self.kprobes.pop(name) 703 # set the kprobes all at once 565 # set the kprobes all at once 704 self.fsetVal('', 'kprobe_event 566 self.fsetVal('', 'kprobe_events') 705 kprobeevents = '' 567 kprobeevents = '' 706 for kp in kplist: 568 for kp in kplist: 707 kprobeevents += self.k 569 kprobeevents += self.kprobeText(kp, self.kprobes[kp]) 708 self.fsetVal(kprobeevents, 'kp 570 self.fsetVal(kprobeevents, 'kprobe_events') 709 if output: 571 if output: 710 check = self.fgetVal(' 572 check = self.fgetVal('kprobe_events') 711 linesack = (len(check. !! 573 linesack = (len(check.split('\n')) - 1) / 2 712 pprint(' kprobe fun !! 574 print(' kprobe functions enabled: %d/%d' % (linesack, linesout)) 713 self.fsetVal('1', 'events/kpro 575 self.fsetVal('1', 'events/kprobes/enable') 714 def testKprobe(self, kname, kprobe): 576 def testKprobe(self, kname, kprobe): 715 self.fsetVal('0', 'events/kpro 577 self.fsetVal('0', 'events/kprobes/enable') 716 kprobeevents = self.kprobeText 578 kprobeevents = self.kprobeText(kname, kprobe) 717 if not kprobeevents: 579 if not kprobeevents: 718 return False 580 return False 719 try: 581 try: 720 self.fsetVal(kprobeeve 582 self.fsetVal(kprobeevents, 'kprobe_events') 721 check = self.fgetVal(' 583 check = self.fgetVal('kprobe_events') 722 except: 584 except: 723 return False 585 return False 724 linesout = len(kprobeevents.sp 586 linesout = len(kprobeevents.split('\n')) 725 linesack = len(check.split('\n 587 linesack = len(check.split('\n')) 726 if linesack < linesout: 588 if linesack < linesout: 727 return False 589 return False 728 return True 590 return True 729 def setVal(self, val, file): !! 591 def setVal(self, val, file, mode='w'): 730 if not os.path.exists(file): 592 if not os.path.exists(file): 731 return False 593 return False 732 try: 594 try: 733 fp = open(file, 'wb', !! 595 fp = open(file, mode, 0) 734 fp.write(val.encode()) !! 596 fp.write(val) 735 fp.flush() 597 fp.flush() 736 fp.close() 598 fp.close() 737 except: 599 except: 738 return False 600 return False 739 return True 601 return True 740 def fsetVal(self, val, path): !! 602 def fsetVal(self, val, path, mode='w'): 741 if not self.useftrace: !! 603 return self.setVal(val, self.tpath+path, mode) 742 return False << 743 return self.setVal(val, self.t << 744 def getVal(self, file): 604 def getVal(self, file): 745 res = '' 605 res = '' 746 if not os.path.exists(file): 606 if not os.path.exists(file): 747 return res 607 return res 748 try: 608 try: 749 fp = open(file, 'r') 609 fp = open(file, 'r') 750 res = fp.read() 610 res = fp.read() 751 fp.close() 611 fp.close() 752 except: 612 except: 753 pass 613 pass 754 return res 614 return res 755 def fgetVal(self, path): 615 def fgetVal(self, path): 756 if not self.useftrace: << 757 return '' << 758 return self.getVal(self.tpath+ 616 return self.getVal(self.tpath+path) 759 def cleanupFtrace(self): 617 def cleanupFtrace(self): 760 if self.useftrace: !! 618 if(self.usecallgraph or self.usetraceevents or self.usedevsrc): 761 self.fsetVal('0', 'eve 619 self.fsetVal('0', 'events/kprobes/enable') 762 self.fsetVal('', 'kpro 620 self.fsetVal('', 'kprobe_events') 763 self.fsetVal('1024', ' 621 self.fsetVal('1024', 'buffer_size_kb') 764 def setupAllKprobes(self): 622 def setupAllKprobes(self): 765 for name in self.tracefuncs: 623 for name in self.tracefuncs: 766 self.defaultKprobe(nam 624 self.defaultKprobe(name, self.tracefuncs[name]) 767 for name in self.dev_tracefunc 625 for name in self.dev_tracefuncs: 768 self.defaultKprobe(nam 626 self.defaultKprobe(name, self.dev_tracefuncs[name]) 769 def isCallgraphFunc(self, name): 627 def isCallgraphFunc(self, name): 770 if len(self.tracefuncs) < 1 an 628 if len(self.tracefuncs) < 1 and self.suspendmode == 'command': 771 return True 629 return True 772 for i in self.tracefuncs: 630 for i in self.tracefuncs: 773 if 'func' in self.trac 631 if 'func' in self.tracefuncs[i]: 774 f = self.trace 632 f = self.tracefuncs[i]['func'] 775 else: 633 else: 776 f = i 634 f = i 777 if name == f: 635 if name == f: 778 return True 636 return True 779 return False 637 return False 780 def initFtrace(self, quiet=False): !! 638 def initFtrace(self): 781 if not self.useftrace: !! 639 self.printSystemInfo(False) 782 return !! 640 print('INITIALIZING FTRACE...') 783 if not quiet: << 784 sysvals.printSystemInf << 785 pprint('INITIALIZING F << 786 # turn trace off 641 # turn trace off 787 self.fsetVal('0', 'tracing_on' 642 self.fsetVal('0', 'tracing_on') 788 self.cleanupFtrace() 643 self.cleanupFtrace() 789 # set the trace clock to globa 644 # set the trace clock to global 790 self.fsetVal('global', 'trace_ 645 self.fsetVal('global', 'trace_clock') 791 self.fsetVal('nop', 'current_t 646 self.fsetVal('nop', 'current_tracer') 792 # set trace buffer to an appro 647 # set trace buffer to an appropriate value 793 cpus = max(1, self.cpucount) 648 cpus = max(1, self.cpucount) 794 if self.bufsize > 0: 649 if self.bufsize > 0: 795 tgtsize = self.bufsize 650 tgtsize = self.bufsize 796 elif self.usecallgraph or self 651 elif self.usecallgraph or self.usedevsrc: 797 bmax = (1*1024*1024) i !! 652 tgtsize = min(self.memfree, 3*1024*1024) 798 else (3*1024*1 << 799 tgtsize = min(self.mem << 800 else: 653 else: 801 tgtsize = 65536 654 tgtsize = 65536 802 while not self.fsetVal('%d' % !! 655 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'): 803 # if the size failed t 656 # if the size failed to set, lower it and keep trying 804 tgtsize -= 65536 657 tgtsize -= 65536 805 if tgtsize < 65536: 658 if tgtsize < 65536: 806 tgtsize = int( 659 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus 807 break 660 break 808 self.vprint('Setting trace buf !! 661 print 'Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus) 809 # initialize the callgraph tra 662 # initialize the callgraph trace 810 if(self.usecallgraph): 663 if(self.usecallgraph): 811 # set trace type 664 # set trace type 812 self.fsetVal('function 665 self.fsetVal('function_graph', 'current_tracer') 813 self.fsetVal('', 'set_ 666 self.fsetVal('', 'set_ftrace_filter') 814 # temporary hack to fi << 815 fp = open(self.tpath+' << 816 fp.write('native_queue << 817 fp.close() << 818 # set trace format opt 667 # set trace format options 819 self.fsetVal('print-pa 668 self.fsetVal('print-parent', 'trace_options') 820 self.fsetVal('funcgrap 669 self.fsetVal('funcgraph-abstime', 'trace_options') 821 self.fsetVal('funcgrap 670 self.fsetVal('funcgraph-cpu', 'trace_options') 822 self.fsetVal('funcgrap 671 self.fsetVal('funcgraph-duration', 'trace_options') 823 self.fsetVal('funcgrap 672 self.fsetVal('funcgraph-proc', 'trace_options') 824 self.fsetVal('funcgrap 673 self.fsetVal('funcgraph-tail', 'trace_options') 825 self.fsetVal('nofuncgr 674 self.fsetVal('nofuncgraph-overhead', 'trace_options') 826 self.fsetVal('context- 675 self.fsetVal('context-info', 'trace_options') 827 self.fsetVal('graph-ti 676 self.fsetVal('graph-time', 'trace_options') 828 self.fsetVal('%d' % se 677 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth') 829 cf = ['dpm_run_callbac 678 cf = ['dpm_run_callback'] 830 if(self.usetraceevents 679 if(self.usetraceevents): 831 cf += ['dpm_pr 680 cf += ['dpm_prepare', 'dpm_complete'] 832 for fn in self.tracefu 681 for fn in self.tracefuncs: 833 if 'func' in s 682 if 'func' in self.tracefuncs[fn]: 834 cf.app 683 cf.append(self.tracefuncs[fn]['func']) 835 else: 684 else: 836 cf.app 685 cf.append(fn) 837 if self.ftop: !! 686 self.setFtraceFilterFunctions(cf) 838 self.setFtrace << 839 else: << 840 self.setFtrace << 841 # initialize the kprobe trace 687 # initialize the kprobe trace 842 elif self.usekprobes: 688 elif self.usekprobes: 843 for name in self.trace 689 for name in self.tracefuncs: 844 self.defaultKp 690 self.defaultKprobe(name, self.tracefuncs[name]) 845 if self.usedevsrc: 691 if self.usedevsrc: 846 for name in se 692 for name in self.dev_tracefuncs: 847 self.d 693 self.defaultKprobe(name, self.dev_tracefuncs[name]) 848 if not quiet: !! 694 print('INITIALIZING KPROBES...') 849 pprint('INITIA << 850 self.addKprobes(self.v 695 self.addKprobes(self.verbose) 851 if(self.usetraceevents): 696 if(self.usetraceevents): 852 # turn trace events on 697 # turn trace events on 853 events = iter(self.tra 698 events = iter(self.traceevents) 854 for e in events: 699 for e in events: 855 self.fsetVal(' 700 self.fsetVal('1', 'events/power/'+e+'/enable') 856 # clear the trace buffer 701 # clear the trace buffer 857 self.fsetVal('', 'trace') 702 self.fsetVal('', 'trace') 858 def verifyFtrace(self): 703 def verifyFtrace(self): 859 # files needed for any trace d 704 # files needed for any trace data 860 files = ['buffer_size_kb', 'cu 705 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock', 861 'trace_marker 706 'trace_marker', 'trace_options', 'tracing_on'] 862 # files needed for callgraph t 707 # files needed for callgraph trace data 863 tp = self.tpath 708 tp = self.tpath 864 if(self.usecallgraph): 709 if(self.usecallgraph): 865 files += [ 710 files += [ 866 'available_fil 711 'available_filter_functions', 867 'set_ftrace_fi 712 'set_ftrace_filter', 868 'set_graph_fun 713 'set_graph_function' 869 ] 714 ] 870 for f in files: 715 for f in files: 871 if(os.path.exists(tp+f 716 if(os.path.exists(tp+f) == False): 872 return False 717 return False 873 return True 718 return True 874 def verifyKprobes(self): 719 def verifyKprobes(self): 875 # files needed for kprobes to 720 # files needed for kprobes to work 876 files = ['kprobe_events', 'eve 721 files = ['kprobe_events', 'events'] 877 tp = self.tpath 722 tp = self.tpath 878 for f in files: 723 for f in files: 879 if(os.path.exists(tp+f 724 if(os.path.exists(tp+f) == False): 880 return False 725 return False 881 return True 726 return True 882 def colorText(self, str, color=31): 727 def colorText(self, str, color=31): 883 if not self.ansi: 728 if not self.ansi: 884 return str 729 return str 885 return '\x1B[%d;40m%s\x1B[m' % 730 return '\x1B[%d;40m%s\x1B[m' % (color, str) 886 def writeDatafileHeader(self, filename !! 731 def writeDatafileHeader(self, filename, fwdata=[]): 887 fp = self.openlog(filename, 'w 732 fp = self.openlog(filename, 'w') 888 fp.write('%s\n%s\n# command | 733 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline)) 889 for test in testdata: !! 734 if(self.suspendmode == 'mem' or self.suspendmode == 'command'): 890 if 'fw' in test: !! 735 for fw in fwdata: 891 fw = test['fw' << 892 if(fw): 736 if(fw): 893 fp.wri 737 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) 894 if 'turbo' in test: << 895 fp.write('# tu << 896 if 'wifi' in test: << 897 fp.write('# wi << 898 if 'netfix' in test: << 899 fp.write('# ne << 900 if test['error'] or le << 901 fp.write('# en << 902 return fp 738 return fp 903 def sudoUserchown(self, dir): !! 739 def sudouser(self, dir): 904 if os.path.exists(dir) and sel !! 740 if os.path.exists(dir) and os.getuid() == 0 and \ >> 741 'SUDO_USER' in os.environ: 905 cmd = 'chown -R {0}:{0 742 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 906 call(cmd.format(self.s !! 743 call(cmd.format(os.environ['SUDO_USER'], dir), shell=True) 907 def outputResult(self, testdata, num=0 744 def outputResult(self, testdata, num=0): 908 if not self.result: 745 if not self.result: 909 return 746 return 910 n = '' 747 n = '' 911 if num > 0: 748 if num > 0: 912 n = '%d' % num 749 n = '%d' % num 913 fp = open(self.result, 'a') 750 fp = open(self.result, 'a') 914 if 'error' in testdata: 751 if 'error' in testdata: 915 fp.write('result%s: fa 752 fp.write('result%s: fail\n' % n) 916 fp.write('error%s: %s\ 753 fp.write('error%s: %s\n' % (n, testdata['error'])) 917 else: 754 else: 918 fp.write('result%s: pa 755 fp.write('result%s: pass\n' % n) 919 if 'mode' in testdata: << 920 fp.write('mode%s: %s\n << 921 for v in ['suspend', 'resume', 756 for v in ['suspend', 'resume', 'boot', 'lastinit']: 922 if v in testdata: 757 if v in testdata: 923 fp.write('%s%s 758 fp.write('%s%s: %.3f\n' % (v, n, testdata[v])) 924 for v in ['fwsuspend', 'fwresu 759 for v in ['fwsuspend', 'fwresume']: 925 if v in testdata: 760 if v in testdata: 926 fp.write('%s%s 761 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0)) 927 if 'bugurl' in testdata: 762 if 'bugurl' in testdata: 928 fp.write('url%s: %s\n' 763 fp.write('url%s: %s\n' % (n, testdata['bugurl'])) 929 fp.close() 764 fp.close() 930 self.sudoUserchown(self.result !! 765 self.sudouser(self.result) 931 def configFile(self, file): 766 def configFile(self, file): 932 dir = os.path.dirname(os.path. 767 dir = os.path.dirname(os.path.realpath(__file__)) 933 if os.path.exists(file): 768 if os.path.exists(file): 934 return file 769 return file 935 elif os.path.exists(dir+'/'+fi 770 elif os.path.exists(dir+'/'+file): 936 return dir+'/'+file 771 return dir+'/'+file 937 elif os.path.exists(dir+'/conf 772 elif os.path.exists(dir+'/config/'+file): 938 return dir+'/config/'+ 773 return dir+'/config/'+file 939 return '' 774 return '' 940 def openlog(self, filename, mode): 775 def openlog(self, filename, mode): 941 isgz = self.gzip 776 isgz = self.gzip 942 if mode == 'r': 777 if mode == 'r': 943 try: 778 try: 944 with gzip.open !! 779 with gzip.open(filename, mode+'b') as fp: 945 test = 780 test = fp.read(64) 946 isgz = True 781 isgz = True 947 except: 782 except: 948 isgz = False 783 isgz = False 949 if isgz: 784 if isgz: 950 return gzip.open(filen !! 785 return gzip.open(filename, mode+'b') 951 return open(filename, mode) 786 return open(filename, mode) 952 def putlog(self, filename, text): << 953 with self.openlog(filename, 'a << 954 fp.write(text) << 955 fp.close() << 956 def dlog(self, text): << 957 if not self.dmesgfile: << 958 return << 959 self.putlog(self.dmesgfile, '# << 960 def flog(self, text): << 961 self.putlog(self.ftracefile, t << 962 def b64unzip(self, data): << 963 try: << 964 out = codecs.decode(ba << 965 except: << 966 out = data << 967 return out << 968 def b64zip(self, data): << 969 out = base64.b64encode(codecs. << 970 return out << 971 def platforminfo(self, cmdafter): << 972 # add platform info on to a co << 973 if not os.path.exists(self.ftr << 974 return False << 975 footer = '#\n' << 976 << 977 # add test command string line << 978 if self.suspendmode == 'comman << 979 footer += '# platform- << 980 << 981 # get a list of target devices << 982 props = dict() << 983 tp = TestProps() << 984 tf = self.openlog(self.ftracef << 985 for line in tf: << 986 if tp.stampInfo(line, << 987 continue << 988 # parse only valid lin << 989 m = re.match(tp.ftrace << 990 if(not m or 'device_pm << 991 continue << 992 m = re.match(r'.*: (?P << 993 if(not m): << 994 continue << 995 dev = m.group('d') << 996 if dev not in props: << 997 props[dev] = D << 998 tf.close() << 999 << 1000 # now get the syspath for eac << 1001 for dirname, dirnames, filena << 1002 if(re.match(r'.*/powe << 1003 dev = dirname << 1004 if dev in pro << 1005 props << 1006 << 1007 # now fill in the properties << 1008 for dev in sorted(props): << 1009 dirname = props[dev]. << 1010 if not dirname or not << 1011 continue << 1012 props[dev].isasync = << 1013 if os.path.exists(dir << 1014 fp = open(dir << 1015 if 'enabled' << 1016 props << 1017 fp.close() << 1018 fields = os.listdir(d << 1019 for file in ['product << 1020 if file not i << 1021 conti << 1022 try: << 1023 with << 1024 << 1025 except: << 1026 conti << 1027 if file == 'i << 1028 idv, << 1029 try: << 1030 << 1031 << 1032 excep << 1033 << 1034 << 1035 props << 1036 break << 1037 if props[dev].altname << 1038 out = props[d << 1039 .repl << 1040 props[dev].al << 1041 << 1042 # add a devinfo line to the b << 1043 out = '' << 1044 for dev in sorted(props): << 1045 out += props[dev].out << 1046 footer += '# platform-devinfo << 1047 << 1048 # add a line for each of thes << 1049 for name, cmdline, info in cm << 1050 footer += '# platform << 1051 self.flog(footer) << 1052 return True << 1053 def commonPrefix(self, list): << 1054 if len(list) < 2: << 1055 return '' << 1056 prefix = list[0] << 1057 for s in list[1:]: << 1058 while s[:len(prefix)] << 1059 prefix = pref << 1060 if not prefix: << 1061 break << 1062 if '/' in prefix and prefix[- << 1063 prefix = prefix[0:pre << 1064 return prefix << 1065 def dictify(self, text, format): << 1066 out = dict() << 1067 header = True if format == 1 << 1068 delim = ' ' if format == 1 el << 1069 for line in text.split('\n'): << 1070 if header: << 1071 header, out[' << 1072 continue << 1073 line = line.strip() << 1074 if delim in line: << 1075 data = line.s << 1076 num = re.sear << 1077 if format == << 1078 out[d << 1079 else: << 1080 out[d << 1081 return out << 1082 def cmdinfovar(self, arg): << 1083 if arg == 'ethdev': << 1084 try: << 1085 cmd = [self.g << 1086 fp = Popen(cm << 1087 info = ascii( << 1088 fp.close() << 1089 except: << 1090 return 'iptoo << 1091 for line in info.spli << 1092 if line[0] == << 1093 retur << 1094 return 'nodevicefound << 1095 return 'unknown' << 1096 def cmdinfo(self, begin, debug=False) << 1097 out = [] << 1098 if begin: << 1099 self.cmd1 = dict() << 1100 for cargs in self.infocmds: << 1101 delta, name, args = c << 1102 for i in range(len(ar << 1103 if args[i][0] << 1104 args[ << 1105 cmdline, cmdpath = ' << 1106 if not cmdpath or (be << 1107 continue << 1108 self.dlog('[%s]' % cm << 1109 try: << 1110 fp = Popen([c << 1111 info = ascii( << 1112 fp.close() << 1113 except: << 1114 continue << 1115 if not debug and begi << 1116 self.cmd1[nam << 1117 elif not debug and de << 1118 before, after << 1119 dinfo = ('\t% << 1120 prefix = self << 1121 for key in so << 1122 if ke << 1123 << 1124 << 1125 << 1126 << 1127 << 1128 << 1129 << 1130 dinfo = '\tno << 1131 out.append((n << 1132 else: << 1133 out.append((n << 1134 return out << 1135 def testVal(self, file, fmt='basic', << 1136 if file == 'restoreall': << 1137 for f in self.cfgdef: << 1138 if os.path.ex << 1139 fp = << 1140 fp.wr << 1141 fp.cl << 1142 self.cfgdef = dict() << 1143 elif value and os.path.exists << 1144 fp = open(file, 'r+') << 1145 if fmt == 'radio': << 1146 m = re.match( << 1147 if m: << 1148 self. << 1149 elif fmt == 'acpi': << 1150 line = fp.rea << 1151 m = re.match( << 1152 if m: << 1153 self. << 1154 else: << 1155 self.cfgdef[f << 1156 fp.write(value) << 1157 fp.close() << 1158 def s0ixSupport(self): << 1159 if not os.path.exists(self.s0 << 1160 return False << 1161 fp = open(sysvals.mempowerfil << 1162 data = fp.read().strip() << 1163 fp.close() << 1164 if '[s2idle]' in data: << 1165 return True << 1166 return False << 1167 def haveTurbostat(self): << 1168 if not self.tstat: << 1169 return False << 1170 cmd = self.getExec('turbostat << 1171 if not cmd: << 1172 return False << 1173 fp = Popen([cmd, '-v'], stdou << 1174 out = ascii(fp.read()).strip( << 1175 fp.close() << 1176 if re.match(r'turbostat versi << 1177 self.vprint(out) << 1178 return True << 1179 return False << 1180 def turbostat(self, s0ixready): << 1181 cmd = self.getExec('turbostat << 1182 rawout = keyline = valline = << 1183 fullcmd = '%s -q -S echo free << 1184 fp = Popen(['sh', '-c', fullc << 1185 for line in fp.stderr: << 1186 line = ascii(line) << 1187 rawout += line << 1188 if keyline and vallin << 1189 continue << 1190 if re.match(r'(?i)Avg << 1191 keyline = lin << 1192 elif keyline: << 1193 valline = lin << 1194 fp.wait() << 1195 if not keyline or not valline << 1196 errmsg = 'unrecognize << 1197 self.vprint(errmsg) << 1198 if not self.verbose: << 1199 pprint(errmsg << 1200 return (fp.returncode << 1201 if self.verbose: << 1202 pprint(rawout.strip() << 1203 out = [] << 1204 for key in keyline: << 1205 idx = keyline.index(k << 1206 val = valline[idx] << 1207 if key == 'SYS%LPI' a << 1208 continue << 1209 out.append('%s=%s' % << 1210 return (fp.returncode, '|'.jo << 1211 def netfixon(self, net='both'): << 1212 cmd = self.getExec('netfix') << 1213 if not cmd: << 1214 return '' << 1215 fp = Popen([cmd, '-s', net, ' << 1216 out = ascii(fp.read()).strip( << 1217 fp.close() << 1218 return out << 1219 def wifiDetails(self, dev): << 1220 try: << 1221 info = open('/sys/cla << 1222 except: << 1223 return dev << 1224 vals = [dev] << 1225 for prop in info.split('\n'): << 1226 if prop.startswith('D << 1227 vals.append(p << 1228 return ':'.join(vals) << 1229 def checkWifi(self, dev=''): << 1230 try: << 1231 w = open('/proc/net/w << 1232 except: << 1233 return '' << 1234 for line in reversed(w.split( << 1235 m = re.match(r' *(?P< << 1236 if not m or (dev and << 1237 continue << 1238 return m.group('dev') << 1239 return '' << 1240 def pollWifi(self, dev, timeout=10): << 1241 start = time.time() << 1242 while (time.time() - start) < << 1243 w = self.checkWifi(de << 1244 if w: << 1245 return '%s re << 1246 (self << 1247 time.sleep(0.01) << 1248 return '%s timeout %d' % (sel << 1249 def errorSummary(self, errinfo, msg): << 1250 found = False << 1251 for entry in errinfo: << 1252 if re.match(entry['ma << 1253 entry['count' << 1254 if self.hostn << 1255 entry << 1256 elif self.htm << 1257 entry << 1258 found = True << 1259 break << 1260 if found: << 1261 return << 1262 arr = msg.split() << 1263 for j in range(len(arr)): << 1264 if re.match(r'^[0-9,\ << 1265 arr[j] = r'[0 << 1266 else: << 1267 arr[j] = arr[ << 1268 .repl << 1269 .repl << 1270 .repl << 1271 .repl << 1272 mstr = ' *'.join(arr) << 1273 entry = { << 1274 'line': msg, << 1275 'match': mstr, << 1276 'count': 1, << 1277 'urls': {self.hostnam << 1278 } << 1279 errinfo.append(entry) << 1280 def multistat(self, start, idx, finis << 1281 if 'time' in self.multitest: << 1282 id = '%d Duration=%dm << 1283 else: << 1284 id = '%d/%d' % (idx+1 << 1285 t = time.time() << 1286 if 'start' not in self.multit << 1287 self.multitest['start << 1288 self.multitest['total << 1289 pprint('TEST (%s) STA << 1290 return << 1291 dt = t - self.multitest['last << 1292 if not start: << 1293 if idx == 0 and self. << 1294 self.multites << 1295 pprint('TEST (%s) COM << 1296 return << 1297 self.multitest['total'] += dt << 1298 self.multitest['last'] = t << 1299 avg = self.multitest['total'] << 1300 if 'time' in self.multitest: << 1301 left = finish - datet << 1302 left -= timedelta(mic << 1303 else: << 1304 left = timedelta(seco << 1305 pprint('TEST (%s) START - Avg << 1306 (id, avg, str(left))) << 1307 def multiinit(self, c, d): << 1308 sz, unit = 'count', 'm' << 1309 if c.endswith('d') or c.endsw << 1310 sz, unit, c = 'time', << 1311 self.multitest['run'] = True << 1312 self.multitest[sz] = getArgIn << 1313 self.multitest['delay'] = get << 1314 if unit == 'd': << 1315 self.multitest[sz] *= << 1316 elif unit == 'h': << 1317 self.multitest[sz] *= << 1318 def displayControl(self, cmd): << 1319 xset, ret = 'timeout 10 xset << 1320 if self.sudouser: << 1321 xset = 'sudo -u %s %s << 1322 if cmd == 'init': << 1323 ret = call(xset.forma << 1324 if not ret: << 1325 ret = call(xs << 1326 elif cmd == 'reset': << 1327 ret = call(xset.forma << 1328 elif cmd in ['on', 'off', 'st << 1329 b4 = self.displayCont << 1330 ret = call(xset.forma << 1331 if not ret: << 1332 curr = self.d << 1333 self.vprint(' << 1334 if curr != cm << 1335 self. << 1336 if ret: << 1337 self.vprint(' << 1338 return ret << 1339 elif cmd == 'stat': << 1340 fp = Popen(xset.forma << 1341 ret = 'unknown' << 1342 for line in fp: << 1343 m = re.match( << 1344 if(m and len( << 1345 out = << 1346 ret = << 1347 break << 1348 fp.close() << 1349 return ret << 1350 def setRuntimeSuspend(self, before=Tr << 1351 if before: << 1352 # runtime suspend dis << 1353 if self.rs > 0: << 1354 self.rstgt, s << 1355 else: << 1356 self.rstgt, s << 1357 pprint('CONFIGURING R << 1358 self.rslist = deviceI << 1359 for i in self.rslist: << 1360 self.setVal(s << 1361 pprint('runtime suspe << 1362 pprint('waiting 5 sec << 1363 time.sleep(5) << 1364 else: << 1365 # runtime suspend re- << 1366 for i in self.rslist: << 1367 self.setVal(s << 1368 pprint('runtime suspe << 1369 def start(self, pm): << 1370 if self.useftrace: << 1371 self.dlog('start ftra << 1372 self.fsetVal('1', 'tr << 1373 if self.useprocmon: << 1374 self.dlog('st << 1375 pm.start() << 1376 def stop(self, pm): << 1377 if self.useftrace: << 1378 if self.useprocmon: << 1379 self.dlog('st << 1380 pm.stop() << 1381 self.dlog('stop ftrac << 1382 self.fsetVal('0', 'tr << 1383 787 1384 sysvals = SystemValues() 788 sysvals = SystemValues() 1385 switchvalues = ['enable', 'disable', 'on', 'o 789 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] 1386 switchoff = ['disable', 'off', 'false', '0'] 790 switchoff = ['disable', 'off', 'false', '0'] 1387 suspendmodename = { 791 suspendmodename = { 1388 'standby': 'standby (S1)', !! 792 'freeze': 'Freeze (S0)', 1389 'freeze': 'freeze (S2idle)', !! 793 'standby': 'Standby (S1)', 1390 'mem': 'suspend (S3)', !! 794 'mem': 'Suspend (S3)', 1391 'disk': 'hibernate (S4)' !! 795 'disk': 'Hibernate (S4)' 1392 } 796 } 1393 797 1394 # Class: DevProps 798 # Class: DevProps 1395 # Description: 799 # Description: 1396 # Simple class which holds property va 800 # Simple class which holds property values collected 1397 # for all the devices used in the time 801 # for all the devices used in the timeline. 1398 class DevProps: 802 class DevProps: 1399 def __init__(self): !! 803 syspath = '' 1400 self.syspath = '' !! 804 altname = '' 1401 self.altname = '' !! 805 async = True 1402 self.isasync = True !! 806 xtraclass = '' 1403 self.xtraclass = '' !! 807 xtrainfo = '' 1404 self.xtrainfo = '' << 1405 def out(self, dev): 808 def out(self, dev): 1406 return '%s,%s,%d;' % (dev, se !! 809 return '%s,%s,%d;' % (dev, self.altname, self.async) 1407 def debug(self, dev): 810 def debug(self, dev): 1408 pprint('%s:\n\taltname = %s\n !! 811 print '%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async) 1409 def altName(self, dev): 812 def altName(self, dev): 1410 if not self.altname or self.a 813 if not self.altname or self.altname == dev: 1411 return dev 814 return dev 1412 return '%s [%s]' % (self.altn 815 return '%s [%s]' % (self.altname, dev) 1413 def xtraClass(self): 816 def xtraClass(self): 1414 if self.xtraclass: 817 if self.xtraclass: 1415 return ' '+self.xtrac 818 return ' '+self.xtraclass 1416 if not self.isasync: !! 819 if not self.async: 1417 return ' sync' 820 return ' sync' 1418 return '' 821 return '' 1419 def xtraInfo(self): 822 def xtraInfo(self): 1420 if self.xtraclass: 823 if self.xtraclass: 1421 return ' '+self.xtrac 824 return ' '+self.xtraclass 1422 if self.isasync: !! 825 if self.async: 1423 return ' (async)' !! 826 return ' async_device' 1424 return ' (sync)' !! 827 return ' sync_device' 1425 828 1426 # Class: DeviceNode 829 # Class: DeviceNode 1427 # Description: 830 # Description: 1428 # A container used to create a device 831 # A container used to create a device hierachy, with a single root node 1429 # and a tree of child nodes. Used by D 832 # and a tree of child nodes. Used by Data.deviceTopology() 1430 class DeviceNode: 833 class DeviceNode: >> 834 name = '' >> 835 children = 0 >> 836 depth = 0 1431 def __init__(self, nodename, nodedept 837 def __init__(self, nodename, nodedepth): 1432 self.name = nodename 838 self.name = nodename 1433 self.children = [] 839 self.children = [] 1434 self.depth = nodedepth 840 self.depth = nodedepth 1435 841 1436 # Class: Data 842 # Class: Data 1437 # Description: 843 # Description: 1438 # The primary container for suspend/re 844 # The primary container for suspend/resume test data. There is one for 1439 # each test run. The data is organized 845 # each test run. The data is organized into a cronological hierarchy: 1440 # Data.dmesg { 846 # Data.dmesg { 1441 # phases { 847 # phases { 1442 # 10 sequential, non-ov 848 # 10 sequential, non-overlapping phases of S/R 1443 # contents: times for p 849 # contents: times for phase start/end, order/color data for html 1444 # devlist { 850 # devlist { 1445 # device callba 851 # device callback or action list for this phase 1446 # device { 852 # device { 1447 # a sin 853 # a single device callback or generic action 1448 # conte 854 # contents: start/stop times, pid/cpu/driver info 1449 # 855 # parents/children, html id for timeline/callgraph 1450 # 856 # optionally includes an ftrace callgraph 1451 # 857 # optionally includes dev/ps data 1452 # } 858 # } 1453 # } 859 # } 1454 # } 860 # } 1455 # } 861 # } 1456 # 862 # 1457 class Data: 863 class Data: 1458 phasedef = { !! 864 dmesg = {} # root data structure 1459 'suspend_prepare': {'order': !! 865 phases = [] # ordered list of phases 1460 'suspend': {'order': !! 866 start = 0.0 # test start 1461 'suspend_late': {'order': !! 867 end = 0.0 # test end 1462 'suspend_noirq': {'order': !! 868 tSuspended = 0.0 # low-level suspend start 1463 'suspend_machine': {'order': !! 869 tResumed = 0.0 # low-level resume start 1464 'resume_machine': {'order': !! 870 tKernSus = 0.0 # kernel level suspend start 1465 'resume_noirq': {'order': !! 871 tKernRes = 0.0 # kernel level resume end 1466 'resume_early': {'order': !! 872 tLow = 0.0 # time spent in low-level suspend (standby/freeze) 1467 'resume': {'order': !! 873 fwValid = False # is firmware data available 1468 'resume_complete': {'order': !! 874 fwSuspend = 0 # time spent in firmware suspend 1469 } !! 875 fwResume = 0 # time spent in firmware resume 1470 errlist = { !! 876 dmesgtext = [] # dmesg text file in memory 1471 'HWERROR' : r'.*\[ *Hardware !! 877 pstl = 0 # process timeline 1472 'FWBUG' : r'.*\[ *Firmware !! 878 testnumber = 0 1473 'TASKFAIL': r'.*Freezing .*af !! 879 idstr = '' 1474 'BUG' : r'(?i).*\bBUG\b.* !! 880 html_device_id = 0 1475 'ERROR' : r'(?i).*\bERROR\b !! 881 stamp = 0 1476 'WARNING' : r'(?i).*\bWARNING !! 882 outfile = '' 1477 'FAULT' : r'(?i).*\bFAULT\b !! 883 devpids = [] 1478 'FAIL' : r'(?i).*\bFAILED\ !! 884 kerror = False 1479 'INVALID' : r'(?i).*\bINVALID << 1480 'CRASH' : r'(?i).*\bCRASHED << 1481 'TIMEOUT' : r'(?i).*\bTIMEOUT << 1482 'ABORT' : r'(?i).*\bABORT\b << 1483 'IRQ' : r'.*\bgenirq: .*' << 1484 'ACPI' : r'.*\bACPI *(?P<b << 1485 'DISKFULL': r'.*\bNo space le << 1486 'USBERR' : r'.*usb .*device << 1487 'ATAERR' : r' *ata[0-9\.]*: << 1488 'MEIERR' : r' *mei.*: .*fail << 1489 'TPMERR' : r'(?i) *tpm *tpm[ << 1490 } << 1491 def __init__(self, num): 885 def __init__(self, num): 1492 idchar = 'abcdefghij' 886 idchar = 'abcdefghij' 1493 self.start = 0.0 # test start !! 887 self.pstl = dict() 1494 self.end = 0.0 # test end << 1495 self.hwstart = 0 # rtc test s << 1496 self.hwend = 0 # rtc test e << 1497 self.tSuspended = 0.0 # low-l << 1498 self.tResumed = 0.0 # low-l << 1499 self.tKernSus = 0.0 # kerne << 1500 self.tKernRes = 0.0 # kerne << 1501 self.fwValid = False # is fi << 1502 self.fwSuspend = 0 # time << 1503 self.fwResume = 0 # time << 1504 self.html_device_id = 0 << 1505 self.stamp = 0 << 1506 self.outfile = '' << 1507 self.kerror = False << 1508 self.wifi = dict() << 1509 self.turbostat = 0 << 1510 self.enterfail = '' << 1511 self.currphase = '' << 1512 self.pstl = dict() # proce << 1513 self.testnumber = num 888 self.testnumber = num 1514 self.idstr = idchar[num] 889 self.idstr = idchar[num] 1515 self.dmesgtext = [] # dmesg !! 890 self.dmesgtext = [] 1516 self.dmesg = dict() # root !! 891 self.phases = [] 1517 self.errorinfo = {'suspend':[ !! 892 self.dmesg = { # fixed list of 10 phases 1518 self.tLow = [] # time !! 893 'suspend_prepare': {'list': dict(), 'start': -1.0, 'end': -1.0, 1519 self.devpids = [] !! 894 'row': 0, 'color': '#CCFFCC', 'order': 0}, 1520 self.devicegroups = 0 !! 895 'suspend': {'list': dict(), 'start': -1.0, 'end': -1.0, 1521 def sortedPhases(self): !! 896 'row': 0, 'color': '#88FF88', 'order': 1}, 1522 return sorted(self.dmesg, key !! 897 'suspend_late': {'list': dict(), 'start': -1.0, 'end': -1.0, 1523 def initDevicegroups(self): !! 898 'row': 0, 'color': '#00AA00', 'order': 2}, 1524 # called when phases are all !! 899 'suspend_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, 1525 for phase in sorted(self.dmes !! 900 'row': 0, 'color': '#008888', 'order': 3}, 1526 if '*' in phase: !! 901 'suspend_machine': {'list': dict(), 'start': -1.0, 'end': -1.0, 1527 p = phase.spl !! 902 'row': 0, 'color': '#0000FF', 'order': 4}, 1528 pnew = '%s%d' !! 903 'resume_machine': {'list': dict(), 'start': -1.0, 'end': -1.0, 1529 self.dmesg[pn !! 904 'row': 0, 'color': '#FF0000', 'order': 5}, >> 905 'resume_noirq': {'list': dict(), 'start': -1.0, 'end': -1.0, >> 906 'row': 0, 'color': '#FF9900', 'order': 6}, >> 907 'resume_early': {'list': dict(), 'start': -1.0, 'end': -1.0, >> 908 'row': 0, 'color': '#FFCC00', 'order': 7}, >> 909 'resume': {'list': dict(), 'start': -1.0, 'end': -1.0, >> 910 'row': 0, 'color': '#FFFF88', 'order': 8}, >> 911 'resume_complete': {'list': dict(), 'start': -1.0, 'end': -1.0, >> 912 'row': 0, 'color': '#FFFFCC', 'order': 9} >> 913 } >> 914 self.phases = self.sortedPhases() 1530 self.devicegroups = [] 915 self.devicegroups = [] 1531 for phase in self.sortedPhase !! 916 for phase in self.phases: 1532 self.devicegroups.app 917 self.devicegroups.append([phase]) 1533 def nextPhase(self, phase, offset): !! 918 self.errorinfo = {'suspend':[],'resume':[]} 1534 order = self.dmesg[phase]['or << 1535 for p in self.dmesg: << 1536 if self.dmesg[p]['ord << 1537 return p << 1538 return '' << 1539 def lastPhase(self, depth=1): << 1540 plist = self.sortedPhases() << 1541 if len(plist) < depth: << 1542 return '' << 1543 return plist[-1*depth] << 1544 def turbostatInfo(self): << 1545 tp = TestProps() << 1546 out = {'syslpi':'N/A','pkgpc1 << 1547 for line in self.dmesgtext: << 1548 m = re.match(tp.tstat << 1549 if not m: << 1550 continue << 1551 for i in m.group('t') << 1552 if 'SYS%LPI' << 1553 out[' << 1554 elif 'pc10' i << 1555 out[' << 1556 break << 1557 return out << 1558 def extractErrorInfo(self): 919 def extractErrorInfo(self): 1559 lf = self.dmesgtext !! 920 elist = { 1560 if len(self.dmesgtext) < 1 an !! 921 'HWERROR' : '.*\[ *Hardware Error *\].*', 1561 lf = sysvals.openlog( !! 922 'FWBUG' : '.*\[ *Firmware Bug *\].*', >> 923 'BUG' : '.*BUG.*', >> 924 'ERROR' : '.*ERROR.*', >> 925 'WARNING' : '.*WARNING.*', >> 926 'IRQ' : '.*genirq: .*', >> 927 'TASKFAIL': '.*Freezing of tasks failed.*', >> 928 } >> 929 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 1562 i = 0 930 i = 0 1563 tp = TestProps() << 1564 list = [] 931 list = [] 1565 for line in lf: 932 for line in lf: 1566 i += 1 933 i += 1 1567 if tp.stampInfo(line, !! 934 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 1568 continue << 1569 m = re.match(r'[ \t]* << 1570 if not m: 935 if not m: 1571 continue 936 continue 1572 t = float(m.group('kt 937 t = float(m.group('ktime')) 1573 if t < self.start or 938 if t < self.start or t > self.end: 1574 continue 939 continue 1575 dir = 'suspend' if t 940 dir = 'suspend' if t < self.tSuspended else 'resume' 1576 msg = m.group('msg') 941 msg = m.group('msg') 1577 if re.match(r'capabil !! 942 for err in elist: 1578 continue !! 943 if re.match(elist[err], msg): 1579 for err in self.errli !! 944 list.append((err, dir, t, i, i)) 1580 if re.match(s << 1581 list. << 1582 self. 945 self.kerror = True 1583 break 946 break 1584 tp.msglist = [] !! 947 for e in list: 1585 for msg, type, dir, t, idx1, !! 948 type, dir, t, idx1, idx2 = e 1586 tp.msglist.append(msg !! 949 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t)) 1587 self.errorinfo[dir].a 950 self.errorinfo[dir].append((type, t, idx1, idx2)) 1588 if self.kerror: 951 if self.kerror: 1589 sysvals.dmesglog = Tr 952 sysvals.dmesglog = True 1590 if len(self.dmesgtext) < 1 an !! 953 lf.close() 1591 lf.close() !! 954 def setStart(self, time): 1592 return tp << 1593 def setStart(self, time, msg=''): << 1594 self.start = time 955 self.start = time 1595 if msg: !! 956 def setEnd(self, time): 1596 try: << 1597 self.hwstart << 1598 except: << 1599 self.hwstart << 1600 def setEnd(self, time, msg=''): << 1601 self.end = time 957 self.end = time 1602 if msg: << 1603 try: << 1604 self.hwend = << 1605 except: << 1606 self.hwend = << 1607 def isTraceEventOutsideDeviceCalls(se 958 def isTraceEventOutsideDeviceCalls(self, pid, time): 1608 for phase in self.sortedPhase !! 959 for phase in self.phases: 1609 list = self.dmesg[pha 960 list = self.dmesg[phase]['list'] 1610 for dev in list: 961 for dev in list: 1611 d = list[dev] 962 d = list[dev] 1612 if(d['pid'] = 963 if(d['pid'] == pid and time >= d['start'] and 1613 time 964 time < d['end']): 1614 retur 965 return False 1615 return True 966 return True >> 967 def phaseCollision(self, phase, isbegin, line): >> 968 key = 'end' >> 969 if isbegin: >> 970 key = 'start' >> 971 if self.dmesg[phase][key] >= 0: >> 972 sysvals.vprint('IGNORE: %s' % line.strip()) >> 973 return True >> 974 return False 1616 def sourcePhase(self, start): 975 def sourcePhase(self, start): 1617 for phase in self.sortedPhase !! 976 for phase in self.phases: 1618 if 'machine' in phase << 1619 continue << 1620 pend = self.dmesg[pha 977 pend = self.dmesg[phase]['end'] 1621 if start <= pend: 978 if start <= pend: 1622 return phase 979 return phase 1623 return 'resume_complete' if ' !! 980 return 'resume_complete' 1624 def sourceDevice(self, phaselist, sta 981 def sourceDevice(self, phaselist, start, end, pid, type): 1625 tgtdev = '' 982 tgtdev = '' 1626 for phase in phaselist: 983 for phase in phaselist: 1627 list = self.dmesg[pha 984 list = self.dmesg[phase]['list'] 1628 for devname in list: 985 for devname in list: 1629 dev = list[de 986 dev = list[devname] 1630 # pid must ma 987 # pid must match 1631 if dev['pid'] 988 if dev['pid'] != pid: 1632 conti 989 continue 1633 devS = dev['s 990 devS = dev['start'] 1634 devE = dev['e 991 devE = dev['end'] 1635 if type == 'd 992 if type == 'device': 1636 # dev 993 # device target event is entirely inside the source boundary 1637 if(st 994 if(start < devS or start >= devE or end <= devS or end > devE): 1638 995 continue 1639 elif type == 996 elif type == 'thread': 1640 # thr 997 # thread target event will expand the source boundary 1641 if st 998 if start < devS: 1642 999 dev['start'] = start 1643 if en 1000 if end > devE: 1644 1001 dev['end'] = end 1645 tgtdev = dev 1002 tgtdev = dev 1646 break 1003 break 1647 return tgtdev 1004 return tgtdev 1648 def addDeviceFunctionCall(self, displ 1005 def addDeviceFunctionCall(self, displayname, kprobename, proc, pid, start, end, cdata, rdata): 1649 # try to place the call in a 1006 # try to place the call in a device 1650 phases = self.sortedPhases() !! 1007 tgtdev = self.sourceDevice(self.phases, start, end, pid, 'device') 1651 tgtdev = self.sourceDevice(ph << 1652 # calls with device pids that 1008 # calls with device pids that occur outside device bounds are dropped 1653 # TODO: include these somehow 1009 # TODO: include these somehow 1654 if not tgtdev and pid in self 1010 if not tgtdev and pid in self.devpids: 1655 return False 1011 return False 1656 # try to place the call in a 1012 # try to place the call in a thread 1657 if not tgtdev: 1013 if not tgtdev: 1658 tgtdev = self.sourceD !! 1014 tgtdev = self.sourceDevice(self.phases, start, end, pid, 'thread') 1659 # create new thread blocks, e 1015 # create new thread blocks, expand as new calls are found 1660 if not tgtdev: 1016 if not tgtdev: 1661 if proc == '<...>': 1017 if proc == '<...>': 1662 threadname = 1018 threadname = 'kthread-%d' % (pid) 1663 else: 1019 else: 1664 threadname = 1020 threadname = '%s-%d' % (proc, pid) 1665 tgtphase = self.sourc 1021 tgtphase = self.sourcePhase(start) 1666 if not tgtphase: << 1667 return False << 1668 self.newAction(tgtpha 1022 self.newAction(tgtphase, threadname, pid, '', start, end, '', ' kth', '') 1669 return self.addDevice 1023 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata) 1670 # this should not happen 1024 # this should not happen 1671 if not tgtdev: 1025 if not tgtdev: 1672 sysvals.vprint('[%f - 1026 sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \ 1673 (start, end, 1027 (start, end, proc, pid, kprobename, cdata, rdata)) 1674 return False 1028 return False 1675 # place the call data inside 1029 # place the call data inside the src element of the tgtdev 1676 if('src' not in tgtdev): 1030 if('src' not in tgtdev): 1677 tgtdev['src'] = [] 1031 tgtdev['src'] = [] 1678 dtf = sysvals.dev_tracefuncs 1032 dtf = sysvals.dev_tracefuncs 1679 ubiquitous = False 1033 ubiquitous = False 1680 if kprobename in dtf and 'ub' 1034 if kprobename in dtf and 'ub' in dtf[kprobename]: 1681 ubiquitous = True 1035 ubiquitous = True 1682 mc = re.match(r'\(.*\) *(?P<a !! 1036 title = cdata+' '+rdata 1683 mr = re.match(r'\((?P<caller> !! 1037 mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)' 1684 if mc and mr: !! 1038 m = re.match(mstr, title) 1685 c = mr.group('caller' !! 1039 if m: 1686 a = mc.group('args'). !! 1040 c = m.group('caller') 1687 r = mr.group('ret') !! 1041 a = m.group('args').strip() >> 1042 r = m.group('ret') 1688 if len(r) > 6: 1043 if len(r) > 6: 1689 r = '' 1044 r = '' 1690 else: 1045 else: 1691 r = 'ret=%s ' 1046 r = 'ret=%s ' % r 1692 if ubiquitous and c i 1047 if ubiquitous and c in dtf and 'ub' in dtf[c]: 1693 return False 1048 return False 1694 else: << 1695 return False << 1696 color = sysvals.kprobeColor(k 1049 color = sysvals.kprobeColor(kprobename) 1697 e = DevFunction(displayname, 1050 e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color) 1698 tgtdev['src'].append(e) 1051 tgtdev['src'].append(e) 1699 return True 1052 return True 1700 def overflowDevices(self): 1053 def overflowDevices(self): 1701 # get a list of devices that 1054 # get a list of devices that extend beyond the end of this test run 1702 devlist = [] 1055 devlist = [] 1703 for phase in self.sortedPhase !! 1056 for phase in self.phases: 1704 list = self.dmesg[pha 1057 list = self.dmesg[phase]['list'] 1705 for devname in list: 1058 for devname in list: 1706 dev = list[de 1059 dev = list[devname] 1707 if dev['end'] 1060 if dev['end'] > self.end: 1708 devli 1061 devlist.append(dev) 1709 return devlist 1062 return devlist 1710 def mergeOverlapDevices(self, devlist 1063 def mergeOverlapDevices(self, devlist): 1711 # merge any devices that over 1064 # merge any devices that overlap devlist 1712 for dev in devlist: 1065 for dev in devlist: 1713 devname = dev['name'] 1066 devname = dev['name'] 1714 for phase in self.sor !! 1067 for phase in self.phases: 1715 list = self.d 1068 list = self.dmesg[phase]['list'] 1716 if devname no 1069 if devname not in list: 1717 conti 1070 continue 1718 tdev = list[d 1071 tdev = list[devname] 1719 o = min(dev[' 1072 o = min(dev['end'], tdev['end']) - max(dev['start'], tdev['start']) 1720 if o <= 0: 1073 if o <= 0: 1721 conti 1074 continue 1722 dev['end'] = 1075 dev['end'] = tdev['end'] 1723 if 'src' not 1076 if 'src' not in dev or 'src' not in tdev: 1724 conti 1077 continue 1725 dev['src'] += 1078 dev['src'] += tdev['src'] 1726 del list[devn 1079 del list[devname] 1727 def usurpTouchingThread(self, name, d 1080 def usurpTouchingThread(self, name, dev): 1728 # the caller test has priorit 1081 # the caller test has priority of this thread, give it to him 1729 for phase in self.sortedPhase !! 1082 for phase in self.phases: 1730 list = self.dmesg[pha 1083 list = self.dmesg[phase]['list'] 1731 if name in list: 1084 if name in list: 1732 tdev = list[n 1085 tdev = list[name] 1733 if tdev['star 1086 if tdev['start'] - dev['end'] < 0.1: 1734 dev[' 1087 dev['end'] = tdev['end'] 1735 if 's 1088 if 'src' not in dev: 1736 1089 dev['src'] = [] 1737 if 's 1090 if 'src' in tdev: 1738 1091 dev['src'] += tdev['src'] 1739 del l 1092 del list[name] 1740 break 1093 break 1741 def stitchTouchingThreads(self, testl 1094 def stitchTouchingThreads(self, testlist): 1742 # merge any threads between t 1095 # merge any threads between tests that touch 1743 for phase in self.sortedPhase !! 1096 for phase in self.phases: 1744 list = self.dmesg[pha 1097 list = self.dmesg[phase]['list'] 1745 for devname in list: 1098 for devname in list: 1746 dev = list[de 1099 dev = list[devname] 1747 if 'htmlclass 1100 if 'htmlclass' not in dev or 'kth' not in dev['htmlclass']: 1748 conti 1101 continue 1749 for data in t 1102 for data in testlist: 1750 data. 1103 data.usurpTouchingThread(devname, dev) 1751 def optimizeDevSrc(self): 1104 def optimizeDevSrc(self): 1752 # merge any src call loops to 1105 # merge any src call loops to reduce timeline size 1753 for phase in self.sortedPhase !! 1106 for phase in self.phases: 1754 list = self.dmesg[pha 1107 list = self.dmesg[phase]['list'] 1755 for dev in list: 1108 for dev in list: 1756 if 'src' not 1109 if 'src' not in list[dev]: 1757 conti 1110 continue 1758 src = list[de 1111 src = list[dev]['src'] 1759 p = 0 1112 p = 0 1760 for e in sort 1113 for e in sorted(src, key=lambda event: event.time): 1761 if no 1114 if not p or not e.repeat(p): 1762 1115 p = e 1763 1116 continue 1764 # e i 1117 # e is another iteration of p, move it into p 1765 p.end 1118 p.end = e.end 1766 p.len 1119 p.length = p.end - p.time 1767 p.cou 1120 p.count += 1 1768 src.r 1121 src.remove(e) 1769 def trimTimeVal(self, t, t0, dT, left 1122 def trimTimeVal(self, t, t0, dT, left): 1770 if left: 1123 if left: 1771 if(t > t0): 1124 if(t > t0): 1772 if(t - dT < t 1125 if(t - dT < t0): 1773 retur 1126 return t0 1774 return t - dT 1127 return t - dT 1775 else: 1128 else: 1776 return t 1129 return t 1777 else: 1130 else: 1778 if(t < t0 + dT): 1131 if(t < t0 + dT): 1779 if(t > t0): 1132 if(t > t0): 1780 retur 1133 return t0 + dT 1781 return t + dT 1134 return t + dT 1782 else: 1135 else: 1783 return t 1136 return t 1784 def trimTime(self, t0, dT, left): 1137 def trimTime(self, t0, dT, left): 1785 self.tSuspended = self.trimTi 1138 self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left) 1786 self.tResumed = self.trimTime 1139 self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left) 1787 self.start = self.trimTimeVal 1140 self.start = self.trimTimeVal(self.start, t0, dT, left) 1788 self.tKernSus = self.trimTime 1141 self.tKernSus = self.trimTimeVal(self.tKernSus, t0, dT, left) 1789 self.tKernRes = self.trimTime 1142 self.tKernRes = self.trimTimeVal(self.tKernRes, t0, dT, left) 1790 self.end = self.trimTimeVal(s 1143 self.end = self.trimTimeVal(self.end, t0, dT, left) 1791 for phase in self.sortedPhase !! 1144 for phase in self.phases: 1792 p = self.dmesg[phase] 1145 p = self.dmesg[phase] 1793 p['start'] = self.tri 1146 p['start'] = self.trimTimeVal(p['start'], t0, dT, left) 1794 p['end'] = self.trimT 1147 p['end'] = self.trimTimeVal(p['end'], t0, dT, left) 1795 list = p['list'] 1148 list = p['list'] 1796 for name in list: 1149 for name in list: 1797 d = list[name 1150 d = list[name] 1798 d['start'] = 1151 d['start'] = self.trimTimeVal(d['start'], t0, dT, left) 1799 d['end'] = se 1152 d['end'] = self.trimTimeVal(d['end'], t0, dT, left) 1800 d['length'] = << 1801 if('ftrace' i 1153 if('ftrace' in d): 1802 cg = 1154 cg = d['ftrace'] 1803 cg.st 1155 cg.start = self.trimTimeVal(cg.start, t0, dT, left) 1804 cg.en 1156 cg.end = self.trimTimeVal(cg.end, t0, dT, left) 1805 for l 1157 for line in cg.list: 1806 1158 line.time = self.trimTimeVal(line.time, t0, dT, left) 1807 if('src' in d 1159 if('src' in d): 1808 for e 1160 for e in d['src']: 1809 1161 e.time = self.trimTimeVal(e.time, t0, dT, left) 1810 << 1811 << 1812 if('cpuexec' << 1813 cpuex << 1814 for e << 1815 << 1816 << 1817 << 1818 << 1819 d['cp << 1820 for dir in ['suspend', 'resum 1162 for dir in ['suspend', 'resume']: 1821 list = [] 1163 list = [] 1822 for e in self.errorin 1164 for e in self.errorinfo[dir]: 1823 type, tm, idx 1165 type, tm, idx1, idx2 = e 1824 tm = self.tri 1166 tm = self.trimTimeVal(tm, t0, dT, left) 1825 list.append(( 1167 list.append((type, tm, idx1, idx2)) 1826 self.errorinfo[dir] = 1168 self.errorinfo[dir] = list 1827 def trimFreezeTime(self, tZero): !! 1169 def normalizeTime(self, tZero): 1828 # trim out any standby or fre 1170 # trim out any standby or freeze clock time 1829 lp = '' !! 1171 if(self.tSuspended != self.tResumed): 1830 for phase in self.sortedPhase !! 1172 if(self.tResumed > tZero): 1831 if 'resume_machine' i !! 1173 self.trimTime(self.tSuspended, \ 1832 tS, tR = self !! 1174 self.tResumed-self.tSuspended, True) 1833 tL = tR - tS !! 1175 else: 1834 if tL <= 0: !! 1176 self.trimTime(self.tSuspended, \ 1835 conti !! 1177 self.tResumed-self.tSuspended, False) 1836 left = True i << 1837 self.trimTime << 1838 if 'waking' i << 1839 tCnt << 1840 if se << 1841 << 1842 else: << 1843 << 1844 text << 1845 else: << 1846 text << 1847 self.tLow.app << 1848 lp = phase << 1849 def getMemTime(self): << 1850 if not self.hwstart or not se << 1851 return << 1852 stime = (self.tSuspended - se << 1853 rtime = (self.end - self.tRes << 1854 hws = self.hwstart + timedelt << 1855 hwr = self.hwend - timedelta( << 1856 self.tLow.append('%.0f'%((hwr << 1857 def getTimeValues(self): 1178 def getTimeValues(self): 1858 s = (self.tSuspended - self.t !! 1179 sktime = (self.dmesg['suspend_machine']['end'] - \ 1859 r = (self.tKernRes - self.tRe !! 1180 self.tKernSus) * 1000 1860 return (max(s, 0), max(r, 0)) !! 1181 rktime = (self.dmesg['resume_complete']['end'] - \ 1861 def setPhase(self, phase, ktime, isbe !! 1182 self.dmesg['resume_machine']['start']) * 1000 >> 1183 return (sktime, rktime) >> 1184 def setPhase(self, phase, ktime, isbegin): 1862 if(isbegin): 1185 if(isbegin): 1863 # phase start over cu << 1864 if self.currphase: << 1865 if 'resume_ma << 1866 sysva << 1867 self.dmesg[se << 1868 phases = self.dmesg.k << 1869 color = self.phasedef << 1870 count = len(phases) i << 1871 # create unique name << 1872 while phase in phases << 1873 phase += '*' << 1874 self.dmesg[phase] = { << 1875 'row': 0, 'co << 1876 self.dmesg[phase]['st 1186 self.dmesg[phase]['start'] = ktime 1877 self.currphase = phas << 1878 else: 1187 else: 1879 # phase end without a << 1880 if phase not in self. << 1881 if self.currp << 1882 sysva << 1883 else: << 1884 sysva << 1885 retur << 1886 phase = self.currphas << 1887 self.dmesg[phase]['en 1188 self.dmesg[phase]['end'] = ktime 1888 self.currphase = '' !! 1189 def dmesgSortVal(self, phase): 1889 return phase !! 1190 return self.dmesg[phase]['order'] >> 1191 def sortedPhases(self): >> 1192 return sorted(self.dmesg, key=self.dmesgSortVal) 1890 def sortedDevices(self, phase): 1193 def sortedDevices(self, phase): 1891 list = self.dmesg[phase]['lis 1194 list = self.dmesg[phase]['list'] 1892 return sorted(list, key=lambd !! 1195 slist = [] >> 1196 tmp = dict() >> 1197 for devname in list: >> 1198 dev = list[devname] >> 1199 if dev['length'] == 0: >> 1200 continue >> 1201 tmp[dev['start']] = devname >> 1202 for t in sorted(tmp): >> 1203 slist.append(tmp[t]) >> 1204 return slist 1893 def fixupInitcalls(self, phase): 1205 def fixupInitcalls(self, phase): 1894 # if any calls never returned 1206 # if any calls never returned, clip them at system resume end 1895 phaselist = self.dmesg[phase] 1207 phaselist = self.dmesg[phase]['list'] 1896 for devname in phaselist: 1208 for devname in phaselist: 1897 dev = phaselist[devna 1209 dev = phaselist[devname] 1898 if(dev['end'] < 0): 1210 if(dev['end'] < 0): 1899 for p in self !! 1211 for p in self.phases: 1900 if se 1212 if self.dmesg[p]['end'] > dev['start']: 1901 1213 dev['end'] = self.dmesg[p]['end'] 1902 1214 break 1903 sysvals.vprin 1215 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase)) 1904 def deviceFilter(self, devicefilter): 1216 def deviceFilter(self, devicefilter): 1905 for phase in self.sortedPhase !! 1217 for phase in self.phases: 1906 list = self.dmesg[pha 1218 list = self.dmesg[phase]['list'] 1907 rmlist = [] 1219 rmlist = [] 1908 for name in list: 1220 for name in list: 1909 keep = False 1221 keep = False 1910 for filter in 1222 for filter in devicefilter: 1911 if fi 1223 if filter in name or \ 1912 1224 ('drv' in list[name] and filter in list[name]['drv']): 1913 1225 keep = True 1914 if not keep: 1226 if not keep: 1915 rmlis 1227 rmlist.append(name) 1916 for name in rmlist: 1228 for name in rmlist: 1917 del list[name 1229 del list[name] 1918 def fixupInitcallsThatDidntReturn(sel 1230 def fixupInitcallsThatDidntReturn(self): 1919 # if any calls never returned 1231 # if any calls never returned, clip them at system resume end 1920 for phase in self.sortedPhase !! 1232 for phase in self.phases: 1921 self.fixupInitcalls(p 1233 self.fixupInitcalls(phase) 1922 def phaseOverlap(self, phases): 1234 def phaseOverlap(self, phases): 1923 rmgroups = [] 1235 rmgroups = [] 1924 newgroup = [] 1236 newgroup = [] 1925 for group in self.devicegroup 1237 for group in self.devicegroups: 1926 for phase in phases: 1238 for phase in phases: 1927 if phase not 1239 if phase not in group: 1928 conti 1240 continue 1929 for p in grou 1241 for p in group: 1930 if p 1242 if p not in newgroup: 1931 1243 newgroup.append(p) 1932 if group not 1244 if group not in rmgroups: 1933 rmgro 1245 rmgroups.append(group) 1934 for group in rmgroups: 1246 for group in rmgroups: 1935 self.devicegroups.rem 1247 self.devicegroups.remove(group) 1936 self.devicegroups.append(newg 1248 self.devicegroups.append(newgroup) 1937 def newActionGlobal(self, name, start 1249 def newActionGlobal(self, name, start, end, pid=-1, color=''): 1938 # which phase is this device 1250 # which phase is this device callback or action in 1939 phases = self.sortedPhases() << 1940 targetphase = 'none' 1251 targetphase = 'none' 1941 htmlclass = '' 1252 htmlclass = '' 1942 overlap = 0.0 1253 overlap = 0.0 1943 myphases = [] !! 1254 phases = [] 1944 for phase in phases: !! 1255 for phase in self.phases: 1945 pstart = self.dmesg[p 1256 pstart = self.dmesg[phase]['start'] 1946 pend = self.dmesg[pha 1257 pend = self.dmesg[phase]['end'] 1947 # see if the action o 1258 # see if the action overlaps this phase 1948 o = max(0, min(end, p 1259 o = max(0, min(end, pend) - max(start, pstart)) 1949 if o > 0: 1260 if o > 0: 1950 myphases.appe !! 1261 phases.append(phase) 1951 # set the target phas 1262 # set the target phase to the one that overlaps most 1952 if o > overlap: 1263 if o > overlap: 1953 if overlap > 1264 if overlap > 0 and phase == 'post_resume': 1954 conti 1265 continue 1955 targetphase = 1266 targetphase = phase 1956 overlap = o 1267 overlap = o 1957 # if no target phase was foun 1268 # if no target phase was found, pin it to the edge 1958 if targetphase == 'none': 1269 if targetphase == 'none': 1959 p0start = self.dmesg[ !! 1270 p0start = self.dmesg[self.phases[0]]['start'] 1960 if start <= p0start: 1271 if start <= p0start: 1961 targetphase = !! 1272 targetphase = self.phases[0] 1962 else: 1273 else: 1963 targetphase = !! 1274 targetphase = self.phases[-1] 1964 if pid == -2: 1275 if pid == -2: 1965 htmlclass = ' bg' 1276 htmlclass = ' bg' 1966 elif pid == -3: 1277 elif pid == -3: 1967 htmlclass = ' ps' 1278 htmlclass = ' ps' 1968 if len(myphases) > 1: !! 1279 if len(phases) > 1: 1969 htmlclass = ' bg' 1280 htmlclass = ' bg' 1970 self.phaseOverlap(myp !! 1281 self.phaseOverlap(phases) 1971 if targetphase in phases: !! 1282 if targetphase in self.phases: 1972 newname = self.newAct 1283 newname = self.newAction(targetphase, name, pid, '', start, end, '', htmlclass, color) 1973 return (targetphase, 1284 return (targetphase, newname) 1974 return False 1285 return False 1975 def newAction(self, phase, name, pid, 1286 def newAction(self, phase, name, pid, parent, start, end, drv, htmlclass='', color=''): 1976 # new device callback for a s 1287 # new device callback for a specific phase 1977 self.html_device_id += 1 1288 self.html_device_id += 1 1978 devid = '%s%d' % (self.idstr, 1289 devid = '%s%d' % (self.idstr, self.html_device_id) 1979 list = self.dmesg[phase]['lis 1290 list = self.dmesg[phase]['list'] 1980 length = -1.0 1291 length = -1.0 1981 if(start >= 0 and end >= 0): 1292 if(start >= 0 and end >= 0): 1982 length = end - start 1293 length = end - start 1983 if pid == -2 or name not in s !! 1294 if pid == -2: 1984 i = 2 1295 i = 2 1985 origname = name 1296 origname = name 1986 while(name in list): 1297 while(name in list): 1987 name = '%s[%d 1298 name = '%s[%d]' % (origname, i) 1988 i += 1 1299 i += 1 1989 list[name] = {'name': name, ' 1300 list[name] = {'name': name, 'start': start, 'end': end, 'pid': pid, 1990 'par': parent, 'lengt 1301 'par': parent, 'length': length, 'row': 0, 'id': devid, 'drv': drv } 1991 if htmlclass: 1302 if htmlclass: 1992 list[name]['htmlclass 1303 list[name]['htmlclass'] = htmlclass 1993 if color: 1304 if color: 1994 list[name]['color'] = 1305 list[name]['color'] = color 1995 return name 1306 return name 1996 def findDevice(self, phase, name): << 1997 list = self.dmesg[phase]['lis << 1998 mydev = '' << 1999 for devname in sorted(list): << 2000 if name == devname or << 2001 mydev = devna << 2002 if mydev: << 2003 return list[mydev] << 2004 return False << 2005 def deviceChildren(self, devname, pha 1307 def deviceChildren(self, devname, phase): 2006 devlist = [] 1308 devlist = [] 2007 list = self.dmesg[phase]['lis 1309 list = self.dmesg[phase]['list'] 2008 for child in list: 1310 for child in list: 2009 if(list[child]['par'] 1311 if(list[child]['par'] == devname): 2010 devlist.appen 1312 devlist.append(child) 2011 return devlist 1313 return devlist 2012 def maxDeviceNameSize(self, phase): << 2013 size = 0 << 2014 for name in self.dmesg[phase] << 2015 if len(name) > size: << 2016 size = len(na << 2017 return size << 2018 def printDetails(self): 1314 def printDetails(self): 2019 sysvals.vprint('Timeline Deta 1315 sysvals.vprint('Timeline Details:') 2020 sysvals.vprint(' tes 1316 sysvals.vprint(' test start: %f' % self.start) 2021 sysvals.vprint('kernel suspen 1317 sysvals.vprint('kernel suspend start: %f' % self.tKernSus) 2022 tS = tR = False !! 1318 for phase in self.phases: 2023 for phase in self.sortedPhase !! 1319 dc = len(self.dmesg[phase]['list']) 2024 devlist = self.dmesg[ !! 1320 sysvals.vprint(' %16s: %f - %f (%d devices)' % (phase, \ 2025 dc, ps, pe = len(devl !! 1321 self.dmesg[phase]['start'], self.dmesg[phase]['end'], dc)) 2026 if not tS and ps >= s << 2027 sysvals.vprin << 2028 tS = True << 2029 if not tR and ps >= s << 2030 sysvals.vprin << 2031 tR = True << 2032 sysvals.vprint('%20s: << 2033 if sysvals.devdump: << 2034 sysvals.vprin << 2035 maxname = '%d << 2036 fmt = '%3d) % << 2037 c = 1 << 2038 for name in s << 2039 s = d << 2040 e = d << 2041 sysva << 2042 c += << 2043 sysvals.vprin << 2044 sysvals.vprint(' kernel res 1322 sysvals.vprint(' kernel resume end: %f' % self.tKernRes) 2045 sysvals.vprint(' t 1323 sysvals.vprint(' test end: %f' % self.end) 2046 def deviceChildrenAllPhases(self, dev 1324 def deviceChildrenAllPhases(self, devname): 2047 devlist = [] 1325 devlist = [] 2048 for phase in self.sortedPhase !! 1326 for phase in self.phases: 2049 list = self.deviceChi 1327 list = self.deviceChildren(devname, phase) 2050 for dev in sorted(lis !! 1328 for dev in list: 2051 if dev not in 1329 if dev not in devlist: 2052 devli 1330 devlist.append(dev) 2053 return devlist 1331 return devlist 2054 def masterTopology(self, name, list, 1332 def masterTopology(self, name, list, depth): 2055 node = DeviceNode(name, depth 1333 node = DeviceNode(name, depth) 2056 for cname in list: 1334 for cname in list: 2057 # avoid recursions 1335 # avoid recursions 2058 if name == cname: 1336 if name == cname: 2059 continue 1337 continue 2060 clist = self.deviceCh 1338 clist = self.deviceChildrenAllPhases(cname) 2061 cnode = self.masterTo 1339 cnode = self.masterTopology(cname, clist, depth+1) 2062 node.children.append( 1340 node.children.append(cnode) 2063 return node 1341 return node 2064 def printTopology(self, node): 1342 def printTopology(self, node): 2065 html = '' 1343 html = '' 2066 if node.name: 1344 if node.name: 2067 info = '' 1345 info = '' 2068 drv = '' 1346 drv = '' 2069 for phase in self.sor !! 1347 for phase in self.phases: 2070 list = self.d 1348 list = self.dmesg[phase]['list'] 2071 if node.name 1349 if node.name in list: 2072 s = l 1350 s = list[node.name]['start'] 2073 e = l 1351 e = list[node.name]['end'] 2074 if li 1352 if list[node.name]['drv']: 2075 1353 drv = ' {'+list[node.name]['drv']+'}' 2076 info 1354 info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000)) 2077 html += '<li><b>'+nod 1355 html += '<li><b>'+node.name+drv+'</b>' 2078 if info: 1356 if info: 2079 html += '<ul> 1357 html += '<ul>'+info+'</ul>' 2080 html += '</li>' 1358 html += '</li>' 2081 if len(node.children) > 0: 1359 if len(node.children) > 0: 2082 html += '<ul>' 1360 html += '<ul>' 2083 for cnode in node.chi 1361 for cnode in node.children: 2084 html += self. 1362 html += self.printTopology(cnode) 2085 html += '</ul>' 1363 html += '</ul>' 2086 return html 1364 return html 2087 def rootDeviceList(self): 1365 def rootDeviceList(self): 2088 # list of devices graphed 1366 # list of devices graphed 2089 real = [] 1367 real = [] 2090 for phase in self.sortedPhase !! 1368 for phase in self.dmesg: 2091 list = self.dmesg[pha 1369 list = self.dmesg[phase]['list'] 2092 for dev in sorted(lis !! 1370 for dev in list: 2093 if list[dev][ 1371 if list[dev]['pid'] >= 0 and dev not in real: 2094 real. 1372 real.append(dev) 2095 # list of top-most root devic 1373 # list of top-most root devices 2096 rootlist = [] 1374 rootlist = [] 2097 for phase in self.sortedPhase !! 1375 for phase in self.dmesg: 2098 list = self.dmesg[pha 1376 list = self.dmesg[phase]['list'] 2099 for dev in sorted(lis !! 1377 for dev in list: 2100 pdev = list[d 1378 pdev = list[dev]['par'] 2101 pid = list[de 1379 pid = list[dev]['pid'] 2102 if(pid < 0 or !! 1380 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): 2103 conti 1381 continue 2104 if pdev and p 1382 if pdev and pdev not in real and pdev not in rootlist: 2105 rootl 1383 rootlist.append(pdev) 2106 return rootlist 1384 return rootlist 2107 def deviceTopology(self): 1385 def deviceTopology(self): 2108 rootlist = self.rootDeviceLis 1386 rootlist = self.rootDeviceList() 2109 master = self.masterTopology( 1387 master = self.masterTopology('', rootlist, 0) 2110 return self.printTopology(mas 1388 return self.printTopology(master) 2111 def selectTimelineDevices(self, widfm 1389 def selectTimelineDevices(self, widfmt, tTotal, mindevlen): 2112 # only select devices that wi 1390 # only select devices that will actually show up in html 2113 self.tdevlist = dict() 1391 self.tdevlist = dict() 2114 for phase in self.dmesg: 1392 for phase in self.dmesg: 2115 devlist = [] 1393 devlist = [] 2116 list = self.dmesg[pha 1394 list = self.dmesg[phase]['list'] 2117 for dev in list: 1395 for dev in list: 2118 length = (lis 1396 length = (list[dev]['end'] - list[dev]['start']) * 1000 2119 width = widfm 1397 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal) 2120 if length >= !! 1398 if width != '0.000000' and length >= mindevlen: 2121 devli 1399 devlist.append(dev) 2122 self.tdevlist[phase] 1400 self.tdevlist[phase] = devlist 2123 def addHorizontalDivider(self, devnam 1401 def addHorizontalDivider(self, devname, devend): 2124 phase = 'suspend_prepare' 1402 phase = 'suspend_prepare' 2125 self.newAction(phase, devname 1403 self.newAction(phase, devname, -2, '', \ 2126 self.start, devend, ' 1404 self.start, devend, '', ' sec', '') 2127 if phase not in self.tdevlist 1405 if phase not in self.tdevlist: 2128 self.tdevlist[phase] 1406 self.tdevlist[phase] = [] 2129 self.tdevlist[phase].append(d 1407 self.tdevlist[phase].append(devname) 2130 d = DevItem(0, phase, self.dm 1408 d = DevItem(0, phase, self.dmesg[phase]['list'][devname]) 2131 return d 1409 return d 2132 def addProcessUsageEvent(self, name, 1410 def addProcessUsageEvent(self, name, times): 2133 # get the start and end times 1411 # get the start and end times for this process 2134 cpuexec = dict() !! 1412 maxC = 0 2135 tlast = start = end = -1 !! 1413 tlast = 0 >> 1414 start = -1 >> 1415 end = -1 2136 for t in sorted(times): 1416 for t in sorted(times): 2137 if tlast < 0: !! 1417 if tlast == 0: 2138 tlast = t 1418 tlast = t 2139 continue 1419 continue 2140 if name in self.pstl[ !! 1420 if name in self.pstl[t]: 2141 if start < 0: !! 1421 if start == -1 or tlast < start: 2142 start 1422 start = tlast 2143 end, key = t, !! 1423 if end == -1 or t > end: 2144 maxj = (t - t !! 1424 end = t 2145 cpuexec[key] << 2146 tlast = t 1425 tlast = t 2147 if start < 0 or end < 0: !! 1426 if start == -1 or end == -1: 2148 return !! 1427 return 0 2149 # add a new action for this p 1428 # add a new action for this process and get the object 2150 out = self.newActionGlobal(na 1429 out = self.newActionGlobal(name, start, end, -3) 2151 if out: !! 1430 if not out: 2152 phase, devname = out !! 1431 return 0 2153 dev = self.dmesg[phas !! 1432 phase, devname = out 2154 dev['cpuexec'] = cpue !! 1433 dev = self.dmesg[phase]['list'][devname] >> 1434 # get the cpu exec data >> 1435 tlast = 0 >> 1436 clast = 0 >> 1437 cpuexec = dict() >> 1438 for t in sorted(times): >> 1439 if tlast == 0 or t <= start or t > end: >> 1440 tlast = t >> 1441 continue >> 1442 list = self.pstl[t] >> 1443 c = 0 >> 1444 if name in list: >> 1445 c = list[name] >> 1446 if c > maxC: >> 1447 maxC = c >> 1448 if c != clast: >> 1449 key = (tlast, t) >> 1450 cpuexec[key] = c >> 1451 tlast = t >> 1452 clast = c >> 1453 dev['cpuexec'] = cpuexec >> 1454 return maxC 2155 def createProcessUsageEvents(self): 1455 def createProcessUsageEvents(self): 2156 # get an array of process nam !! 1456 # get an array of process names 2157 proclist = {'sus': dict(), 'r !! 1457 proclist = [] 2158 tdata = {'sus': [], 'res': [] !! 1458 for t in self.pstl: >> 1459 pslist = self.pstl[t] >> 1460 for ps in pslist: >> 1461 if ps not in proclist: >> 1462 proclist.append(ps) >> 1463 # get a list of data points for suspend and resume >> 1464 tsus = [] >> 1465 tres = [] 2159 for t in sorted(self.pstl): 1466 for t in sorted(self.pstl): 2160 dir = 'sus' if t < se !! 1467 if t < self.tSuspended: 2161 for ps in sorted(self !! 1468 tsus.append(t) 2162 if ps not in !! 1469 else: 2163 procl !! 1470 tres.append(t) 2164 tdata[dir].append(t) << 2165 # process the events for susp 1471 # process the events for suspend and resume 2166 if len(proclist['sus']) > 0 o !! 1472 if len(proclist) > 0: 2167 sysvals.vprint('Proce 1473 sysvals.vprint('Process Execution:') 2168 for dir in ['sus', 'res']: !! 1474 for ps in proclist: 2169 for ps in sorted(proc !! 1475 c = self.addProcessUsageEvent(ps, tsus) 2170 self.addProce !! 1476 if c > 0: 2171 def handleEndMarker(self, time, msg=' !! 1477 sysvals.vprint('%25s (sus): %d' % (ps, c)) 2172 dm = self.dmesg !! 1478 c = self.addProcessUsageEvent(ps, tres) 2173 self.setEnd(time, msg) !! 1479 if c > 0: 2174 self.initDevicegroups() !! 1480 sysvals.vprint('%25s (res): %d' % (ps, c)) 2175 # give suspend_prepare an end << 2176 if 'suspend_prepare' in dm an << 2177 dm['suspend_prepare'] << 2178 # assume resume machine ends << 2179 if 'resume_machine' in dm and << 2180 np = self.nextPhase(' << 2181 if np: << 2182 dm['resume_ma << 2183 # if kernel resume end not fo << 2184 if self.tKernRes == 0.0: << 2185 self.tKernRes = time << 2186 # if kernel suspend start not << 2187 if self.tKernSus == 0.0: << 2188 self.tKernSus = time << 2189 # set resume complete to end << 2190 if 'resume_complete' in dm: << 2191 dm['resume_complete'] << 2192 def initcall_debug_call(self, line, q << 2193 m = re.match(r'.*(\[ *)(?P<t> << 2194 r'PM: *calling .* @ ( << 2195 if not m: << 2196 m = re.match(r'.*(\[ << 2197 r'calling .* << 2198 if not m: << 2199 m = re.match(r'.*(\[ << 2200 r'(?P<f>.*)\+ << 2201 if m: << 2202 return True if quick << 2203 return False if quick else (' << 2204 def initcall_debug_return(self, line, << 2205 m = re.match(r'.*(\[ *)(?P<t> << 2206 r'.* returned (?P<r>[ << 2207 if not m: << 2208 m = re.match(r'.*(\[ << 2209 r'.* returned << 2210 if not m: << 2211 m = re.match(r'.*(\[ << 2212 r'(?P<f>.*)\+ << 2213 if m: << 2214 return True if quick << 2215 return False if quick else (' << 2216 def debugPrint(self): 1481 def debugPrint(self): 2217 for p in self.sortedPhases(): !! 1482 for p in self.phases: 2218 list = self.dmesg[p][ 1483 list = self.dmesg[p]['list'] 2219 for devname in sorted !! 1484 for devname in list: 2220 dev = list[de 1485 dev = list[devname] 2221 if 'ftrace' i 1486 if 'ftrace' in dev: 2222 dev[' 1487 dev['ftrace'].debugPrint(' [%s]' % devname) 2223 1488 2224 # Class: DevFunction 1489 # Class: DevFunction 2225 # Description: 1490 # Description: 2226 # A container for kprobe function data 1491 # A container for kprobe function data we want in the dev timeline 2227 class DevFunction: 1492 class DevFunction: >> 1493 row = 0 >> 1494 count = 1 2228 def __init__(self, name, args, caller 1495 def __init__(self, name, args, caller, ret, start, end, u, proc, pid, color): 2229 self.row = 0 << 2230 self.count = 1 << 2231 self.name = name 1496 self.name = name 2232 self.args = args 1497 self.args = args 2233 self.caller = caller 1498 self.caller = caller 2234 self.ret = ret 1499 self.ret = ret 2235 self.time = start 1500 self.time = start 2236 self.length = end - start 1501 self.length = end - start 2237 self.end = end 1502 self.end = end 2238 self.ubiquitous = u 1503 self.ubiquitous = u 2239 self.proc = proc 1504 self.proc = proc 2240 self.pid = pid 1505 self.pid = pid 2241 self.color = color 1506 self.color = color 2242 def title(self): 1507 def title(self): 2243 cnt = '' 1508 cnt = '' 2244 if self.count > 1: 1509 if self.count > 1: 2245 cnt = '(x%d)' % self. 1510 cnt = '(x%d)' % self.count 2246 l = '%0.3fms' % (self.length 1511 l = '%0.3fms' % (self.length * 1000) 2247 if self.ubiquitous: 1512 if self.ubiquitous: 2248 title = '%s(%s)%s <- 1513 title = '%s(%s)%s <- %s, %s(%s)' % \ 2249 (self.name, s 1514 (self.name, self.args, cnt, self.caller, self.ret, l) 2250 else: 1515 else: 2251 title = '%s(%s) %s%s( 1516 title = '%s(%s) %s%s(%s)' % (self.name, self.args, self.ret, cnt, l) 2252 return title.replace('"', '') 1517 return title.replace('"', '') 2253 def text(self): 1518 def text(self): 2254 if self.count > 1: 1519 if self.count > 1: 2255 text = '%s(x%d)' % (s 1520 text = '%s(x%d)' % (self.name, self.count) 2256 else: 1521 else: 2257 text = self.name 1522 text = self.name 2258 return text 1523 return text 2259 def repeat(self, tgt): 1524 def repeat(self, tgt): 2260 # is the tgt call just a repe 1525 # is the tgt call just a repeat of this call (e.g. are we in a loop) 2261 dt = self.time - tgt.end 1526 dt = self.time - tgt.end 2262 # only combine calls if -all- 1527 # only combine calls if -all- attributes are identical 2263 if tgt.caller == self.caller 1528 if tgt.caller == self.caller and \ 2264 tgt.name == self.name 1529 tgt.name == self.name and tgt.args == self.args and \ 2265 tgt.proc == self.proc 1530 tgt.proc == self.proc and tgt.pid == self.pid and \ 2266 tgt.ret == self.ret a 1531 tgt.ret == self.ret and dt >= 0 and \ 2267 dt <= sysvals.callloo 1532 dt <= sysvals.callloopmaxgap and \ 2268 self.length < sysvals 1533 self.length < sysvals.callloopmaxlen: 2269 return True 1534 return True 2270 return False 1535 return False 2271 1536 2272 # Class: FTraceLine 1537 # Class: FTraceLine 2273 # Description: 1538 # Description: 2274 # A container for a single line of ftr 1539 # A container for a single line of ftrace data. There are six basic types: 2275 # callgraph line: 1540 # callgraph line: 2276 # call: " dpm_run_ca 1541 # call: " dpm_run_callback() {" 2277 # return: " }" 1542 # return: " }" 2278 # leaf: " dpm_run_cal 1543 # leaf: " dpm_run_callback();" 2279 # trace event: 1544 # trace event: 2280 # tracing_mark_write: 1545 # tracing_mark_write: SUSPEND START or RESUME COMPLETE 2281 # suspend_resume: phas 1546 # suspend_resume: phase or custom exec block data 2282 # device_pm_callback: 1547 # device_pm_callback: device callback info 2283 class FTraceLine: 1548 class FTraceLine: >> 1549 time = 0.0 >> 1550 length = 0.0 >> 1551 fcall = False >> 1552 freturn = False >> 1553 fevent = False >> 1554 fkprobe = False >> 1555 depth = 0 >> 1556 name = '' >> 1557 type = '' 2284 def __init__(self, t, m='', d=''): 1558 def __init__(self, t, m='', d=''): 2285 self.length = 0.0 << 2286 self.fcall = False << 2287 self.freturn = False << 2288 self.fevent = False << 2289 self.fkprobe = False << 2290 self.depth = 0 << 2291 self.name = '' << 2292 self.type = '' << 2293 self.time = float(t) 1559 self.time = float(t) 2294 if not m and not d: 1560 if not m and not d: 2295 return 1561 return 2296 # is this a trace event 1562 # is this a trace event 2297 if(d == 'traceevent' or re.ma !! 1563 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)): 2298 if(d == 'traceevent') 1564 if(d == 'traceevent'): 2299 # nop format 1565 # nop format trace event 2300 msg = m 1566 msg = m 2301 else: 1567 else: 2302 # function_gr 1568 # function_graph format trace event 2303 em = re.match !! 1569 em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m) 2304 msg = em.grou 1570 msg = em.group('msg') 2305 1571 2306 emm = re.match(r'^(?P !! 1572 emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg) 2307 if(emm): 1573 if(emm): 2308 self.name = e 1574 self.name = emm.group('msg') 2309 self.type = e 1575 self.type = emm.group('call') 2310 else: 1576 else: 2311 self.name = m 1577 self.name = msg 2312 km = re.match(r'^(?P< !! 1578 km = re.match('^(?P<n>.*)_cal$', self.type) 2313 if km: 1579 if km: 2314 self.fcall = 1580 self.fcall = True 2315 self.fkprobe 1581 self.fkprobe = True 2316 self.type = k 1582 self.type = km.group('n') 2317 return 1583 return 2318 km = re.match(r'^(?P< !! 1584 km = re.match('^(?P<n>.*)_ret$', self.type) 2319 if km: 1585 if km: 2320 self.freturn 1586 self.freturn = True 2321 self.fkprobe 1587 self.fkprobe = True 2322 self.type = k 1588 self.type = km.group('n') 2323 return 1589 return 2324 self.fevent = True 1590 self.fevent = True 2325 return 1591 return 2326 # convert the duration to sec 1592 # convert the duration to seconds 2327 if(d): 1593 if(d): 2328 self.length = float(d 1594 self.length = float(d)/1000000 2329 # the indentation determines 1595 # the indentation determines the depth 2330 match = re.match(r'^(?P<d> *) !! 1596 match = re.match('^(?P<d> *)(?P<o>.*)$', m) 2331 if(not match): 1597 if(not match): 2332 return 1598 return 2333 self.depth = self.getDepth(ma 1599 self.depth = self.getDepth(match.group('d')) 2334 m = match.group('o') 1600 m = match.group('o') 2335 # function return 1601 # function return 2336 if(m[0] == '}'): 1602 if(m[0] == '}'): 2337 self.freturn = True 1603 self.freturn = True 2338 if(len(m) > 1): 1604 if(len(m) > 1): 2339 # includes co 1605 # includes comment with function name 2340 match = re.ma !! 1606 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m) 2341 if(match): 1607 if(match): 2342 self. 1608 self.name = match.group('n').strip() 2343 # function call 1609 # function call 2344 else: 1610 else: 2345 self.fcall = True 1611 self.fcall = True 2346 # function call with 1612 # function call with children 2347 if(m[-1] == '{'): 1613 if(m[-1] == '{'): 2348 match = re.ma !! 1614 match = re.match('^(?P<n>.*) *\(.*', m) 2349 if(match): 1615 if(match): 2350 self. 1616 self.name = match.group('n').strip() 2351 # function call with 1617 # function call with no children (leaf) 2352 elif(m[-1] == ';'): 1618 elif(m[-1] == ';'): 2353 self.freturn 1619 self.freturn = True 2354 match = re.ma !! 1620 match = re.match('^(?P<n>.*) *\(.*', m) 2355 if(match): 1621 if(match): 2356 self. 1622 self.name = match.group('n').strip() 2357 # something else (pos 1623 # something else (possibly a trace marker) 2358 else: 1624 else: 2359 self.name = m 1625 self.name = m 2360 def isCall(self): 1626 def isCall(self): 2361 return self.fcall and not sel 1627 return self.fcall and not self.freturn 2362 def isReturn(self): 1628 def isReturn(self): 2363 return self.freturn and not s 1629 return self.freturn and not self.fcall 2364 def isLeaf(self): 1630 def isLeaf(self): 2365 return self.fcall and self.fr 1631 return self.fcall and self.freturn 2366 def getDepth(self, str): 1632 def getDepth(self, str): 2367 return len(str)/2 1633 return len(str)/2 2368 def debugPrint(self, info=''): 1634 def debugPrint(self, info=''): 2369 if self.isLeaf(): 1635 if self.isLeaf(): 2370 pprint(' -- %12.6f (d !! 1636 print(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \ 2371 self.depth, s 1637 self.depth, self.name, self.length*1000000, info)) 2372 elif self.freturn: 1638 elif self.freturn: 2373 pprint(' -- %12.6f (d !! 1639 print(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \ 2374 self.depth, s 1640 self.depth, self.name, self.length*1000000, info)) 2375 else: 1641 else: 2376 pprint(' -- %12.6f (d !! 1642 print(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \ 2377 self.depth, s 1643 self.depth, self.name, self.length*1000000, info)) 2378 def startMarker(self): 1644 def startMarker(self): 2379 # Is this the starting line o 1645 # Is this the starting line of a suspend? 2380 if not self.fevent: 1646 if not self.fevent: 2381 return False 1647 return False 2382 if sysvals.usetracemarkers: 1648 if sysvals.usetracemarkers: 2383 if(self.name.startswi !! 1649 if(self.name == 'SUSPEND START'): 2384 return True 1650 return True 2385 return False 1651 return False 2386 else: 1652 else: 2387 if(self.type == 'susp 1653 if(self.type == 'suspend_resume' and 2388 re.match(r'su !! 1654 re.match('suspend_enter\[.*\] begin', self.name)): 2389 return True 1655 return True 2390 return False 1656 return False 2391 def endMarker(self): 1657 def endMarker(self): 2392 # Is this the ending line of 1658 # Is this the ending line of a resume? 2393 if not self.fevent: 1659 if not self.fevent: 2394 return False 1660 return False 2395 if sysvals.usetracemarkers: 1661 if sysvals.usetracemarkers: 2396 if(self.name.startswi !! 1662 if(self.name == 'RESUME COMPLETE'): 2397 return True 1663 return True 2398 return False 1664 return False 2399 else: 1665 else: 2400 if(self.type == 'susp 1666 if(self.type == 'suspend_resume' and 2401 re.match(r'th !! 1667 re.match('thaw_processes\[.*\] end', self.name)): 2402 return True 1668 return True 2403 return False 1669 return False 2404 1670 2405 # Class: FTraceCallGraph 1671 # Class: FTraceCallGraph 2406 # Description: 1672 # Description: 2407 # A container for the ftrace callgraph 1673 # A container for the ftrace callgraph of a single recursive function. 2408 # This can be a dpm_run_callback, dpm_ 1674 # This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph 2409 # Each instance is tied to a single de 1675 # Each instance is tied to a single device in a single phase, and is 2410 # comprised of an ordered list of FTra 1676 # comprised of an ordered list of FTraceLine objects 2411 class FTraceCallGraph: 1677 class FTraceCallGraph: >> 1678 id = '' >> 1679 start = -1.0 >> 1680 end = -1.0 >> 1681 list = [] >> 1682 invalid = False >> 1683 depth = 0 >> 1684 pid = 0 >> 1685 name = '' >> 1686 partial = False 2412 vfname = 'missing_function_name' 1687 vfname = 'missing_function_name' >> 1688 ignore = False >> 1689 sv = 0 2413 def __init__(self, pid, sv): 1690 def __init__(self, pid, sv): 2414 self.id = '' << 2415 self.invalid = False << 2416 self.name = '' << 2417 self.partial = False << 2418 self.ignore = False << 2419 self.start = -1.0 1691 self.start = -1.0 2420 self.end = -1.0 1692 self.end = -1.0 2421 self.list = [] 1693 self.list = [] 2422 self.depth = 0 1694 self.depth = 0 2423 self.pid = pid 1695 self.pid = pid 2424 self.sv = sv 1696 self.sv = sv 2425 def addLine(self, line): 1697 def addLine(self, line): 2426 # if this is already invalid, 1698 # if this is already invalid, just leave 2427 if(self.invalid): 1699 if(self.invalid): 2428 if(line.depth == 0 an 1700 if(line.depth == 0 and line.freturn): 2429 return 1 1701 return 1 2430 return 0 1702 return 0 2431 # invalidate on bad depth 1703 # invalidate on bad depth 2432 if(self.depth < 0): 1704 if(self.depth < 0): 2433 self.invalidate(line) 1705 self.invalidate(line) 2434 return 0 1706 return 0 2435 # ignore data til we return t 1707 # ignore data til we return to the current depth 2436 if self.ignore: 1708 if self.ignore: 2437 if line.depth > self. 1709 if line.depth > self.depth: 2438 return 0 1710 return 0 2439 else: 1711 else: 2440 self.list[-1] 1712 self.list[-1].freturn = True 2441 self.list[-1] 1713 self.list[-1].length = line.time - self.list[-1].time 2442 self.ignore = 1714 self.ignore = False 2443 # if this is 1715 # if this is a return at self.depth, no more work is needed 2444 if line.depth 1716 if line.depth == self.depth and line.isReturn(): 2445 if li 1717 if line.depth == 0: 2446 1718 self.end = line.time 2447 1719 return 1 2448 retur 1720 return 0 2449 # compare current depth with 1721 # compare current depth with this lines pre-call depth 2450 prelinedep = line.depth 1722 prelinedep = line.depth 2451 if line.isReturn(): 1723 if line.isReturn(): 2452 prelinedep += 1 1724 prelinedep += 1 2453 last = 0 1725 last = 0 2454 lasttime = line.time 1726 lasttime = line.time 2455 if len(self.list) > 0: 1727 if len(self.list) > 0: 2456 last = self.list[-1] 1728 last = self.list[-1] 2457 lasttime = last.time 1729 lasttime = last.time 2458 if last.isLeaf(): 1730 if last.isLeaf(): 2459 lasttime += l 1731 lasttime += last.length 2460 # handle low misalignments by 1732 # handle low misalignments by inserting returns 2461 mismatch = prelinedep - self. 1733 mismatch = prelinedep - self.depth 2462 warning = self.sv.verbose and 1734 warning = self.sv.verbose and abs(mismatch) > 1 2463 info = [] 1735 info = [] 2464 if mismatch < 0: 1736 if mismatch < 0: 2465 idx = 0 1737 idx = 0 2466 # add return calls to 1738 # add return calls to get the depth down 2467 while prelinedep < se 1739 while prelinedep < self.depth: 2468 self.depth -= 1740 self.depth -= 1 2469 if idx == 0 a 1741 if idx == 0 and last and last.isCall(): 2470 # spe 1742 # special case, turn last call into a leaf 2471 last. 1743 last.depth = self.depth 2472 last. 1744 last.freturn = True 2473 last. 1745 last.length = line.time - last.time 2474 if wa 1746 if warning: 2475 1747 info.append(('[make leaf]', last)) 2476 else: 1748 else: 2477 vline 1749 vline = FTraceLine(lasttime) 2478 vline 1750 vline.depth = self.depth 2479 vline 1751 vline.name = self.vfname 2480 vline 1752 vline.freturn = True 2481 self. 1753 self.list.append(vline) 2482 if wa 1754 if warning: 2483 1755 if idx == 0: 2484 1756 info.append(('', last)) 2485 1757 info.append(('[add return]', vline)) 2486 idx += 1 1758 idx += 1 2487 if warning: 1759 if warning: 2488 info.append(( 1760 info.append(('', line)) 2489 # handle high misalignments b 1761 # handle high misalignments by inserting calls 2490 elif mismatch > 0: 1762 elif mismatch > 0: 2491 idx = 0 1763 idx = 0 2492 if warning: 1764 if warning: 2493 info.append(( 1765 info.append(('', last)) 2494 # add calls to get th 1766 # add calls to get the depth up 2495 while prelinedep > se 1767 while prelinedep > self.depth: 2496 if idx == 0 a 1768 if idx == 0 and line.isReturn(): 2497 # spe 1769 # special case, turn this return into a leaf 2498 line. 1770 line.fcall = True 2499 preli 1771 prelinedep -= 1 2500 if wa 1772 if warning: 2501 1773 info.append(('[make leaf]', line)) 2502 else: 1774 else: 2503 vline 1775 vline = FTraceLine(lasttime) 2504 vline 1776 vline.depth = self.depth 2505 vline 1777 vline.name = self.vfname 2506 vline 1778 vline.fcall = True 2507 self. 1779 self.list.append(vline) 2508 self. 1780 self.depth += 1 2509 if no 1781 if not last: 2510 1782 self.start = vline.time 2511 if wa 1783 if warning: 2512 1784 info.append(('[add call]', vline)) 2513 idx += 1 1785 idx += 1 2514 if warning and ('[mak 1786 if warning and ('[make leaf]', line) not in info: 2515 info.append(( 1787 info.append(('', line)) 2516 if warning: 1788 if warning: 2517 pprint('WARNING: ftra !! 1789 print 'WARNING: ftrace data missing, corrections made:' 2518 for i in info: 1790 for i in info: 2519 t, obj = i 1791 t, obj = i 2520 if obj: 1792 if obj: 2521 obj.d 1793 obj.debugPrint(t) 2522 # process the call and set th 1794 # process the call and set the new depth 2523 skipadd = False 1795 skipadd = False 2524 md = self.sv.max_graph_depth 1796 md = self.sv.max_graph_depth 2525 if line.isCall(): 1797 if line.isCall(): 2526 # ignore blacklisted/ 1798 # ignore blacklisted/overdepth funcs 2527 if (md and self.depth 1799 if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist): 2528 self.ignore = 1800 self.ignore = True 2529 else: 1801 else: 2530 self.depth += 1802 self.depth += 1 2531 elif line.isReturn(): 1803 elif line.isReturn(): 2532 self.depth -= 1 1804 self.depth -= 1 2533 # remove blacklisted/ 1805 # remove blacklisted/overdepth/empty funcs that slipped through 2534 if (last and last.isC 1806 if (last and last.isCall() and last.depth == line.depth) or \ 2535 (md and last 1807 (md and last and last.depth >= md) or \ 2536 (line.name in 1808 (line.name in self.sv.cgblacklist): 2537 while len(sel 1809 while len(self.list) > 0 and self.list[-1].depth > line.depth: 2538 self. 1810 self.list.pop(-1) 2539 if len(self.l 1811 if len(self.list) == 0: 2540 self. 1812 self.invalid = True 2541 retur 1813 return 1 2542 self.list[-1] 1814 self.list[-1].freturn = True 2543 self.list[-1] 1815 self.list[-1].length = line.time - self.list[-1].time 2544 self.list[-1] 1816 self.list[-1].name = line.name 2545 skipadd = Tru 1817 skipadd = True 2546 if len(self.list) < 1: 1818 if len(self.list) < 1: 2547 self.start = line.tim 1819 self.start = line.time 2548 # check for a mismatch that r 1820 # check for a mismatch that returned all the way to callgraph end 2549 res = 1 1821 res = 1 2550 if mismatch < 0 and self.list 1822 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn: 2551 line = self.list[-1] 1823 line = self.list[-1] 2552 skipadd = True 1824 skipadd = True 2553 res = -1 1825 res = -1 2554 if not skipadd: 1826 if not skipadd: 2555 self.list.append(line 1827 self.list.append(line) 2556 if(line.depth == 0 and line.f 1828 if(line.depth == 0 and line.freturn): 2557 if(self.start < 0): 1829 if(self.start < 0): 2558 self.start = 1830 self.start = line.time 2559 self.end = line.time 1831 self.end = line.time 2560 if line.fcall: 1832 if line.fcall: 2561 self.end += l 1833 self.end += line.length 2562 if self.list[0].name 1834 if self.list[0].name == self.vfname: 2563 self.invalid 1835 self.invalid = True 2564 if res == -1: 1836 if res == -1: 2565 self.partial 1837 self.partial = True 2566 return res 1838 return res 2567 return 0 1839 return 0 2568 def invalidate(self, line): 1840 def invalidate(self, line): 2569 if(len(self.list) > 0): 1841 if(len(self.list) > 0): 2570 first = self.list[0] 1842 first = self.list[0] 2571 self.list = [] 1843 self.list = [] 2572 self.list.append(firs 1844 self.list.append(first) 2573 self.invalid = True 1845 self.invalid = True 2574 id = 'task %s' % (self.pid) 1846 id = 'task %s' % (self.pid) 2575 window = '(%f - %f)' % (self. 1847 window = '(%f - %f)' % (self.start, line.time) 2576 if(self.depth < 0): 1848 if(self.depth < 0): 2577 pprint('Data misalign !! 1849 print('Data misalignment for '+id+\ 2578 ' (buffer ove 1850 ' (buffer overflow), ignoring this callback') 2579 else: 1851 else: 2580 pprint('Too much data !! 1852 print('Too much data for '+id+\ 2581 ' '+window+', 1853 ' '+window+', ignoring this callback') 2582 def slice(self, dev): 1854 def slice(self, dev): 2583 minicg = FTraceCallGraph(dev[ 1855 minicg = FTraceCallGraph(dev['pid'], self.sv) 2584 minicg.name = self.name 1856 minicg.name = self.name 2585 mydepth = -1 1857 mydepth = -1 2586 good = False 1858 good = False 2587 for l in self.list: 1859 for l in self.list: 2588 if(l.time < dev['star 1860 if(l.time < dev['start'] or l.time > dev['end']): 2589 continue 1861 continue 2590 if mydepth < 0: 1862 if mydepth < 0: 2591 if l.name == 1863 if l.name == 'mutex_lock' and l.freturn: 2592 mydep 1864 mydepth = l.depth 2593 continue 1865 continue 2594 elif l.depth == mydep 1866 elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall: 2595 good = True 1867 good = True 2596 break 1868 break 2597 l.depth -= mydepth 1869 l.depth -= mydepth 2598 minicg.addLine(l) 1870 minicg.addLine(l) 2599 if not good or len(minicg.lis 1871 if not good or len(minicg.list) < 1: 2600 return 0 1872 return 0 2601 return minicg 1873 return minicg 2602 def repair(self, enddepth): 1874 def repair(self, enddepth): 2603 # bring the depth back to 0 w 1875 # bring the depth back to 0 with additional returns 2604 fixed = False 1876 fixed = False 2605 last = self.list[-1] 1877 last = self.list[-1] 2606 for i in reversed(range(endde 1878 for i in reversed(range(enddepth)): 2607 t = FTraceLine(last.t 1879 t = FTraceLine(last.time) 2608 t.depth = i 1880 t.depth = i 2609 t.freturn = True 1881 t.freturn = True 2610 fixed = self.addLine( 1882 fixed = self.addLine(t) 2611 if fixed != 0: 1883 if fixed != 0: 2612 self.end = la 1884 self.end = last.time 2613 return True 1885 return True 2614 return False 1886 return False 2615 def postProcess(self): 1887 def postProcess(self): 2616 if len(self.list) > 0: 1888 if len(self.list) > 0: 2617 self.name = self.list 1889 self.name = self.list[0].name 2618 stack = dict() 1890 stack = dict() 2619 cnt = 0 1891 cnt = 0 2620 last = 0 1892 last = 0 2621 for l in self.list: 1893 for l in self.list: 2622 # ftrace bug: reporte 1894 # ftrace bug: reported duration is not reliable 2623 # check each leaf and 1895 # check each leaf and clip it at max possible length 2624 if last and last.isLe 1896 if last and last.isLeaf(): 2625 if last.lengt 1897 if last.length > l.time - last.time: 2626 last. 1898 last.length = l.time - last.time 2627 if l.isCall(): 1899 if l.isCall(): 2628 stack[l.depth 1900 stack[l.depth] = l 2629 cnt += 1 1901 cnt += 1 2630 elif l.isReturn(): 1902 elif l.isReturn(): 2631 if(l.depth no 1903 if(l.depth not in stack): 2632 if se 1904 if self.sv.verbose: 2633 !! 1905 print 'Post Process Error: Depth missing' 2634 1906 l.debugPrint() 2635 retur 1907 return False 2636 # calculate c 1908 # calculate call length from call/return lines 2637 cl = stack[l. 1909 cl = stack[l.depth] 2638 cl.length = l 1910 cl.length = l.time - cl.time 2639 if cl.name == 1911 if cl.name == self.vfname: 2640 cl.na 1912 cl.name = l.name 2641 stack.pop(l.d 1913 stack.pop(l.depth) 2642 l.length = 0 1914 l.length = 0 2643 cnt -= 1 1915 cnt -= 1 2644 last = l 1916 last = l 2645 if(cnt == 0): 1917 if(cnt == 0): 2646 # trace caught the wh 1918 # trace caught the whole call tree 2647 return True 1919 return True 2648 elif(cnt < 0): 1920 elif(cnt < 0): 2649 if self.sv.verbose: 1921 if self.sv.verbose: 2650 pprint('Post !! 1922 print 'Post Process Error: Depth is less than 0' 2651 return False 1923 return False 2652 # trace ended before call tre 1924 # trace ended before call tree finished 2653 return self.repair(cnt) 1925 return self.repair(cnt) 2654 def deviceMatch(self, pid, data): 1926 def deviceMatch(self, pid, data): 2655 found = '' 1927 found = '' 2656 # add the callgraph data to t 1928 # add the callgraph data to the device hierarchy 2657 borderphase = { 1929 borderphase = { 2658 'dpm_prepare': 'suspe 1930 'dpm_prepare': 'suspend_prepare', 2659 'dpm_complete': 'resu 1931 'dpm_complete': 'resume_complete' 2660 } 1932 } 2661 if(self.name in borderphase): 1933 if(self.name in borderphase): 2662 p = borderphase[self. 1934 p = borderphase[self.name] 2663 list = data.dmesg[p][ 1935 list = data.dmesg[p]['list'] 2664 for devname in list: 1936 for devname in list: 2665 dev = list[de 1937 dev = list[devname] 2666 if(pid == dev 1938 if(pid == dev['pid'] and 2667 self. 1939 self.start <= dev['start'] and 2668 self. 1940 self.end >= dev['end']): 2669 cg = 1941 cg = self.slice(dev) 2670 if cg 1942 if cg: 2671 1943 dev['ftrace'] = cg 2672 found 1944 found = devname 2673 return found 1945 return found 2674 for p in data.sortedPhases(): !! 1946 for p in data.phases: 2675 if(data.dmesg[p]['sta 1947 if(data.dmesg[p]['start'] <= self.start and 2676 self.start <= 1948 self.start <= data.dmesg[p]['end']): 2677 list = data.d 1949 list = data.dmesg[p]['list'] 2678 for devname i !! 1950 for devname in list: 2679 dev = 1951 dev = list[devname] 2680 if(pi 1952 if(pid == dev['pid'] and 2681 1953 self.start <= dev['start'] and 2682 1954 self.end >= dev['end']): 2683 1955 dev['ftrace'] = self 2684 1956 found = devname 2685 1957 break 2686 break 1958 break 2687 return found 1959 return found 2688 def newActionFromFunction(self, data) 1960 def newActionFromFunction(self, data): 2689 name = self.name 1961 name = self.name 2690 if name in ['dpm_run_callback 1962 if name in ['dpm_run_callback', 'dpm_prepare', 'dpm_complete']: 2691 return 1963 return 2692 fs = self.start 1964 fs = self.start 2693 fe = self.end 1965 fe = self.end 2694 if fs < data.start or fe > da 1966 if fs < data.start or fe > data.end: 2695 return 1967 return 2696 phase = '' 1968 phase = '' 2697 for p in data.sortedPhases(): !! 1969 for p in data.phases: 2698 if(data.dmesg[p]['sta 1970 if(data.dmesg[p]['start'] <= self.start and 2699 self.start < 1971 self.start < data.dmesg[p]['end']): 2700 phase = p 1972 phase = p 2701 break 1973 break 2702 if not phase: 1974 if not phase: 2703 return 1975 return 2704 out = data.newActionGlobal(na 1976 out = data.newActionGlobal(name, fs, fe, -2) 2705 if out: 1977 if out: 2706 phase, myname = out 1978 phase, myname = out 2707 data.dmesg[phase]['li 1979 data.dmesg[phase]['list'][myname]['ftrace'] = self 2708 def debugPrint(self, info=''): 1980 def debugPrint(self, info=''): 2709 pprint('%s pid=%d [%f - %f] % !! 1981 print('%s pid=%d [%f - %f] %.3f us') % \ 2710 (self.name, self.pid, 1982 (self.name, self.pid, self.start, self.end, 2711 (self.end - self.star !! 1983 (self.end - self.start)*1000000) 2712 for l in self.list: 1984 for l in self.list: 2713 if l.isLeaf(): 1985 if l.isLeaf(): 2714 pprint('%f (% !! 1986 print('%f (%02d): %s(); (%.3f us)%s' % (l.time, \ 2715 l.dep 1987 l.depth, l.name, l.length*1000000, info)) 2716 elif l.freturn: 1988 elif l.freturn: 2717 pprint('%f (% !! 1989 print('%f (%02d): %s} (%.3f us)%s' % (l.time, \ 2718 l.dep 1990 l.depth, l.name, l.length*1000000, info)) 2719 else: 1991 else: 2720 pprint('%f (% !! 1992 print('%f (%02d): %s() { (%.3f us)%s' % (l.time, \ 2721 l.dep 1993 l.depth, l.name, l.length*1000000, info)) 2722 pprint(' ') !! 1994 print(' ') 2723 1995 2724 class DevItem: 1996 class DevItem: 2725 def __init__(self, test, phase, dev): 1997 def __init__(self, test, phase, dev): 2726 self.test = test 1998 self.test = test 2727 self.phase = phase 1999 self.phase = phase 2728 self.dev = dev 2000 self.dev = dev 2729 def isa(self, cls): 2001 def isa(self, cls): 2730 if 'htmlclass' in self.dev an 2002 if 'htmlclass' in self.dev and cls in self.dev['htmlclass']: 2731 return True 2003 return True 2732 return False 2004 return False 2733 2005 2734 # Class: Timeline 2006 # Class: Timeline 2735 # Description: 2007 # Description: 2736 # A container for a device timeline wh 2008 # A container for a device timeline which calculates 2737 # all the html properties to display i 2009 # all the html properties to display it correctly 2738 class Timeline: 2010 class Timeline: >> 2011 html = '' >> 2012 height = 0 # total timeline height >> 2013 scaleH = 20 # timescale (top) row height >> 2014 rowH = 30 # device row height >> 2015 bodyH = 0 # body height >> 2016 rows = 0 # total timeline rows >> 2017 rowlines = dict() >> 2018 rowheight = dict() 2739 html_tblock = '<div id="block{0}" cla 2019 html_tblock = '<div id="block{0}" class="tblock" style="left:{1}%;width:{2}%;"><div class="tback" style="height:{3}px"></div>\n' 2740 html_device = '<div id="{0}" title="{ 2020 html_device = '<div id="{0}" title="{1}" class="thread{7}" style="left:{2}%;top:{3}px;height:{4}px;width:{5}%;{8}">{6}</div>\n' 2741 html_phase = '<div class="phase" styl 2021 html_phase = '<div class="phase" style="left:{0}%;width:{1}%;top:{2}px;height:{3}px;background:{4}">{5}</div>\n' 2742 html_phaselet = '<div id="{0}" class= 2022 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n' 2743 html_legend = '<div id="p{3}" class=" 2023 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}"> {2}</div>\n' 2744 def __init__(self, rowheight, scalehe 2024 def __init__(self, rowheight, scaleheight): >> 2025 self.rowH = rowheight >> 2026 self.scaleH = scaleheight 2745 self.html = '' 2027 self.html = '' 2746 self.height = 0 # total time << 2747 self.scaleH = scaleheight # t << 2748 self.rowH = rowheight # d << 2749 self.bodyH = 0 # body heigh << 2750 self.rows = 0 # total time << 2751 self.rowlines = dict() << 2752 self.rowheight = dict() << 2753 def createHeader(self, sv, stamp): 2028 def createHeader(self, sv, stamp): 2754 if(not stamp['time']): 2029 if(not stamp['time']): 2755 return 2030 return 2756 self.html += '<div class="ver !! 2031 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 2757 % (sv.title, sv.versi 2032 % (sv.title, sv.version) 2758 if sv.logmsg and sv.testlog: 2033 if sv.logmsg and sv.testlog: 2759 self.html += '<button 2034 self.html += '<button id="showtest" class="logbtn btnfmt">log</button>' 2760 if sv.dmesglog: 2035 if sv.dmesglog: 2761 self.html += '<button 2036 self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>' 2762 if sv.ftracelog: 2037 if sv.ftracelog: 2763 self.html += '<button 2038 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>' 2764 headline_stamp = '<div class= 2039 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 2765 self.html += headline_stamp.f 2040 self.html += headline_stamp.format(stamp['host'], stamp['kernel'], 2766 stamp['mode'], stamp[ 2041 stamp['mode'], stamp['time']) 2767 if 'man' in stamp and 'plat' 2042 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \ 2768 stamp['man'] and stam 2043 stamp['man'] and stamp['plat'] and stamp['cpu']: 2769 headline_sysinfo = '< 2044 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n' 2770 self.html += headline 2045 self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu']) 2771 2046 2772 # Function: getDeviceRows 2047 # Function: getDeviceRows 2773 # Description: 2048 # Description: 2774 # determine how may rows the devic 2049 # determine how may rows the device funcs will take 2775 # Arguments: 2050 # Arguments: 2776 # rawlist: the list of devices 2051 # rawlist: the list of devices/actions for a single phase 2777 # Output: 2052 # Output: 2778 # The total number of rows nee 2053 # The total number of rows needed to display this phase of the timeline 2779 def getDeviceRows(self, rawlist): 2054 def getDeviceRows(self, rawlist): 2780 # clear all rows and set them 2055 # clear all rows and set them to undefined 2781 sortdict = dict() 2056 sortdict = dict() 2782 for item in rawlist: 2057 for item in rawlist: 2783 item.row = -1 2058 item.row = -1 2784 sortdict[item] = item 2059 sortdict[item] = item.length 2785 sortlist = sorted(sortdict, k 2060 sortlist = sorted(sortdict, key=sortdict.get, reverse=True) 2786 remaining = len(sortlist) 2061 remaining = len(sortlist) 2787 rowdata = dict() 2062 rowdata = dict() 2788 row = 1 2063 row = 1 2789 # try to pack each row with a 2064 # try to pack each row with as many ranges as possible 2790 while(remaining > 0): 2065 while(remaining > 0): 2791 if(row not in rowdata 2066 if(row not in rowdata): 2792 rowdata[row] 2067 rowdata[row] = [] 2793 for i in sortlist: 2068 for i in sortlist: 2794 if(i.row >= 0 2069 if(i.row >= 0): 2795 conti 2070 continue 2796 s = i.time 2071 s = i.time 2797 e = i.time + 2072 e = i.time + i.length 2798 valid = True 2073 valid = True 2799 for ritem in 2074 for ritem in rowdata[row]: 2800 rs = 2075 rs = ritem.time 2801 re = 2076 re = ritem.time + ritem.length 2802 if(no 2077 if(not (((s <= rs) and (e <= rs)) or 2803 2078 ((s >= re) and (e >= re)))): 2804 2079 valid = False 2805 2080 break 2806 if(valid): 2081 if(valid): 2807 rowda 2082 rowdata[row].append(i) 2808 i.row 2083 i.row = row 2809 remai 2084 remaining -= 1 2810 row += 1 2085 row += 1 2811 return row 2086 return row 2812 # Function: getPhaseRows 2087 # Function: getPhaseRows 2813 # Description: 2088 # Description: 2814 # Organize the timeline entrie 2089 # Organize the timeline entries into the smallest 2815 # number of rows possible, wit 2090 # number of rows possible, with no entry overlapping 2816 # Arguments: 2091 # Arguments: 2817 # devlist: the list of devices 2092 # devlist: the list of devices/actions in a group of contiguous phases 2818 # Output: 2093 # Output: 2819 # The total number of rows nee 2094 # The total number of rows needed to display this phase of the timeline 2820 def getPhaseRows(self, devlist, row=0 2095 def getPhaseRows(self, devlist, row=0, sortby='length'): 2821 # clear all rows and set them 2096 # clear all rows and set them to undefined 2822 remaining = len(devlist) 2097 remaining = len(devlist) 2823 rowdata = dict() 2098 rowdata = dict() 2824 sortdict = dict() 2099 sortdict = dict() 2825 myphases = [] 2100 myphases = [] 2826 # initialize all device rows 2101 # initialize all device rows to -1 and calculate devrows 2827 for item in devlist: 2102 for item in devlist: 2828 dev = item.dev 2103 dev = item.dev 2829 tp = (item.test, item 2104 tp = (item.test, item.phase) 2830 if tp not in myphases 2105 if tp not in myphases: 2831 myphases.appe 2106 myphases.append(tp) 2832 dev['row'] = -1 2107 dev['row'] = -1 2833 if sortby == 'start': 2108 if sortby == 'start': 2834 # sort by sta 2109 # sort by start 1st, then length 2nd 2835 sortdict[item 2110 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start'])) 2836 else: 2111 else: 2837 # sort by len 2112 # sort by length 1st, then name 2nd 2838 sortdict[item 2113 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name']) 2839 if 'src' in dev: 2114 if 'src' in dev: 2840 dev['devrows' 2115 dev['devrows'] = self.getDeviceRows(dev['src']) 2841 # sort the devlist by length 2116 # sort the devlist by length so that large items graph on top 2842 sortlist = sorted(sortdict, k 2117 sortlist = sorted(sortdict, key=sortdict.get, reverse=True) 2843 orderedlist = [] 2118 orderedlist = [] 2844 for item in sortlist: 2119 for item in sortlist: 2845 if item.dev['pid'] == 2120 if item.dev['pid'] == -2: 2846 orderedlist.a 2121 orderedlist.append(item) 2847 for item in sortlist: 2122 for item in sortlist: 2848 if item not in ordere 2123 if item not in orderedlist: 2849 orderedlist.a 2124 orderedlist.append(item) 2850 # try to pack each row with a 2125 # try to pack each row with as many devices as possible 2851 while(remaining > 0): 2126 while(remaining > 0): 2852 rowheight = 1 2127 rowheight = 1 2853 if(row not in rowdata 2128 if(row not in rowdata): 2854 rowdata[row] 2129 rowdata[row] = [] 2855 for item in orderedli 2130 for item in orderedlist: 2856 dev = item.de 2131 dev = item.dev 2857 if(dev['row'] 2132 if(dev['row'] < 0): 2858 s = d 2133 s = dev['start'] 2859 e = d 2134 e = dev['end'] 2860 valid 2135 valid = True 2861 for r 2136 for ritem in rowdata[row]: 2862 2137 rs = ritem.dev['start'] 2863 2138 re = ritem.dev['end'] 2864 2139 if(not (((s <= rs) and (e <= rs)) or 2865 2140 ((s >= re) and (e >= re)))): 2866 2141 valid = False 2867 2142 break 2868 if(va 2143 if(valid): 2869 2144 rowdata[row].append(item) 2870 2145 dev['row'] = row 2871 2146 remaining -= 1 2872 2147 if 'devrows' in dev and dev['devrows'] > rowheight: 2873 2148 rowheight = dev['devrows'] 2874 for t, p in myphases: 2149 for t, p in myphases: 2875 if t not in s 2150 if t not in self.rowlines or t not in self.rowheight: 2876 self. 2151 self.rowlines[t] = dict() 2877 self. 2152 self.rowheight[t] = dict() 2878 if p not in s 2153 if p not in self.rowlines[t] or p not in self.rowheight[t]: 2879 self. 2154 self.rowlines[t][p] = dict() 2880 self. 2155 self.rowheight[t][p] = dict() 2881 rh = self.row 2156 rh = self.rowH 2882 # section hea 2157 # section headers should use a different row height 2883 if len(rowdat 2158 if len(rowdata[row]) == 1 and \ 2884 'html 2159 'htmlclass' in rowdata[row][0].dev and \ 2885 'sec' 2160 'sec' in rowdata[row][0].dev['htmlclass']: 2886 rh = 2161 rh = 15 2887 self.rowlines 2162 self.rowlines[t][p][row] = rowheight 2888 self.rowheigh 2163 self.rowheight[t][p][row] = rowheight * rh 2889 row += 1 2164 row += 1 2890 if(row > self.rows): 2165 if(row > self.rows): 2891 self.rows = int(row) 2166 self.rows = int(row) 2892 return row 2167 return row 2893 def phaseRowHeight(self, test, phase, 2168 def phaseRowHeight(self, test, phase, row): 2894 return self.rowheight[test][p 2169 return self.rowheight[test][phase][row] 2895 def phaseRowTop(self, test, phase, ro 2170 def phaseRowTop(self, test, phase, row): 2896 top = 0 2171 top = 0 2897 for i in sorted(self.rowheigh 2172 for i in sorted(self.rowheight[test][phase]): 2898 if i >= row: 2173 if i >= row: 2899 break 2174 break 2900 top += self.rowheight 2175 top += self.rowheight[test][phase][i] 2901 return top 2176 return top 2902 def calcTotalRows(self): 2177 def calcTotalRows(self): 2903 # Calculate the heights and o 2178 # Calculate the heights and offsets for the header and rows 2904 maxrows = 0 2179 maxrows = 0 2905 standardphases = [] 2180 standardphases = [] 2906 for t in self.rowlines: 2181 for t in self.rowlines: 2907 for p in self.rowline 2182 for p in self.rowlines[t]: 2908 total = 0 2183 total = 0 2909 for i in sort 2184 for i in sorted(self.rowlines[t][p]): 2910 total 2185 total += self.rowlines[t][p][i] 2911 if total > ma 2186 if total > maxrows: 2912 maxro 2187 maxrows = total 2913 if total == l 2188 if total == len(self.rowlines[t][p]): 2914 stand 2189 standardphases.append((t, p)) 2915 self.height = self.scaleH + ( 2190 self.height = self.scaleH + (maxrows*self.rowH) 2916 self.bodyH = self.height - se 2191 self.bodyH = self.height - self.scaleH 2917 # if there is 1 line per row, 2192 # if there is 1 line per row, draw them the standard way 2918 for t, p in standardphases: 2193 for t, p in standardphases: 2919 for i in sorted(self. 2194 for i in sorted(self.rowheight[t][p]): 2920 self.rowheigh !! 2195 self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p]) 2921 def createZoomBox(self, mode='command 2196 def createZoomBox(self, mode='command', testcount=1): 2922 # Create bounding box, add bu 2197 # Create bounding box, add buttons 2923 html_zoombox = '<center><butt 2198 html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n' 2924 html_timeline = '<div id="dme 2199 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n' 2925 html_devlist1 = '<button id=" 2200 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail{0}</button>' 2926 html_devlist2 = '<button id=" 2201 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n' 2927 if mode != 'command': 2202 if mode != 'command': 2928 if testcount > 1: 2203 if testcount > 1: 2929 self.html += 2204 self.html += html_devlist2 2930 self.html += 2205 self.html += html_devlist1.format('1') 2931 else: 2206 else: 2932 self.html += 2207 self.html += html_devlist1.format('') 2933 self.html += html_zoombox 2208 self.html += html_zoombox 2934 self.html += html_timeline.fo 2209 self.html += html_timeline.format('dmesg', self.height) 2935 # Function: createTimeScale 2210 # Function: createTimeScale 2936 # Description: 2211 # Description: 2937 # Create the timescale for a t 2212 # Create the timescale for a timeline block 2938 # Arguments: 2213 # Arguments: 2939 # m0: start time (mode begin) 2214 # m0: start time (mode begin) 2940 # mMax: end time (mode end) 2215 # mMax: end time (mode end) 2941 # tTotal: total timeline time 2216 # tTotal: total timeline time 2942 # mode: suspend or resume 2217 # mode: suspend or resume 2943 # Output: 2218 # Output: 2944 # The html code needed to disp 2219 # The html code needed to display the time scale 2945 def createTimeScale(self, m0, mMax, t 2220 def createTimeScale(self, m0, mMax, tTotal, mode): 2946 timescale = '<div class="t" s 2221 timescale = '<div class="t" style="right:{0}%">{1}</div>\n' 2947 rline = '<div class="t" style 2222 rline = '<div class="t" style="left:0;border-left:1px solid black;border-right:0;">{0}</div>\n' 2948 output = '<div class="timesca 2223 output = '<div class="timescale">\n' 2949 # set scale for timeline 2224 # set scale for timeline 2950 mTotal = mMax - m0 2225 mTotal = mMax - m0 2951 tS = 0.1 2226 tS = 0.1 2952 if(tTotal <= 0): 2227 if(tTotal <= 0): 2953 return output+'</div> 2228 return output+'</div>\n' 2954 if(tTotal > 4): 2229 if(tTotal > 4): 2955 tS = 1 2230 tS = 1 2956 divTotal = int(mTotal/tS) + 1 2231 divTotal = int(mTotal/tS) + 1 2957 divEdge = (mTotal - tS*(divTo 2232 divEdge = (mTotal - tS*(divTotal-1))*100/mTotal 2958 for i in range(divTotal): 2233 for i in range(divTotal): 2959 htmlline = '' 2234 htmlline = '' 2960 if(mode == 'suspend') 2235 if(mode == 'suspend'): 2961 pos = '%0.3f' 2236 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal) - divEdge) 2962 val = '%0.fms 2237 val = '%0.fms' % (float(i-divTotal+1)*tS*1000) 2963 if(i == divTo 2238 if(i == divTotal - 1): 2964 val = 2239 val = mode 2965 htmlline = ti 2240 htmlline = timescale.format(pos, val) 2966 else: 2241 else: 2967 pos = '%0.3f' 2242 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal)) 2968 val = '%0.fms 2243 val = '%0.fms' % (float(i)*tS*1000) 2969 htmlline = ti 2244 htmlline = timescale.format(pos, val) 2970 if(i == 0): 2245 if(i == 0): 2971 htmll 2246 htmlline = rline.format(mode) 2972 output += htmlline 2247 output += htmlline 2973 self.html += output+'</div>\n 2248 self.html += output+'</div>\n' 2974 2249 2975 # Class: TestProps 2250 # Class: TestProps 2976 # Description: 2251 # Description: 2977 # A list of values describing the prop 2252 # A list of values describing the properties of these test runs 2978 class TestProps: 2253 class TestProps: 2979 stampfmt = r'# [a-z]*-(?P<m>[0-9]{2}) !! 2254 stamp = '' 2980 r'(?P<H>[0-9] !! 2255 sysinfo = '' 2981 r' (?P<host>. !! 2256 cmdline = '' 2982 wififmt = r'^# wifi *(?P<d>\S*) *( !! 2257 kparams = '' 2983 tstatfmt = r'^# turbostat (?P<t>\S* !! 2258 S0i3 = False 2984 testerrfmt = r'^# enter_sleep_error ( !! 2259 fwdata = [] 2985 sysinfofmt = r'^# sysinfo .*' !! 2260 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ 2986 cmdlinefmt = r'^# command \| (?P<cmd> !! 2261 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ 2987 kparamsfmt = r'^# kparams \| (?P<kp>. !! 2262 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' 2988 devpropfmt = r'# Device Properties: . !! 2263 sysinfofmt = '^# sysinfo .*' 2989 pinfofmt = r'# platform-(?P<val>[a- !! 2264 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2990 tracertypefmt = r'# tracer: (?P<t>.*) !! 2265 kparamsfmt = '^# kparams \| (?P<kp>.*)' 2991 firmwarefmt = r'# fwsuspend (?P<s>[0- << 2992 procexecfmt = r'ps - (?P<ps>.*)$' << 2993 procmultifmt = r'@(?P<n>[0-9]*)\|(?P< << 2994 ftrace_line_fmt_fg = \ 2266 ftrace_line_fmt_fg = \ 2995 r'^ *(?P<time>[0-9\.]*) *\| * !! 2267 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2996 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2268 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2997 r'[ +!#\*@$]*(?P<dur>[0-9\.]* !! 2269 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)' 2998 ftrace_line_fmt_nop = \ 2270 ftrace_line_fmt_nop = \ 2999 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2271 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\ 3000 r'(?P<flags>\S*) *(?P<time>[0 !! 2272 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\ 3001 r'(?P<msg>.*)' !! 2273 '(?P<msg>.*)' 3002 machinesuspend = r'machine_suspend\[. !! 2274 ftrace_line_fmt = ftrace_line_fmt_nop 3003 multiproclist = dict() !! 2275 cgformat = False 3004 multiproctime = 0.0 !! 2276 data = 0 3005 multiproccnt = 0 !! 2277 ktemp = dict() 3006 def __init__(self): 2278 def __init__(self): 3007 self.stamp = '' << 3008 self.sysinfo = '' << 3009 self.cmdline = '' << 3010 self.testerror = [] << 3011 self.turbostat = [] << 3012 self.wifi = [] << 3013 self.fwdata = [] << 3014 self.ftrace_line_fmt = self.f << 3015 self.cgformat = False << 3016 self.data = 0 << 3017 self.ktemp = dict() 2279 self.ktemp = dict() 3018 def setTracerType(self, tracer): 2280 def setTracerType(self, tracer): 3019 if(tracer == 'function_graph' 2281 if(tracer == 'function_graph'): 3020 self.cgformat = True 2282 self.cgformat = True 3021 self.ftrace_line_fmt 2283 self.ftrace_line_fmt = self.ftrace_line_fmt_fg 3022 elif(tracer == 'nop'): 2284 elif(tracer == 'nop'): 3023 self.ftrace_line_fmt 2285 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 3024 else: 2286 else: 3025 doError('Invalid trac 2287 doError('Invalid tracer format: [%s]' % tracer) 3026 def stampInfo(self, line, sv): << 3027 if re.match(self.stampfmt, li << 3028 self.stamp = line << 3029 return True << 3030 elif re.match(self.sysinfofmt << 3031 self.sysinfo = line << 3032 return True << 3033 elif re.match(self.tstatfmt, << 3034 self.turbostat.append << 3035 return True << 3036 elif re.match(self.wififmt, l << 3037 self.wifi.append(line << 3038 return True << 3039 elif re.match(self.testerrfmt << 3040 self.testerror.append << 3041 return True << 3042 elif re.match(self.firmwarefm << 3043 self.fwdata.append(li << 3044 return True << 3045 elif(re.match(self.devpropfmt << 3046 self.parseDevprops(li << 3047 return True << 3048 elif(re.match(self.pinfofmt, << 3049 self.parsePlatformInf << 3050 return True << 3051 m = re.match(self.cmdlinefmt, << 3052 if m: << 3053 self.cmdline = m.grou << 3054 return True << 3055 m = re.match(self.tracertypef << 3056 if(m): << 3057 self.setTracerType(m. << 3058 return True << 3059 return False << 3060 def parseStamp(self, data, sv): 2288 def parseStamp(self, data, sv): 3061 # global test data << 3062 m = re.match(self.stampfmt, s 2289 m = re.match(self.stampfmt, self.stamp) 3063 if not self.stamp or not m: << 3064 doError('data does no << 3065 data.stamp = {'time': '', 'ho 2290 data.stamp = {'time': '', 'host': '', 'mode': ''} 3066 dt = datetime(int(m.group('y' 2291 dt = datetime(int(m.group('y'))+2000, int(m.group('m')), 3067 int(m.group('d')), in 2292 int(m.group('d')), int(m.group('H')), int(m.group('M')), 3068 int(m.group('S'))) 2293 int(m.group('S'))) 3069 data.stamp['time'] = dt.strft 2294 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p') 3070 data.stamp['host'] = m.group( 2295 data.stamp['host'] = m.group('host') 3071 data.stamp['mode'] = m.group( 2296 data.stamp['mode'] = m.group('mode') 3072 data.stamp['kernel'] = m.grou 2297 data.stamp['kernel'] = m.group('kernel') 3073 if re.match(self.sysinfofmt, 2298 if re.match(self.sysinfofmt, self.sysinfo): 3074 for f in self.sysinfo 2299 for f in self.sysinfo.split('|'): 3075 if '#' in f: 2300 if '#' in f: 3076 conti 2301 continue 3077 tmp = f.strip 2302 tmp = f.strip().split(':', 1) 3078 key = tmp[0] 2303 key = tmp[0] 3079 val = tmp[1] 2304 val = tmp[1] 3080 data.stamp[ke 2305 data.stamp[key] = val 3081 sv.hostname = data.stamp['hos 2306 sv.hostname = data.stamp['host'] 3082 sv.suspendmode = data.stamp[' 2307 sv.suspendmode = data.stamp['mode'] 3083 if sv.suspendmode == 'freeze' << 3084 self.machinesuspend = << 3085 else: << 3086 self.machinesuspend = << 3087 if sv.suspendmode == 'command 2308 if sv.suspendmode == 'command' and sv.ftracefile != '': 3088 modes = ['on', 'freez 2309 modes = ['on', 'freeze', 'standby', 'mem', 'disk'] 3089 fp = sv.openlog(sv.ft !! 2310 fp = sysvals.openlog(sv.ftracefile, 'r') 3090 for line in fp: 2311 for line in fp: 3091 m = re.match( !! 2312 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line) 3092 if m and m.gr 2313 if m and m.group('mode') in ['1', '2', '3', '4']: 3093 sv.su 2314 sv.suspendmode = modes[int(m.group('mode'))] 3094 data. 2315 data.stamp['mode'] = sv.suspendmode 3095 break 2316 break 3096 fp.close() 2317 fp.close() 3097 sv.cmdline = self.cmdline !! 2318 m = re.match(self.cmdlinefmt, self.cmdline) >> 2319 if m: >> 2320 sv.cmdline = m.group('cmd') >> 2321 if self.kparams: >> 2322 m = re.match(self.kparamsfmt, self.kparams) >> 2323 if m: >> 2324 sv.kparams = m.group('kp') 3098 if not sv.stamp: 2325 if not sv.stamp: 3099 sv.stamp = data.stamp 2326 sv.stamp = data.stamp 3100 # firmware data << 3101 if sv.suspendmode == 'mem' an << 3102 m = re.match(self.fir << 3103 if m: << 3104 data.fwSuspen << 3105 if(data.fwSus << 3106 data. << 3107 # turbostat data << 3108 if len(self.turbostat) > data << 3109 m = re.match(self.tst << 3110 if m: << 3111 data.turbosta << 3112 # wifi data << 3113 if len(self.wifi) > data.test << 3114 m = re.match(self.wif << 3115 if m: << 3116 data.wifi = { << 3117 'time << 3118 data.stamp['w << 3119 # sleep mode enter errors << 3120 if len(self.testerror) > data << 3121 m = re.match(self.tes << 3122 if m: << 3123 data.enterfai << 3124 def devprops(self, data): << 3125 props = dict() << 3126 devlist = data.split(';') << 3127 for dev in devlist: << 3128 f = dev.split(',') << 3129 if len(f) < 3: << 3130 continue << 3131 dev = f[0] << 3132 props[dev] = DevProps << 3133 props[dev].altname = << 3134 if int(f[2]): << 3135 props[dev].is << 3136 else: << 3137 props[dev].is << 3138 return props << 3139 def parseDevprops(self, line, sv): << 3140 idx = line.index(': ') + 2 << 3141 if idx >= len(line): << 3142 return << 3143 props = self.devprops(line[id << 3144 if sv.suspendmode == 'command << 3145 sv.testcommand = prop << 3146 sv.devprops = props << 3147 def parsePlatformInfo(self, line, sv) << 3148 m = re.match(self.pinfofmt, l << 3149 if not m: << 3150 return << 3151 name, info = m.group('val'), << 3152 if name == 'devinfo': << 3153 sv.devprops = self.de << 3154 return << 3155 elif name == 'testcmd': << 3156 sv.testcommand = info << 3157 return << 3158 field = info.split('|') << 3159 if len(field) < 2: << 3160 return << 3161 cmdline = field[0].strip() << 3162 output = sv.b64unzip(field[1] << 3163 sv.platinfo.append([name, cmd << 3164 2327 3165 # Class: TestRun 2328 # Class: TestRun 3166 # Description: 2329 # Description: 3167 # A container for a suspend/resume tes 2330 # A container for a suspend/resume test run. This is necessary as 3168 # there could be more than one, and th 2331 # there could be more than one, and they need to be separate. 3169 class TestRun: 2332 class TestRun: >> 2333 ftemp = dict() >> 2334 ttemp = dict() >> 2335 data = 0 3170 def __init__(self, dataobj): 2336 def __init__(self, dataobj): 3171 self.data = dataobj 2337 self.data = dataobj 3172 self.ftemp = dict() 2338 self.ftemp = dict() 3173 self.ttemp = dict() 2339 self.ttemp = dict() 3174 2340 3175 class ProcessMonitor: 2341 class ProcessMonitor: 3176 maxchars = 512 !! 2342 proclist = dict() 3177 def __init__(self): !! 2343 running = False 3178 self.proclist = dict() << 3179 self.running = False << 3180 def procstat(self): 2344 def procstat(self): 3181 c = ['cat /proc/[1-9]*/stat 2 2345 c = ['cat /proc/[1-9]*/stat 2>/dev/null'] 3182 process = Popen(c, shell=True 2346 process = Popen(c, shell=True, stdout=PIPE) 3183 running = dict() 2347 running = dict() 3184 for line in process.stdout: 2348 for line in process.stdout: 3185 data = ascii(line).sp !! 2349 data = line.split() 3186 pid = data[0] 2350 pid = data[0] 3187 name = re.sub('[()]', 2351 name = re.sub('[()]', '', data[1]) 3188 user = int(data[13]) 2352 user = int(data[13]) 3189 kern = int(data[14]) 2353 kern = int(data[14]) 3190 kjiff = ujiff = 0 2354 kjiff = ujiff = 0 3191 if pid not in self.pr 2355 if pid not in self.proclist: 3192 self.proclist 2356 self.proclist[pid] = {'name' : name, 'user' : user, 'kern' : kern} 3193 else: 2357 else: 3194 val = self.pr 2358 val = self.proclist[pid] 3195 ujiff = user 2359 ujiff = user - val['user'] 3196 kjiff = kern 2360 kjiff = kern - val['kern'] 3197 val['user'] = 2361 val['user'] = user 3198 val['kern'] = 2362 val['kern'] = kern 3199 if ujiff > 0 or kjiff 2363 if ujiff > 0 or kjiff > 0: 3200 running[pid] 2364 running[pid] = ujiff + kjiff 3201 process.wait() 2365 process.wait() 3202 out = [''] !! 2366 out = '' 3203 for pid in running: 2367 for pid in running: 3204 jiffies = running[pid 2368 jiffies = running[pid] 3205 val = self.proclist[p 2369 val = self.proclist[pid] 3206 if len(out[-1]) > sel !! 2370 if out: 3207 out.append('' !! 2371 out += ',' 3208 elif len(out[-1]) > 0 !! 2372 out += '%s-%s %d' % (val['name'], pid, jiffies) 3209 out[-1] += ', !! 2373 return 'ps - '+out 3210 out[-1] += '%s-%s %d' << 3211 if len(out) > 1: << 3212 for line in out: << 3213 sysvals.fsetV << 3214 else: << 3215 sysvals.fsetVal('ps - << 3216 def processMonitor(self, tid): 2374 def processMonitor(self, tid): 3217 while self.running: 2375 while self.running: 3218 self.procstat() !! 2376 out = self.procstat() >> 2377 if out: >> 2378 sysvals.fsetVal(out, 'trace_marker') 3219 def start(self): 2379 def start(self): 3220 self.thread = Thread(target=s 2380 self.thread = Thread(target=self.processMonitor, args=(0,)) 3221 self.running = True 2381 self.running = True 3222 self.thread.start() 2382 self.thread.start() 3223 def stop(self): 2383 def stop(self): 3224 self.running = False 2384 self.running = False 3225 2385 3226 # ----------------- FUNCTIONS --------------- 2386 # ----------------- FUNCTIONS -------------------- 3227 2387 3228 # Function: doesTraceLogHaveTraceEvents 2388 # Function: doesTraceLogHaveTraceEvents 3229 # Description: 2389 # Description: 3230 # Quickly determine if the ftrace log 2390 # Quickly determine if the ftrace log has all of the trace events, 3231 # markers, and/or kprobes required for 2391 # markers, and/or kprobes required for primary parsing. 3232 def doesTraceLogHaveTraceEvents(): 2392 def doesTraceLogHaveTraceEvents(): 3233 kpcheck = ['_cal: (', '_ret: ('] !! 2393 kpcheck = ['_cal: (', '_cpu_down()'] 3234 techeck = ['suspend_resume', 'device_ !! 2394 techeck = ['suspend_resume'] 3235 tmcheck = ['SUSPEND START', 'RESUME C 2395 tmcheck = ['SUSPEND START', 'RESUME COMPLETE'] 3236 sysvals.usekprobes = False 2396 sysvals.usekprobes = False 3237 fp = sysvals.openlog(sysvals.ftracefi 2397 fp = sysvals.openlog(sysvals.ftracefile, 'r') 3238 for line in fp: 2398 for line in fp: 3239 # check for kprobes 2399 # check for kprobes 3240 if not sysvals.usekprobes: 2400 if not sysvals.usekprobes: 3241 for i in kpcheck: 2401 for i in kpcheck: 3242 if i in line: 2402 if i in line: 3243 sysva 2403 sysvals.usekprobes = True 3244 # check for all necessary tra 2404 # check for all necessary trace events 3245 check = techeck[:] 2405 check = techeck[:] 3246 for i in techeck: 2406 for i in techeck: 3247 if i in line: 2407 if i in line: 3248 check.remove( 2408 check.remove(i) 3249 techeck = check 2409 techeck = check 3250 # check for all necessary tra 2410 # check for all necessary trace markers 3251 check = tmcheck[:] 2411 check = tmcheck[:] 3252 for i in tmcheck: 2412 for i in tmcheck: 3253 if i in line: 2413 if i in line: 3254 check.remove( 2414 check.remove(i) 3255 tmcheck = check 2415 tmcheck = check 3256 fp.close() 2416 fp.close() 3257 sysvals.usetraceevents = True if len( !! 2417 if len(techeck) == 0: 3258 sysvals.usetracemarkers = True if len !! 2418 sysvals.usetraceevents = True >> 2419 else: >> 2420 sysvals.usetraceevents = False >> 2421 if len(tmcheck) == 0: >> 2422 sysvals.usetracemarkers = True >> 2423 else: >> 2424 sysvals.usetracemarkers = False 3259 2425 3260 # Function: appendIncompleteTraceLog 2426 # Function: appendIncompleteTraceLog 3261 # Description: 2427 # Description: 3262 # Adds callgraph data which lacks trac !! 2428 # [deprecated for kernel 3.15 or newer] 3263 # for timelines generated from 3.15 or !! 2429 # Legacy support of ftrace outputs that lack the device_pm_callback >> 2430 # and/or suspend_resume trace events. The primary data should be >> 2431 # taken from dmesg, and this ftrace is used only for callgraph data >> 2432 # or custom actions in the timeline. The data is appended to the Data >> 2433 # objects provided. 3264 # Arguments: 2434 # Arguments: 3265 # testruns: the array of Data objects 2435 # testruns: the array of Data objects obtained from parseKernelLog 3266 def appendIncompleteTraceLog(testruns): 2436 def appendIncompleteTraceLog(testruns): 3267 # create TestRun vessels for ftrace p 2437 # create TestRun vessels for ftrace parsing 3268 testcnt = len(testruns) 2438 testcnt = len(testruns) 3269 testidx = 0 2439 testidx = 0 3270 testrun = [] 2440 testrun = [] 3271 for data in testruns: 2441 for data in testruns: 3272 testrun.append(TestRun(data)) 2442 testrun.append(TestRun(data)) 3273 2443 3274 # extract the callgraph and traceeven 2444 # extract the callgraph and traceevent data 3275 sysvals.vprint('Analyzing the ftrace 2445 sysvals.vprint('Analyzing the ftrace data (%s)...' % \ 3276 os.path.basename(sysvals.ftra 2446 os.path.basename(sysvals.ftracefile)) 3277 tp = TestProps() 2447 tp = TestProps() 3278 tf = sysvals.openlog(sysvals.ftracefi 2448 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3279 data = 0 2449 data = 0 3280 for line in tf: 2450 for line in tf: 3281 # remove any latent carriage 2451 # remove any latent carriage returns 3282 line = line.replace('\r\n', ' 2452 line = line.replace('\r\n', '') 3283 if tp.stampInfo(line, sysvals !! 2453 # grab the stamp and sysinfo >> 2454 if re.match(tp.stampfmt, line): >> 2455 tp.stamp = line >> 2456 continue >> 2457 elif re.match(tp.sysinfofmt, line): >> 2458 tp.sysinfo = line >> 2459 continue >> 2460 elif re.match(tp.cmdlinefmt, line): >> 2461 tp.cmdline = line >> 2462 continue >> 2463 # determine the trace data type (required for further parsing) >> 2464 m = re.match(sysvals.tracertypefmt, line) >> 2465 if(m): >> 2466 tp.setTracerType(m.group('t')) >> 2467 continue >> 2468 # device properties line >> 2469 if(re.match(sysvals.devpropfmt, line)): >> 2470 devProps(line) 3284 continue 2471 continue 3285 # parse only valid lines, if 2472 # parse only valid lines, if this is not one move on 3286 m = re.match(tp.ftrace_line_f 2473 m = re.match(tp.ftrace_line_fmt, line) 3287 if(not m): 2474 if(not m): 3288 continue 2475 continue 3289 # gather the basic message da 2476 # gather the basic message data from the line 3290 m_time = m.group('time') 2477 m_time = m.group('time') 3291 m_pid = m.group('pid') 2478 m_pid = m.group('pid') 3292 m_msg = m.group('msg') 2479 m_msg = m.group('msg') 3293 if(tp.cgformat): 2480 if(tp.cgformat): 3294 m_param3 = m.group('d 2481 m_param3 = m.group('dur') 3295 else: 2482 else: 3296 m_param3 = 'traceeven 2483 m_param3 = 'traceevent' 3297 if(m_time and m_pid and m_msg 2484 if(m_time and m_pid and m_msg): 3298 t = FTraceLine(m_time 2485 t = FTraceLine(m_time, m_msg, m_param3) 3299 pid = int(m_pid) 2486 pid = int(m_pid) 3300 else: 2487 else: 3301 continue 2488 continue 3302 # the line should be a call, 2489 # the line should be a call, return, or event 3303 if(not t.fcall and not t.fret 2490 if(not t.fcall and not t.freturn and not t.fevent): 3304 continue 2491 continue 3305 # look for the suspend start 2492 # look for the suspend start marker 3306 if(t.startMarker()): 2493 if(t.startMarker()): 3307 data = testrun[testid 2494 data = testrun[testidx].data 3308 tp.parseStamp(data, s 2495 tp.parseStamp(data, sysvals) 3309 data.setStart(t.time, !! 2496 data.setStart(t.time) 3310 continue 2497 continue 3311 if(not data): 2498 if(not data): 3312 continue 2499 continue 3313 # find the end of resume 2500 # find the end of resume 3314 if(t.endMarker()): 2501 if(t.endMarker()): 3315 data.setEnd(t.time, t !! 2502 data.setEnd(t.time) 3316 testidx += 1 2503 testidx += 1 3317 if(testidx >= testcnt 2504 if(testidx >= testcnt): 3318 break 2505 break 3319 continue 2506 continue 3320 # trace event processing 2507 # trace event processing 3321 if(t.fevent): 2508 if(t.fevent): 3322 continue !! 2509 # general trace events have two types, begin and end >> 2510 if(re.match('(?P<name>.*) begin$', t.name)): >> 2511 isbegin = True >> 2512 elif(re.match('(?P<name>.*) end$', t.name)): >> 2513 isbegin = False >> 2514 else: >> 2515 continue >> 2516 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) >> 2517 if(m): >> 2518 val = m.group('val') >> 2519 if val == '0': >> 2520 name = m.group('name') >> 2521 else: >> 2522 name = m.group('name')+'['+val+']' >> 2523 else: >> 2524 m = re.match('(?P<name>.*) .*', t.name) >> 2525 name = m.group('name') >> 2526 # special processing for trace events >> 2527 if re.match('dpm_prepare\[.*', name): >> 2528 continue >> 2529 elif re.match('machine_suspend.*', name): >> 2530 continue >> 2531 elif re.match('suspend_enter\[.*', name): >> 2532 if(not isbegin): >> 2533 data.dmesg['suspend_prepare']['end'] = t.time >> 2534 continue >> 2535 elif re.match('dpm_suspend\[.*', name): >> 2536 if(not isbegin): >> 2537 data.dmesg['suspend']['end'] = t.time >> 2538 continue >> 2539 elif re.match('dpm_suspend_late\[.*', name): >> 2540 if(isbegin): >> 2541 data.dmesg['suspend_late']['start'] = t.time >> 2542 else: >> 2543 data.dmesg['suspend_late']['end'] = t.time >> 2544 continue >> 2545 elif re.match('dpm_suspend_noirq\[.*', name): >> 2546 if(isbegin): >> 2547 data.dmesg['suspend_noirq']['start'] = t.time >> 2548 else: >> 2549 data.dmesg['suspend_noirq']['end'] = t.time >> 2550 continue >> 2551 elif re.match('dpm_resume_noirq\[.*', name): >> 2552 if(isbegin): >> 2553 data.dmesg['resume_machine']['end'] = t.time >> 2554 data.dmesg['resume_noirq']['start'] = t.time >> 2555 else: >> 2556 data.dmesg['resume_noirq']['end'] = t.time >> 2557 continue >> 2558 elif re.match('dpm_resume_early\[.*', name): >> 2559 if(isbegin): >> 2560 data.dmesg['resume_early']['start'] = t.time >> 2561 else: >> 2562 data.dmesg['resume_early']['end'] = t.time >> 2563 continue >> 2564 elif re.match('dpm_resume\[.*', name): >> 2565 if(isbegin): >> 2566 data.dmesg['resume']['start'] = t.time >> 2567 else: >> 2568 data.dmesg['resume']['end'] = t.time >> 2569 continue >> 2570 elif re.match('dpm_complete\[.*', name): >> 2571 if(isbegin): >> 2572 data.dmesg['resume_complete']['start'] = t.time >> 2573 else: >> 2574 data.dmesg['resume_complete']['end'] = t.time >> 2575 continue >> 2576 # skip trace events inside devices calls >> 2577 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)): >> 2578 continue >> 2579 # global events (outside device calls) are simply graphed >> 2580 if(isbegin): >> 2581 # store each trace event in ttemp >> 2582 if(name not in testrun[testidx].ttemp): >> 2583 testrun[testidx].ttemp[name] = [] >> 2584 testrun[testidx].ttemp[name].append(\ >> 2585 {'begin': t.time, 'end': t.time}) >> 2586 else: >> 2587 # finish off matching trace event in ttemp >> 2588 if(name in testrun[testidx].ttemp): >> 2589 testrun[testidx].ttemp[name][-1]['end'] = t.time 3323 # call/return processing 2590 # call/return processing 3324 elif sysvals.usecallgraph: 2591 elif sysvals.usecallgraph: 3325 # create a callgraph 2592 # create a callgraph object for the data 3326 if(pid not in testrun 2593 if(pid not in testrun[testidx].ftemp): 3327 testrun[testi 2594 testrun[testidx].ftemp[pid] = [] 3328 testrun[testi 2595 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals)) 3329 # when the call is fi 2596 # when the call is finished, see which device matches it 3330 cg = testrun[testidx] 2597 cg = testrun[testidx].ftemp[pid][-1] 3331 res = cg.addLine(t) 2598 res = cg.addLine(t) 3332 if(res != 0): 2599 if(res != 0): 3333 testrun[testi 2600 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals)) 3334 if(res == -1): 2601 if(res == -1): 3335 testrun[testi 2602 testrun[testidx].ftemp[pid][-1].addLine(t) 3336 tf.close() 2603 tf.close() 3337 2604 3338 for test in testrun: 2605 for test in testrun: >> 2606 # add the traceevent data to the device hierarchy >> 2607 if(sysvals.usetraceevents): >> 2608 for name in test.ttemp: >> 2609 for event in test.ttemp[name]: >> 2610 test.data.newActionGlobal(name, event['begin'], event['end']) >> 2611 3339 # add the callgraph data to t 2612 # add the callgraph data to the device hierarchy 3340 for pid in test.ftemp: 2613 for pid in test.ftemp: 3341 for cg in test.ftemp[ 2614 for cg in test.ftemp[pid]: 3342 if len(cg.lis 2615 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3343 conti 2616 continue 3344 if(not cg.pos 2617 if(not cg.postProcess()): 3345 id = 2618 id = 'task %s cpu %s' % (pid, m.group('cpu')) 3346 sysva 2619 sysvals.vprint('Sanity check failed for '+\ 3347 2620 id+', ignoring this callback') 3348 conti 2621 continue 3349 callstart = c 2622 callstart = cg.start 3350 callend = cg. 2623 callend = cg.end 3351 for p in test !! 2624 for p in test.data.phases: 3352 if(te 2625 if(test.data.dmesg[p]['start'] <= callstart and 3353 2626 callstart <= test.data.dmesg[p]['end']): 3354 2627 list = test.data.dmesg[p]['list'] 3355 2628 for devname in list: 3356 2629 dev = list[devname] 3357 2630 if(pid == dev['pid'] and 3358 2631 callstart <= dev['start'] and 3359 2632 callend >= dev['end']): 3360 2633 dev['ftrace'] = cg 3361 2634 break 3362 2635 3363 # Function: loadTraceLog << 3364 # Description: << 3365 # load the ftrace file into memory and << 3366 # Output: << 3367 # TestProps instance and an array of l << 3368 def loadTraceLog(): << 3369 tp, data, lines, trace = TestProps(), << 3370 tf = sysvals.openlog(sysvals.ftracefi << 3371 for line in tf: << 3372 # remove any latent carriage << 3373 line = line.replace('\r\n', ' << 3374 if tp.stampInfo(line, sysvals << 3375 continue << 3376 # ignore all other commented << 3377 if line[0] == '#': << 3378 continue << 3379 # ftrace line: parse only val << 3380 m = re.match(tp.ftrace_line_f << 3381 if(not m): << 3382 continue << 3383 dur = m.group('dur') if tp.cg << 3384 info = (m.group('time'), m.gr << 3385 m.group('msg'), dur) << 3386 # group the data by timestamp << 3387 t = float(info[0]) << 3388 if t in data: << 3389 data[t].append(info) << 3390 else: << 3391 data[t] = [info] << 3392 # we only care about trace ev << 3393 if (info[3].startswith('suspe << 3394 info[3].startswith('t << 3395 trace.append( << 3396 tf.close() << 3397 for t in sorted(data): << 3398 first, last, blk = [], [], da << 3399 if len(blk) > 1 and t in trac << 3400 # move certain lines << 3401 for i in range(len(bl << 3402 if 'SUSPEND S << 3403 first << 3404 elif re.match << 3405 last. << 3406 elif re.match << 3407 first << 3408 elif 'RESUME << 3409 last. << 3410 if len(first) == 1 an << 3411 blk.insert(0, << 3412 elif len(last) == 1 a << 3413 blk.append(bl << 3414 for info in blk: << 3415 lines.append(info) << 3416 return (tp, lines) << 3417 << 3418 # Function: parseTraceLog 2636 # Function: parseTraceLog 3419 # Description: 2637 # Description: 3420 # Analyze an ftrace log output file ge 2638 # Analyze an ftrace log output file generated from this app during 3421 # the execution phase. Used when the f 2639 # the execution phase. Used when the ftrace log is the primary data source 3422 # and includes the suspend_resume and 2640 # and includes the suspend_resume and device_pm_callback trace events 3423 # The ftrace filename is taken from sy 2641 # The ftrace filename is taken from sysvals 3424 # Output: 2642 # Output: 3425 # An array of Data objects 2643 # An array of Data objects 3426 def parseTraceLog(live=False): 2644 def parseTraceLog(live=False): 3427 sysvals.vprint('Analyzing the ftrace 2645 sysvals.vprint('Analyzing the ftrace data (%s)...' % \ 3428 os.path.basename(sysvals.ftra 2646 os.path.basename(sysvals.ftracefile)) 3429 if(os.path.exists(sysvals.ftracefile) 2647 if(os.path.exists(sysvals.ftracefile) == False): 3430 doError('%s does not exist' % 2648 doError('%s does not exist' % sysvals.ftracefile) 3431 if not live: 2649 if not live: 3432 sysvals.setupAllKprobes() 2650 sysvals.setupAllKprobes() 3433 ksuscalls = ['ksys_sync', 'pm_prepare !! 2651 tracewatch = [] 3434 krescalls = ['pm_restore_console'] << 3435 tracewatch = ['irq_wakeup'] << 3436 if sysvals.usekprobes: 2652 if sysvals.usekprobes: 3437 tracewatch += ['sync_filesyst 2653 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 3438 'syscore_resume', 're !! 2654 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', 'CPU_OFF'] 3439 'CPU_OFF', 'acpi_susp << 3440 2655 3441 # extract the callgraph and traceeven 2656 # extract the callgraph and traceevent data 3442 s2idle_enter = hwsus = False !! 2657 tp = TestProps() 3443 testruns, testdata = [], [] !! 2658 testruns = [] 3444 testrun, data, limbo = 0, 0, True !! 2659 testdata = [] >> 2660 testrun = 0 >> 2661 data = 0 >> 2662 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3445 phase = 'suspend_prepare' 2663 phase = 'suspend_prepare' 3446 tp, tf = loadTraceLog() !! 2664 for line in tf: 3447 for m_time, m_proc, m_pid, m_msg, m_p !! 2665 # remove any latent carriage returns >> 2666 line = line.replace('\r\n', '') >> 2667 # stamp and sysinfo lines >> 2668 if re.match(tp.stampfmt, line): >> 2669 tp.stamp = line >> 2670 continue >> 2671 elif re.match(tp.sysinfofmt, line): >> 2672 tp.sysinfo = line >> 2673 continue >> 2674 elif re.match(tp.cmdlinefmt, line): >> 2675 tp.cmdline = line >> 2676 continue >> 2677 # firmware line: pull out any firmware data >> 2678 m = re.match(sysvals.firmwarefmt, line) >> 2679 if(m): >> 2680 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) >> 2681 continue >> 2682 # tracer type line: determine the trace data type >> 2683 m = re.match(sysvals.tracertypefmt, line) >> 2684 if(m): >> 2685 tp.setTracerType(m.group('t')) >> 2686 continue >> 2687 # device properties line >> 2688 if(re.match(sysvals.devpropfmt, line)): >> 2689 devProps(line) >> 2690 continue >> 2691 # ignore all other commented lines >> 2692 if line[0] == '#': >> 2693 continue >> 2694 # ftrace line: parse only valid lines >> 2695 m = re.match(tp.ftrace_line_fmt, line) >> 2696 if(not m): >> 2697 continue 3448 # gather the basic message da 2698 # gather the basic message data from the line >> 2699 m_time = m.group('time') >> 2700 m_proc = m.group('proc') >> 2701 m_pid = m.group('pid') >> 2702 m_msg = m.group('msg') >> 2703 if(tp.cgformat): >> 2704 m_param3 = m.group('dur') >> 2705 else: >> 2706 m_param3 = 'traceevent' 3449 if(m_time and m_pid and m_msg 2707 if(m_time and m_pid and m_msg): 3450 t = FTraceLine(m_time 2708 t = FTraceLine(m_time, m_msg, m_param3) 3451 pid = int(m_pid) 2709 pid = int(m_pid) 3452 else: 2710 else: 3453 continue 2711 continue 3454 # the line should be a call, 2712 # the line should be a call, return, or event 3455 if(not t.fcall and not t.fret 2713 if(not t.fcall and not t.freturn and not t.fevent): 3456 continue 2714 continue 3457 # find the start of suspend 2715 # find the start of suspend 3458 if(t.startMarker()): 2716 if(t.startMarker()): 3459 data, limbo = Data(le !! 2717 phase = 'suspend_prepare' >> 2718 data = Data(len(testdata)) 3460 testdata.append(data) 2719 testdata.append(data) 3461 testrun = TestRun(dat 2720 testrun = TestRun(data) 3462 testruns.append(testr 2721 testruns.append(testrun) 3463 tp.parseStamp(data, s 2722 tp.parseStamp(data, sysvals) 3464 data.setStart(t.time, !! 2723 data.setStart(t.time) 3465 data.first_suspend_pr !! 2724 data.tKernSus = t.time 3466 phase = data.setPhase << 3467 continue 2725 continue 3468 if(not data or limbo): !! 2726 if(not data): 3469 continue 2727 continue 3470 # process cpu exec line 2728 # process cpu exec line 3471 if t.type == 'tracing_mark_wr 2729 if t.type == 'tracing_mark_write': 3472 if t.name == 'CMD COM !! 2730 m = re.match(sysvals.procexecfmt, t.name) 3473 data.tKernRes << 3474 m = re.match(tp.proce << 3475 if(m): 2731 if(m): 3476 parts, msg = !! 2732 proclist = dict() 3477 m = re.match( !! 2733 for ps in m.group('ps').split(','): 3478 if(m): << 3479 parts << 3480 if tp << 3481 << 3482 << 3483 procl << 3484 tp.mu << 3485 else: << 3486 procl << 3487 tp.mu << 3488 for ps in msg << 3489 val = 2734 val = ps.split() 3490 if no !! 2735 if not val: 3491 2736 continue 3492 name 2737 name = val[0].replace('--', '-') 3493 procl 2738 proclist[name] = int(val[1]) 3494 if parts == 1 !! 2739 data.pstl[t.time] = proclist 3495 data. << 3496 elif parts == << 3497 data. << 3498 tp.mu << 3499 continue 2740 continue 3500 # find the end of resume 2741 # find the end of resume 3501 if(t.endMarker()): 2742 if(t.endMarker()): 3502 if data.tKernRes == 0 !! 2743 data.setEnd(t.time) >> 2744 if data.tKernRes == 0.0: 3503 data.tKernRes 2745 data.tKernRes = t.time 3504 data.handleEndMarker( !! 2746 if data.dmesg['resume_complete']['end'] < 0: >> 2747 data.dmesg['resume_complete']['end'] = t.time >> 2748 if sysvals.suspendmode == 'mem' and len(tp.fwdata) > data.testnumber: >> 2749 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber] >> 2750 if(data.tSuspended != 0 and data.tResumed != 0 and \ >> 2751 (data.fwSuspend > 0 or data.fwResume > 0)): >> 2752 data.fwValid = True 3505 if(not sysvals.usetra 2753 if(not sysvals.usetracemarkers): 3506 # no trace ma 2754 # no trace markers? then quit and be sure to finish recording 3507 # the event w 2755 # the event we used to trigger resume end 3508 if('thaw_proc !! 2756 if(len(testrun.ttemp['thaw_processes']) > 0): 3509 # if 2757 # if an entry exists, assume this is its end 3510 testr 2758 testrun.ttemp['thaw_processes'][-1]['end'] = t.time 3511 limbo = True !! 2759 break 3512 continue 2760 continue 3513 # trace event processing 2761 # trace event processing 3514 if(t.fevent): 2762 if(t.fevent): >> 2763 if(phase == 'post_resume'): >> 2764 data.setEnd(t.time) 3515 if(t.type == 'suspend 2765 if(t.type == 'suspend_resume'): 3516 # suspend_res 2766 # suspend_resume trace events have two types, begin and end 3517 if(re.match(r !! 2767 if(re.match('(?P<name>.*) begin$', t.name)): 3518 isbeg 2768 isbegin = True 3519 elif(re.match !! 2769 elif(re.match('(?P<name>.*) end$', t.name)): 3520 isbeg 2770 isbegin = False 3521 else: 2771 else: 3522 conti 2772 continue 3523 if '[' in t.n !! 2773 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) 3524 m = r !! 2774 if(m): >> 2775 val = m.group('val') >> 2776 if val == '0': >> 2777 name = m.group('name') >> 2778 else: >> 2779 name = m.group('name')+'['+val+']' 3525 else: 2780 else: 3526 m = r !! 2781 m = re.match('(?P<name>.*) .*', t.name) 3527 name = m.grou !! 2782 name = m.group('name') 3528 # ignore thes 2783 # ignore these events 3529 if(name.split 2784 if(name.split('[')[0] in tracewatch): 3530 conti 2785 continue 3531 # -- phase ch 2786 # -- phase changes -- 3532 # start of ke 2787 # start of kernel suspend 3533 if(re.match(r !! 2788 if(re.match('suspend_enter\[.*', t.name)): 3534 if(is !! 2789 if(isbegin and data.start == data.tKernSus): >> 2790 data.dmesg[phase]['start'] = t.time 3535 2791 data.tKernSus = t.time 3536 conti 2792 continue 3537 # suspend_pre 2793 # suspend_prepare start 3538 elif(re.match !! 2794 elif(re.match('dpm_prepare\[.*', t.name)): 3539 if is !! 2795 phase = 'suspend_prepare' 3540 !! 2796 if(not isbegin): 3541 !! 2797 data.dmesg[phase]['end'] = t.time 3542 !! 2798 if data.dmesg[phase]['start'] < 0: 3543 !! 2799 data.dmesg[phase]['start'] = data.start 3544 phase << 3545 conti 2800 continue 3546 # suspend sta 2801 # suspend start 3547 elif(re.match !! 2802 elif(re.match('dpm_suspend\[.*', t.name)): 3548 phase !! 2803 phase = 'suspend' >> 2804 data.setPhase(phase, t.time, isbegin) 3549 conti 2805 continue 3550 # suspend_lat 2806 # suspend_late start 3551 elif(re.match !! 2807 elif(re.match('dpm_suspend_late\[.*', t.name)): 3552 phase !! 2808 phase = 'suspend_late' >> 2809 data.setPhase(phase, t.time, isbegin) 3553 conti 2810 continue 3554 # suspend_noi 2811 # suspend_noirq start 3555 elif(re.match !! 2812 elif(re.match('dpm_suspend_noirq\[.*', t.name)): 3556 phase !! 2813 if data.phaseCollision('suspend_noirq', isbegin, line): >> 2814 continue >> 2815 phase = 'suspend_noirq' >> 2816 data.setPhase(phase, t.time, isbegin) >> 2817 if(not isbegin): >> 2818 phase = 'suspend_machine' >> 2819 data.dmesg[phase]['start'] = t.time 3557 conti 2820 continue 3558 # suspend_mac 2821 # suspend_machine/resume_machine 3559 elif(re.match !! 2822 elif(re.match('machine_suspend\[.*', t.name)): 3560 lp = << 3561 if(is 2823 if(isbegin): 3562 !! 2824 phase = 'suspend_machine' 3563 !! 2825 data.dmesg[phase]['end'] = t.time 3564 !! 2826 data.tSuspended = t.time 3565 << 3566 << 3567 << 3568 << 3569 << 3570 << 3571 << 3572 << 3573 << 3574 << 3575 << 3576 << 3577 << 3578 << 3579 else: 2827 else: 3580 !! 2828 if(sysvals.suspendmode in ['mem', 'disk'] and not tp.S0i3): 3581 !! 2829 data.dmesg['suspend_machine']['end'] = t.time 3582 << 3583 << 3584 << 3585 << 3586 << 3587 << 3588 2830 data.tSuspended = t.time >> 2831 phase = 'resume_machine' >> 2832 data.dmesg[phase]['start'] = t.time 3589 2833 data.tResumed = t.time >> 2834 data.tLow = data.tResumed - data.tSuspended >> 2835 continue >> 2836 # acpi_suspend >> 2837 elif(re.match('acpi_suspend\[.*', t.name)): >> 2838 # acpi_suspend[0] S0i3 >> 2839 if(re.match('acpi_suspend\[0\] begin', t.name)): >> 2840 if(sysvals.suspendmode == 'mem'): >> 2841 tp.S0i3 = True >> 2842 data.dmesg['suspend_machine']['end'] = t.time >> 2843 data.tSuspended = t.time 3590 conti 2844 continue 3591 # resume_noir 2845 # resume_noirq start 3592 elif(re.match !! 2846 elif(re.match('dpm_resume_noirq\[.*', t.name)): 3593 phase !! 2847 if data.phaseCollision('resume_noirq', isbegin, line): >> 2848 continue >> 2849 phase = 'resume_noirq' >> 2850 data.setPhase(phase, t.time, isbegin) >> 2851 if(isbegin): >> 2852 data.dmesg['resume_machine']['end'] = t.time 3594 conti 2853 continue 3595 # resume_earl 2854 # resume_early start 3596 elif(re.match !! 2855 elif(re.match('dpm_resume_early\[.*', t.name)): 3597 phase !! 2856 phase = 'resume_early' >> 2857 data.setPhase(phase, t.time, isbegin) 3598 conti 2858 continue 3599 # resume star 2859 # resume start 3600 elif(re.match !! 2860 elif(re.match('dpm_resume\[.*', t.name)): 3601 phase !! 2861 phase = 'resume' >> 2862 data.setPhase(phase, t.time, isbegin) 3602 conti 2863 continue 3603 # resume comp 2864 # resume complete start 3604 elif(re.match !! 2865 elif(re.match('dpm_complete\[.*', t.name)): 3605 phase !! 2866 phase = 'resume_complete' >> 2867 if(isbegin): >> 2868 data.dmesg[phase]['start'] = t.time 3606 conti 2869 continue 3607 # skip trace 2870 # skip trace events inside devices calls 3608 if(not data.i 2871 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)): 3609 conti 2872 continue 3610 # global even 2873 # global events (outside device calls) are graphed 3611 if(name not i 2874 if(name not in testrun.ttemp): 3612 testr 2875 testrun.ttemp[name] = [] 3613 # special han << 3614 if name == 'm << 3615 if hw << 3616 << 3617 elif << 3618 << 3619 << 3620 << 3621 elif << 3622 << 3623 << 3624 << 3625 conti << 3626 if(isbegin): 2876 if(isbegin): 3627 # cre 2877 # create a new list entry 3628 testr 2878 testrun.ttemp[name].append(\ 3629 2879 {'begin': t.time, 'end': t.time, 'pid': pid}) 3630 else: 2880 else: 3631 if(le 2881 if(len(testrun.ttemp[name]) > 0): 3632 2882 # if an entry exists, assume this is its end 3633 2883 testrun.ttemp[name][-1]['end'] = t.time >> 2884 elif(phase == 'post_resume'): >> 2885 # post resume events can just have ends >> 2886 testrun.ttemp[name].append({ >> 2887 'begin': data.dmesg[phase]['start'], >> 2888 'end': t.time}) 3634 # device callback sta 2889 # device callback start 3635 elif(t.type == 'devic 2890 elif(t.type == 'device_pm_callback_start'): 3636 if phase not !! 2891 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\ 3637 conti << 3638 m = re.match( << 3639 t.nam 2892 t.name); 3640 if(not m): 2893 if(not m): 3641 conti 2894 continue 3642 drv = m.group 2895 drv = m.group('drv') 3643 n = m.group(' 2896 n = m.group('d') 3644 p = m.group(' 2897 p = m.group('p') 3645 if(n and p): 2898 if(n and p): 3646 data. 2899 data.newAction(phase, n, pid, p, t.time, -1, drv) 3647 if pi 2900 if pid not in data.devpids: 3648 2901 data.devpids.append(pid) 3649 # device callback fin 2902 # device callback finish 3650 elif(t.type == 'devic 2903 elif(t.type == 'device_pm_callback_end'): 3651 if phase not !! 2904 m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name); 3652 conti << 3653 m = re.match( << 3654 if(not m): 2905 if(not m): 3655 conti 2906 continue 3656 n = m.group(' 2907 n = m.group('d') 3657 dev = data.fi !! 2908 list = data.dmesg[phase]['list'] 3658 if dev: !! 2909 if(n in list): >> 2910 dev = list[n] 3659 dev[' 2911 dev['length'] = t.time - dev['start'] 3660 dev[' 2912 dev['end'] = t.time 3661 # kprobe event processing 2913 # kprobe event processing 3662 elif(t.fkprobe): 2914 elif(t.fkprobe): 3663 kprobename = t.type 2915 kprobename = t.type 3664 kprobedata = t.name 2916 kprobedata = t.name 3665 key = (kprobename, pi 2917 key = (kprobename, pid) 3666 # displayname is gene 2918 # displayname is generated from kprobe data 3667 displayname = '' 2919 displayname = '' 3668 if(t.fcall): 2920 if(t.fcall): 3669 displayname = 2921 displayname = sysvals.kprobeDisplayName(kprobename, kprobedata) 3670 if not displa 2922 if not displayname: 3671 conti 2923 continue 3672 if(key not in 2924 if(key not in tp.ktemp): 3673 tp.kt 2925 tp.ktemp[key] = [] 3674 tp.ktemp[key] 2926 tp.ktemp[key].append({ 3675 'pid' 2927 'pid': pid, 3676 'begi 2928 'begin': t.time, 3677 'end' !! 2929 'end': t.time, 3678 'name 2930 'name': displayname, 3679 'cdat 2931 'cdata': kprobedata, 3680 'proc 2932 'proc': m_proc, 3681 }) 2933 }) 3682 # start of ke << 3683 if(data.tKern << 3684 and k << 3685 data. << 3686 elif(t.freturn): 2934 elif(t.freturn): 3687 if(key not in 2935 if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1: 3688 conti 2936 continue 3689 e = next((x f !! 2937 e = tp.ktemp[key][-1] 3690 if not e: !! 2938 if e['begin'] < 0.0 or t.time - e['begin'] < 0.000001: 3691 conti << 3692 if (t.time - << 3693 tp.kt 2939 tp.ktemp[key].pop() 3694 conti !! 2940 else: 3695 e['end'] = t. !! 2941 e['end'] = t.time 3696 e['rdata'] = !! 2942 e['rdata'] = kprobedata 3697 # end of kern 2943 # end of kernel resume 3698 if(phase != ' !! 2944 if(kprobename == 'pm_notifier_call_chain' or \ 3699 if ph !! 2945 kprobename == 'pm_restore_console'): 3700 !! 2946 data.dmesg[phase]['end'] = t.time 3701 data. 2947 data.tKernRes = t.time 3702 2948 3703 # callgraph processing 2949 # callgraph processing 3704 elif sysvals.usecallgraph: 2950 elif sysvals.usecallgraph: 3705 # create a callgraph 2951 # create a callgraph object for the data 3706 key = (m_proc, pid) 2952 key = (m_proc, pid) 3707 if(key not in testrun 2953 if(key not in testrun.ftemp): 3708 testrun.ftemp 2954 testrun.ftemp[key] = [] 3709 testrun.ftemp 2955 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3710 # when the call is fi 2956 # when the call is finished, see which device matches it 3711 cg = testrun.ftemp[ke 2957 cg = testrun.ftemp[key][-1] 3712 res = cg.addLine(t) 2958 res = cg.addLine(t) 3713 if(res != 0): 2959 if(res != 0): 3714 testrun.ftemp 2960 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3715 if(res == -1): 2961 if(res == -1): 3716 testrun.ftemp 2962 testrun.ftemp[key][-1].addLine(t) 3717 if len(testdata) < 1: !! 2963 tf.close() 3718 sysvals.vprint('WARNING: ftra << 3719 if data and not data.devicegroups: << 3720 sysvals.vprint('WARNING: ftra << 3721 data.handleEndMarker(t.time, << 3722 2964 3723 if sysvals.suspendmode == 'command': 2965 if sysvals.suspendmode == 'command': 3724 for test in testruns: 2966 for test in testruns: 3725 for p in test.data.so !! 2967 for p in test.data.phases: 3726 if p == 'susp 2968 if p == 'suspend_prepare': 3727 test. 2969 test.data.dmesg[p]['start'] = test.data.start 3728 test. 2970 test.data.dmesg[p]['end'] = test.data.end 3729 else: 2971 else: 3730 test. 2972 test.data.dmesg[p]['start'] = test.data.end 3731 test. 2973 test.data.dmesg[p]['end'] = test.data.end 3732 test.data.tSuspended 2974 test.data.tSuspended = test.data.end 3733 test.data.tResumed = 2975 test.data.tResumed = test.data.end >> 2976 test.data.tLow = 0 3734 test.data.fwValid = F 2977 test.data.fwValid = False 3735 2978 3736 # dev source and procmon events can b 2979 # dev source and procmon events can be unreadable with mixed phase height 3737 if sysvals.usedevsrc or sysvals.usepr 2980 if sysvals.usedevsrc or sysvals.useprocmon: 3738 sysvals.mixedphaseheight = Fa 2981 sysvals.mixedphaseheight = False 3739 2982 3740 # expand phase boundaries so there ar << 3741 for data in testdata: << 3742 lp = data.sortedPhases()[0] << 3743 for p in data.sortedPhases(): << 3744 if(p != lp and not (' << 3745 data.dmesg[lp << 3746 lp = p << 3747 << 3748 for i in range(len(testruns)): 2983 for i in range(len(testruns)): 3749 test = testruns[i] 2984 test = testruns[i] 3750 data = test.data 2985 data = test.data 3751 # find the total time range f 2986 # find the total time range for this test (begin, end) 3752 tlb, tle = data.start, data.e 2987 tlb, tle = data.start, data.end 3753 if i < len(testruns) - 1: 2988 if i < len(testruns) - 1: 3754 tle = testruns[i+1].d 2989 tle = testruns[i+1].data.start 3755 # add the process usage data 2990 # add the process usage data to the timeline 3756 if sysvals.useprocmon: 2991 if sysvals.useprocmon: 3757 data.createProcessUsa 2992 data.createProcessUsageEvents() 3758 # add the traceevent data to 2993 # add the traceevent data to the device hierarchy 3759 if(sysvals.usetraceevents): 2994 if(sysvals.usetraceevents): 3760 # add actual trace fu 2995 # add actual trace funcs 3761 for name in sorted(te !! 2996 for name in test.ttemp: 3762 for event in 2997 for event in test.ttemp[name]: 3763 if ev !! 2998 data.newActionGlobal(name, event['begin'], event['end'], event['pid']) 3764 << 3765 title << 3766 if na << 3767 << 3768 data. << 3769 # add the kprobe base 2999 # add the kprobe based virtual tracefuncs as actual devices 3770 for key in sorted(tp. !! 3000 for key in tp.ktemp: 3771 name, pid = k 3001 name, pid = key 3772 if name not i 3002 if name not in sysvals.tracefuncs: 3773 conti 3003 continue 3774 if pid not in << 3775 data. << 3776 for e in tp.k 3004 for e in tp.ktemp[key]: 3777 kb, k 3005 kb, ke = e['begin'], e['end'] 3778 if ke !! 3006 if kb == ke or tlb > kb or tle <= kb: 3779 3007 continue 3780 color 3008 color = sysvals.kprobeColor(name) 3781 data. 3009 data.newActionGlobal(e['name'], kb, ke, pid, color) 3782 # add config base kpr 3010 # add config base kprobes and dev kprobes 3783 if sysvals.usedevsrc: 3011 if sysvals.usedevsrc: 3784 for key in so !! 3012 for key in tp.ktemp: 3785 name, 3013 name, pid = key 3786 if na 3014 if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs: 3787 3015 continue 3788 for e 3016 for e in tp.ktemp[key]: 3789 3017 kb, ke = e['begin'], e['end'] 3790 !! 3018 if kb == ke or tlb > kb or tle <= kb: 3791 3019 continue 3792 3020 data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb, 3793 3021 ke, e['cdata'], e['rdata']) 3794 if sysvals.usecallgraph: 3022 if sysvals.usecallgraph: 3795 # add the callgraph d 3023 # add the callgraph data to the device hierarchy 3796 sortlist = dict() 3024 sortlist = dict() 3797 for key in sorted(tes !! 3025 for key in test.ftemp: 3798 proc, pid = k 3026 proc, pid = key 3799 for cg in tes 3027 for cg in test.ftemp[key]: 3800 if le 3028 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3801 3029 continue 3802 if(no 3030 if(not cg.postProcess()): 3803 3031 id = 'task %s' % (pid) 3804 3032 sysvals.vprint('Sanity check failed for '+\ 3805 3033 id+', ignoring this callback') 3806 3034 continue 3807 # mat 3035 # match cg data to devices 3808 devna 3036 devname = '' 3809 if sy 3037 if sysvals.suspendmode != 'command': 3810 3038 devname = cg.deviceMatch(pid, data) 3811 if no 3039 if not devname: 3812 3040 sortkey = '%f%f%d' % (cg.start, cg.end, pid) 3813 3041 sortlist[sortkey] = cg 3814 elif !! 3042 elif len(cg.list) > 1000000: 3815 !! 3043 print 'WARNING: the callgraph for %s is massive (%d lines)' %\ 3816 !! 3044 (devname, len(cg.list)) 3817 # create blocks for o 3045 # create blocks for orphan cg data 3818 for sortkey in sorted 3046 for sortkey in sorted(sortlist): 3819 cg = sortlist 3047 cg = sortlist[sortkey] 3820 name = cg.nam 3048 name = cg.name 3821 if sysvals.is 3049 if sysvals.isCallgraphFunc(name): 3822 sysva 3050 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name)) 3823 cg.ne 3051 cg.newActionFromFunction(data) 3824 if sysvals.suspendmode == 'command': 3052 if sysvals.suspendmode == 'command': 3825 return (testdata, '') 3053 return (testdata, '') 3826 3054 3827 # fill in any missing phases 3055 # fill in any missing phases 3828 error = [] 3056 error = [] 3829 for data in testdata: 3057 for data in testdata: 3830 tn = '' if len(testdata) == 1 3058 tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1)) 3831 terr = '' 3059 terr = '' 3832 phasedef = data.phasedef !! 3060 lp = data.phases[0] 3833 lp = 'suspend_prepare' !! 3061 for p in data.phases: 3834 for p in sorted(phasedef, key !! 3062 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): 3835 if p not in data.dmes << 3836 if not terr: 3063 if not terr: 3837 ph = !! 3064 print 'TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp) 3838 if p !! 3065 terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp) 3839 << 3840 << 3841 << 3842 << 3843 else: << 3844 << 3845 pprin << 3846 error 3066 error.append(terr) 3847 if da << 3848 << 3849 if da << 3850 << 3851 data. << 3852 sysvals.vprin 3067 sysvals.vprint('WARNING: phase "%s" is missing!' % p) >> 3068 if(data.dmesg[p]['start'] < 0): >> 3069 data.dmesg[p]['start'] = data.dmesg[lp]['end'] >> 3070 if(p == 'resume_machine'): >> 3071 data.tSuspended = data.dmesg[lp]['end'] >> 3072 data.tResumed = data.dmesg[lp]['end'] >> 3073 data.tLow = 0 >> 3074 if(data.dmesg[p]['end'] < 0): >> 3075 data.dmesg[p]['end'] = data.dmesg[p]['start'] >> 3076 if(p != lp and not ('machine' in p and 'machine' in lp)): >> 3077 data.dmesg[lp]['end'] = data.dmesg[p]['start'] 3853 lp = p 3078 lp = p 3854 if not terr and 'dev' in data << 3855 terr = '%s%s failed i << 3856 (sysvals.susp << 3857 error.append(terr) << 3858 if not terr and data.enterfai << 3859 pprint('test%s FAILED << 3860 terr = 'test%s failed << 3861 error.append(terr) << 3862 if data.tSuspended == 0: << 3863 data.tSuspended = dat << 3864 if data.tResumed == 0: << 3865 data.tResumed = data. << 3866 3079 3867 if(len(sysvals.devicefilter) 3080 if(len(sysvals.devicefilter) > 0): 3868 data.deviceFilter(sys 3081 data.deviceFilter(sysvals.devicefilter) 3869 data.fixupInitcallsThatDidntR 3082 data.fixupInitcallsThatDidntReturn() 3870 if sysvals.usedevsrc: 3083 if sysvals.usedevsrc: 3871 data.optimizeDevSrc() 3084 data.optimizeDevSrc() 3872 3085 3873 # x2: merge any overlapping devices b 3086 # x2: merge any overlapping devices between test runs 3874 if sysvals.usedevsrc and len(testdata 3087 if sysvals.usedevsrc and len(testdata) > 1: 3875 tc = len(testdata) 3088 tc = len(testdata) 3876 for i in range(tc - 1): 3089 for i in range(tc - 1): 3877 devlist = testdata[i] 3090 devlist = testdata[i].overflowDevices() 3878 for j in range(i + 1, 3091 for j in range(i + 1, tc): 3879 testdata[j].m 3092 testdata[j].mergeOverlapDevices(devlist) 3880 testdata[0].stitchTouchingThr 3093 testdata[0].stitchTouchingThreads(testdata[1:]) 3881 return (testdata, ', '.join(error)) 3094 return (testdata, ', '.join(error)) 3882 3095 3883 # Function: loadKernelLog 3096 # Function: loadKernelLog 3884 # Description: 3097 # Description: >> 3098 # [deprecated for kernel 3.15.0 or newer] 3885 # load the dmesg file into memory and 3099 # load the dmesg file into memory and fix up any ordering issues >> 3100 # The dmesg filename is taken from sysvals 3886 # Output: 3101 # Output: 3887 # An array of empty Data objects with 3102 # An array of empty Data objects with only their dmesgtext attributes set 3888 def loadKernelLog(): 3103 def loadKernelLog(): 3889 sysvals.vprint('Analyzing the dmesg d 3104 sysvals.vprint('Analyzing the dmesg data (%s)...' % \ 3890 os.path.basename(sysvals.dmes 3105 os.path.basename(sysvals.dmesgfile)) 3891 if(os.path.exists(sysvals.dmesgfile) 3106 if(os.path.exists(sysvals.dmesgfile) == False): 3892 doError('%s does not exist' % 3107 doError('%s does not exist' % sysvals.dmesgfile) 3893 3108 3894 # there can be multiple test runs in 3109 # there can be multiple test runs in a single file 3895 tp = TestProps() 3110 tp = TestProps() 3896 tp.stamp = datetime.now().strftime('# 3111 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown') 3897 testruns = [] 3112 testruns = [] 3898 data = 0 3113 data = 0 3899 lf = sysvals.openlog(sysvals.dmesgfil 3114 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 3900 for line in lf: 3115 for line in lf: 3901 line = line.replace('\r\n', ' 3116 line = line.replace('\r\n', '') 3902 idx = line.find('[') 3117 idx = line.find('[') 3903 if idx > 1: 3118 if idx > 1: 3904 line = line[idx:] 3119 line = line[idx:] 3905 if tp.stampInfo(line, sysvals !! 3120 # grab the stamp and sysinfo >> 3121 if re.match(tp.stampfmt, line): >> 3122 tp.stamp = line >> 3123 continue >> 3124 elif re.match(tp.sysinfofmt, line): >> 3125 tp.sysinfo = line >> 3126 continue >> 3127 elif re.match(tp.cmdlinefmt, line): >> 3128 tp.cmdline = line >> 3129 continue >> 3130 m = re.match(sysvals.firmwarefmt, line) >> 3131 if(m): >> 3132 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) 3906 continue 3133 continue 3907 m = re.match(r'[ \t]*(\[ *)(? !! 3134 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 3908 if(not m): 3135 if(not m): 3909 continue 3136 continue 3910 msg = m.group("msg") 3137 msg = m.group("msg") 3911 if re.match(r'PM: Syncing fil !! 3138 if(re.match('PM: Syncing filesystems.*', msg)): 3912 re.match(r'PM: suspen << 3913 if(data): 3139 if(data): 3914 testruns.appe 3140 testruns.append(data) 3915 data = Data(len(testr 3141 data = Data(len(testruns)) 3916 tp.parseStamp(data, s 3142 tp.parseStamp(data, sysvals) >> 3143 if len(tp.fwdata) > data.testnumber: >> 3144 data.fwSuspend, data.fwResume = tp.fwdata[data.testnumber] >> 3145 if(data.fwSuspend > 0 or data.fwResume > 0): >> 3146 data.fwValid = True 3917 if(not data): 3147 if(not data): 3918 continue 3148 continue 3919 m = re.match(r'.* *(?P<k>[0-9 !! 3149 m = re.match('.* *(?P<k>[0-9]\.[0-9]{2}\.[0-9]-.*) .*', msg) 3920 if(m): 3150 if(m): 3921 sysvals.stamp['kernel 3151 sysvals.stamp['kernel'] = m.group('k') 3922 m = re.match(r'PM: Preparing !! 3152 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg) 3923 if not m: !! 3153 if(m): 3924 m = re.match(r'PM: Pr << 3925 if m: << 3926 sysvals.stamp['mode'] 3154 sysvals.stamp['mode'] = sysvals.suspendmode = m.group('m') 3927 data.dmesgtext.append(line) 3155 data.dmesgtext.append(line) 3928 lf.close() 3156 lf.close() 3929 3157 3930 if sysvals.suspendmode == 's2idle': << 3931 sysvals.suspendmode = 'freeze << 3932 elif sysvals.suspendmode == 'deep': << 3933 sysvals.suspendmode = 'mem' << 3934 if data: 3158 if data: 3935 testruns.append(data) 3159 testruns.append(data) 3936 if len(testruns) < 1: 3160 if len(testruns) < 1: 3937 doError('dmesg log has no sus !! 3161 print('ERROR: dmesg log has no suspend/resume data: %s' \ 3938 % sysvals.dmesgfile) 3162 % sysvals.dmesgfile) 3939 3163 3940 # fix lines with same timestamp/funct 3164 # fix lines with same timestamp/function with the call and return swapped 3941 for data in testruns: 3165 for data in testruns: 3942 last = '' 3166 last = '' 3943 for line in data.dmesgtext: 3167 for line in data.dmesgtext: 3944 ct, cf, n, p = data.i !! 3168 mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\ 3945 rt, rf, l = data.init !! 3169 '(?P<f>.*)\+ @ .*, parent: .*', line) 3946 if ct and rt and ct = !! 3170 mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\ >> 3171 '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last) >> 3172 if(mc and mr and (mc.group('t') == mr.group('t')) and >> 3173 (mc.group('f') == mr.group('f'))): 3947 i = data.dmes 3174 i = data.dmesgtext.index(last) 3948 j = data.dmes 3175 j = data.dmesgtext.index(line) 3949 data.dmesgtex 3176 data.dmesgtext[i] = line 3950 data.dmesgtex 3177 data.dmesgtext[j] = last 3951 last = line 3178 last = line 3952 return testruns 3179 return testruns 3953 3180 3954 # Function: parseKernelLog 3181 # Function: parseKernelLog 3955 # Description: 3182 # Description: >> 3183 # [deprecated for kernel 3.15.0 or newer] 3956 # Analyse a dmesg log output file gene 3184 # Analyse a dmesg log output file generated from this app during 3957 # the execution phase. Create a set of 3185 # the execution phase. Create a set of device structures in memory 3958 # for subsequent formatting in the htm 3186 # for subsequent formatting in the html output file 3959 # This call is only for legacy support 3187 # This call is only for legacy support on kernels where the ftrace 3960 # data lacks the suspend_resume or dev 3188 # data lacks the suspend_resume or device_pm_callbacks trace events. 3961 # Arguments: 3189 # Arguments: 3962 # data: an empty Data object (with dme 3190 # data: an empty Data object (with dmesgtext) obtained from loadKernelLog 3963 # Output: 3191 # Output: 3964 # The filled Data object 3192 # The filled Data object 3965 def parseKernelLog(data): 3193 def parseKernelLog(data): 3966 phase = 'suspend_runtime' 3194 phase = 'suspend_runtime' 3967 3195 3968 if(data.fwValid): 3196 if(data.fwValid): 3969 sysvals.vprint('Firmware Susp 3197 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \ 3970 (data.fwSuspend, data 3198 (data.fwSuspend, data.fwResume)) 3971 3199 3972 # dmesg phase match table 3200 # dmesg phase match table 3973 dm = { 3201 dm = { 3974 'suspend_prepare': ['PM: Sync !! 3202 'suspend_prepare': 'PM: Syncing filesystems.*', 3975 'suspend': ['PM: Ente !! 3203 'suspend': 'PM: Entering [a-z]* sleep.*', 3976 'PM: Susp !! 3204 'suspend_late': 'PM: suspend of devices complete after.*', 3977 'suspend_late': ['PM: susp !! 3205 'suspend_noirq': 'PM: late suspend of devices complete after.*', 3978 !! 3206 'suspend_machine': 'PM: noirq suspend of devices complete after.*', 3979 'suspend_noirq': ['PM: late !! 3207 'resume_machine': 'ACPI: Low-level resume complete.*', 3980 !! 3208 'resume_noirq': 'ACPI: Waking up from system sleep state.*', 3981 'suspend_machine': ['PM: susp !! 3209 'resume_early': 'PM: noirq resume of devices complete after.*', 3982 !! 3210 'resume': 'PM: early resume of devices complete after.*', 3983 !! 3211 'resume_complete': 'PM: resume of devices complete after.*', 3984 'resume_machine': ['[PM: ]*T !! 3212 'post_resume': '.*Restarting tasks \.\.\..*', 3985 << 3986 << 3987 << 3988 'resume_noirq': ['PM: resu << 3989 << 3990 'resume_early': ['PM: noir << 3991 << 3992 'resume': ['PM: earl << 3993 << 3994 'resume_complete': ['PM: resu << 3995 << 3996 'post_resume': [r'.*Resta << 3997 } 3213 } >> 3214 if(sysvals.suspendmode == 'standby'): >> 3215 dm['resume_machine'] = 'PM: Restoring platform NVS memory' >> 3216 elif(sysvals.suspendmode == 'disk'): >> 3217 dm['suspend_late'] = 'PM: freeze of devices complete after.*' >> 3218 dm['suspend_noirq'] = 'PM: late freeze of devices complete after.*' >> 3219 dm['suspend_machine'] = 'PM: noirq freeze of devices complete after.*' >> 3220 dm['resume_machine'] = 'PM: Restoring platform NVS memory' >> 3221 dm['resume_early'] = 'PM: noirq restore of devices complete after.*' >> 3222 dm['resume'] = 'PM: early restore of devices complete after.*' >> 3223 dm['resume_complete'] = 'PM: restore of devices complete after.*' >> 3224 elif(sysvals.suspendmode == 'freeze'): >> 3225 dm['resume_machine'] = 'ACPI: resume from mwait' 3998 3226 3999 # action table (expected events that 3227 # action table (expected events that occur and show up in dmesg) 4000 at = { 3228 at = { 4001 'sync_filesystems': { 3229 'sync_filesystems': { 4002 'smsg': '.*[Ff]+ilesy !! 3230 'smsg': 'PM: Syncing filesystems.*', 4003 'emsg': 'PM: Preparin !! 3231 'emsg': 'PM: Preparing system for mem sleep.*' }, 4004 'freeze_user_processes': { 3232 'freeze_user_processes': { 4005 'smsg': 'Freezing use !! 3233 'smsg': 'Freezing user space processes .*', 4006 'emsg': 'Freezing rem 3234 'emsg': 'Freezing remaining freezable tasks.*' }, 4007 'freeze_tasks': { 3235 'freeze_tasks': { 4008 'smsg': 'Freezing rem 3236 'smsg': 'Freezing remaining freezable tasks.*', 4009 'emsg': 'PM: Suspendi !! 3237 'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' }, 4010 'ACPI prepare': { 3238 'ACPI prepare': { 4011 'smsg': 'ACPI: Prepar 3239 'smsg': 'ACPI: Preparing to enter system sleep state.*', 4012 'emsg': 'PM: Saving p 3240 'emsg': 'PM: Saving platform NVS memory.*' }, 4013 'PM vns': { 3241 'PM vns': { 4014 'smsg': 'PM: Saving p 3242 'smsg': 'PM: Saving platform NVS memory.*', 4015 'emsg': 'Disabling no 3243 'emsg': 'Disabling non-boot CPUs .*' }, 4016 } 3244 } 4017 3245 4018 t0 = -1.0 3246 t0 = -1.0 4019 cpu_start = -1.0 3247 cpu_start = -1.0 4020 prevktime = -1.0 3248 prevktime = -1.0 4021 actions = dict() 3249 actions = dict() 4022 for line in data.dmesgtext: 3250 for line in data.dmesgtext: 4023 # parse each dmesg line into 3251 # parse each dmesg line into the time and message 4024 m = re.match(r'[ \t]*(\[ *)(? !! 3252 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 4025 if(m): 3253 if(m): 4026 val = m.group('ktime' 3254 val = m.group('ktime') 4027 try: 3255 try: 4028 ktime = float 3256 ktime = float(val) 4029 except: 3257 except: 4030 continue 3258 continue 4031 msg = m.group('msg') 3259 msg = m.group('msg') 4032 # initialize data sta 3260 # initialize data start to first line time 4033 if t0 < 0: 3261 if t0 < 0: 4034 data.setStart 3262 data.setStart(ktime) 4035 t0 = ktime 3263 t0 = ktime 4036 else: 3264 else: 4037 continue 3265 continue 4038 3266 4039 # check for a phase change li << 4040 phasechange = False << 4041 for p in dm: << 4042 for s in dm[p]: << 4043 if(re.match(s << 4044 phase << 4045 dm[p] << 4046 break << 4047 << 4048 # hack for determining resume 3267 # hack for determining resume_machine end for freeze 4049 if(not sysvals.usetraceevents 3268 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \ 4050 and phase == 'resume_ 3269 and phase == 'resume_machine' and \ 4051 data.initcall_debug_c !! 3270 re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4052 data.setPhase(phase, !! 3271 data.dmesg['resume_machine']['end'] = ktime 4053 phase = 'resume_noirq 3272 phase = 'resume_noirq' 4054 data.setPhase(phase, !! 3273 data.dmesg[phase]['start'] = ktime 4055 3274 4056 if phasechange: !! 3275 # suspend start 4057 if phase == 'suspend_ !! 3276 if(re.match(dm['suspend_prepare'], msg)): 4058 data.setPhase !! 3277 phase = 'suspend_prepare' 4059 data.setStart !! 3278 data.dmesg[phase]['start'] = ktime 4060 data.tKernSus !! 3279 data.setStart(ktime) 4061 elif phase == 'suspen !! 3280 data.tKernSus = ktime 4062 lp = data.las !! 3281 # suspend start 4063 if lp: !! 3282 elif(re.match(dm['suspend'], msg)): 4064 data. !! 3283 data.dmesg['suspend_prepare']['end'] = ktime 4065 data.setPhase !! 3284 phase = 'suspend' 4066 elif phase == 'suspen !! 3285 data.dmesg[phase]['start'] = ktime 4067 lp = data.las !! 3286 # suspend_late start 4068 if lp: !! 3287 elif(re.match(dm['suspend_late'], msg)): 4069 data. !! 3288 data.dmesg['suspend']['end'] = ktime 4070 data.setPhase !! 3289 phase = 'suspend_late' 4071 elif phase == 'suspen !! 3290 data.dmesg[phase]['start'] = ktime 4072 lp = data.las !! 3291 # suspend_noirq start 4073 if lp: !! 3292 elif(re.match(dm['suspend_noirq'], msg)): 4074 data. !! 3293 data.dmesg['suspend_late']['end'] = ktime 4075 data.setPhase !! 3294 phase = 'suspend_noirq' 4076 elif phase == 'suspen !! 3295 data.dmesg[phase]['start'] = ktime 4077 lp = data.las !! 3296 # suspend_machine start 4078 if lp: !! 3297 elif(re.match(dm['suspend_machine'], msg)): 4079 data. !! 3298 data.dmesg['suspend_noirq']['end'] = ktime 4080 data.setPhase !! 3299 phase = 'suspend_machine' 4081 elif phase == 'resume !! 3300 data.dmesg[phase]['start'] = ktime 4082 lp = data.las !! 3301 # resume_machine start 4083 if(sysvals.su !! 3302 elif(re.match(dm['resume_machine'], msg)): 4084 data. !! 3303 if(sysvals.suspendmode in ['freeze', 'standby']): 4085 if lp !! 3304 data.tSuspended = prevktime 4086 !! 3305 data.dmesg['suspend_machine']['end'] = prevktime 4087 else: !! 3306 else: 4088 data. !! 3307 data.tSuspended = ktime 4089 if lp !! 3308 data.dmesg['suspend_machine']['end'] = ktime 4090 !! 3309 phase = 'resume_machine' 4091 data.tResumed !! 3310 data.tResumed = ktime 4092 data.setPhase !! 3311 data.tLow = data.tResumed - data.tSuspended 4093 elif phase == 'resume !! 3312 data.dmesg[phase]['start'] = ktime 4094 lp = data.las !! 3313 # resume_noirq start 4095 if lp: !! 3314 elif(re.match(dm['resume_noirq'], msg)): 4096 data. !! 3315 data.dmesg['resume_machine']['end'] = ktime 4097 data.setPhase !! 3316 phase = 'resume_noirq' 4098 elif phase == 'resume !! 3317 data.dmesg[phase]['start'] = ktime 4099 lp = data.las !! 3318 # resume_early start 4100 if lp: !! 3319 elif(re.match(dm['resume_early'], msg)): 4101 data. !! 3320 data.dmesg['resume_noirq']['end'] = ktime 4102 data.setPhase !! 3321 phase = 'resume_early' 4103 elif phase == 'resume !! 3322 data.dmesg[phase]['start'] = ktime 4104 lp = data.las !! 3323 # resume start 4105 if lp: !! 3324 elif(re.match(dm['resume'], msg)): 4106 data. !! 3325 data.dmesg['resume_early']['end'] = ktime 4107 data.setPhase !! 3326 phase = 'resume' 4108 elif phase == 'resume !! 3327 data.dmesg[phase]['start'] = ktime 4109 lp = data.las !! 3328 # resume complete start 4110 if lp: !! 3329 elif(re.match(dm['resume_complete'], msg)): 4111 data. !! 3330 data.dmesg['resume']['end'] = ktime 4112 data.setPhase !! 3331 phase = 'resume_complete' 4113 elif phase == 'post_r !! 3332 data.dmesg[phase]['start'] = ktime 4114 lp = data.las !! 3333 # post resume start 4115 if lp: !! 3334 elif(re.match(dm['post_resume'], msg)): 4116 data. !! 3335 data.dmesg['resume_complete']['end'] = ktime 4117 data.setEnd(k !! 3336 data.setEnd(ktime) 4118 data.tKernRes !! 3337 data.tKernRes = ktime 4119 break !! 3338 break 4120 3339 4121 # -- device callbacks -- 3340 # -- device callbacks -- 4122 if(phase in data.sortedPhases !! 3341 if(phase in data.phases): 4123 # device init call 3342 # device init call 4124 t, f, n, p = data.ini !! 3343 if(re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4125 if t and f and n and !! 3344 sm = re.match('calling (?P<f>.*)\+ @ '+\ 4126 data.newActio !! 3345 '(?P<n>.*), parent: (?P<p>.*)', msg); 4127 else: !! 3346 f = sm.group('f') 4128 # device init !! 3347 n = sm.group('n') 4129 t, f, l = dat !! 3348 p = sm.group('p') 4130 if t and f an !! 3349 if(f and n and p): 4131 list !! 3350 data.newAction(phase, f, int(n), p, ktime, -1, '') 4132 if(f !! 3351 # device init return 4133 !! 3352 elif(re.match('call (?P<f>.*)\+ returned .* after '+\ 4134 !! 3353 '(?P<t>.*) usecs', msg)): 4135 !! 3354 sm = re.match('call (?P<f>.*)\+ returned .* after '+\ >> 3355 '(?P<t>.*) usecs(?P<a>.*)', msg); >> 3356 f = sm.group('f') >> 3357 t = sm.group('t') >> 3358 list = data.dmesg[phase]['list'] >> 3359 if(f in list): >> 3360 dev = list[f] >> 3361 dev['length'] = int(t) >> 3362 dev['end'] = ktime 4136 3363 4137 # if trace events are not ava 3364 # if trace events are not available, these are better than nothing 4138 if(not sysvals.usetraceevents 3365 if(not sysvals.usetraceevents): 4139 # look for known acti 3366 # look for known actions 4140 for a in sorted(at): !! 3367 for a in at: 4141 if(re.match(a 3368 if(re.match(at[a]['smsg'], msg)): 4142 if(a 3369 if(a not in actions): 4143 !! 3370 actions[a] = [] >> 3371 actions[a].append({'begin': ktime, 'end': ktime}) 4144 if(re.match(a 3372 if(re.match(at[a]['emsg'], msg)): 4145 if(a !! 3373 if(a in actions): 4146 3374 actions[a][-1]['end'] = ktime 4147 # now look for CPU on 3375 # now look for CPU on/off events 4148 if(re.match(r'Disabli !! 3376 if(re.match('Disabling non-boot CPUs .*', msg)): 4149 # start of fi 3377 # start of first cpu suspend 4150 cpu_start = k 3378 cpu_start = ktime 4151 elif(re.match(r'Enabl !! 3379 elif(re.match('Enabling non-boot CPUs .*', msg)): 4152 # start of fi 3380 # start of first cpu resume 4153 cpu_start = k 3381 cpu_start = ktime 4154 elif(re.match(r'smpbo !! 3382 elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)): 4155 or re.match(r << 4156 # end of a cp 3383 # end of a cpu suspend, start of the next 4157 m = re.match( !! 3384 m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) 4158 if(not m): << 4159 m = r << 4160 cpu = 'CPU'+m 3385 cpu = 'CPU'+m.group('cpu') 4161 if(cpu not in 3386 if(cpu not in actions): 4162 actio 3387 actions[cpu] = [] 4163 actions[cpu]. 3388 actions[cpu].append({'begin': cpu_start, 'end': ktime}) 4164 cpu_start = k 3389 cpu_start = ktime 4165 elif(re.match(r'CPU(? !! 3390 elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)): 4166 # end of a cp 3391 # end of a cpu resume, start of the next 4167 m = re.match( !! 3392 m = re.match('CPU(?P<cpu>[0-9]*) is up', msg) 4168 cpu = 'CPU'+m 3393 cpu = 'CPU'+m.group('cpu') 4169 if(cpu not in 3394 if(cpu not in actions): 4170 actio 3395 actions[cpu] = [] 4171 actions[cpu]. 3396 actions[cpu].append({'begin': cpu_start, 'end': ktime}) 4172 cpu_start = k 3397 cpu_start = ktime 4173 prevktime = ktime 3398 prevktime = ktime 4174 data.initDevicegroups() << 4175 3399 4176 # fill in any missing phases 3400 # fill in any missing phases 4177 phasedef = data.phasedef !! 3401 lp = data.phases[0] 4178 terr, lp = '', 'suspend_prepare' !! 3402 for p in data.phases: 4179 if lp not in data.dmesg: !! 3403 if(data.dmesg[p]['start'] < 0 and data.dmesg[p]['end'] < 0): 4180 doError('dmesg log format has !! 3404 print('WARNING: phase "%s" is missing, something went wrong!' % p) 4181 for p in sorted(phasedef, key=lambda !! 3405 print(' In %s, this dmesg line denotes the start of %s:' % \ 4182 if p not in data.dmesg: !! 3406 (sysvals.suspendmode, p)) 4183 if not terr: !! 3407 print(' "%s"' % dm[p]) 4184 pprint('TEST !! 3408 if(data.dmesg[p]['start'] < 0): 4185 terr = '%s fa !! 3409 data.dmesg[p]['start'] = data.dmesg[lp]['end'] 4186 if data.tSusp !! 3410 if(p == 'resume_machine'): 4187 data. !! 3411 data.tSuspended = data.dmesg[lp]['end'] 4188 if data.tResu !! 3412 data.tResumed = data.dmesg[lp]['end'] 4189 data. !! 3413 data.tLow = 0 4190 sysvals.vprint('WARNI !! 3414 if(data.dmesg[p]['end'] < 0): 4191 lp = p !! 3415 data.dmesg[p]['end'] = data.dmesg[p]['start'] 4192 lp = data.sortedPhases()[0] << 4193 for p in data.sortedPhases(): << 4194 if(p != lp and not ('machine' << 4195 data.dmesg[lp]['end'] << 4196 lp = p 3416 lp = p 4197 if data.tSuspended == 0: << 4198 data.tSuspended = data.tKernR << 4199 if data.tResumed == 0: << 4200 data.tResumed = data.tSuspend << 4201 3417 4202 # fill in any actions we've found 3418 # fill in any actions we've found 4203 for name in sorted(actions): !! 3419 for name in actions: 4204 for event in actions[name]: 3420 for event in actions[name]: 4205 data.newActionGlobal( 3421 data.newActionGlobal(name, event['begin'], event['end']) 4206 3422 4207 if(len(sysvals.devicefilter) > 0): 3423 if(len(sysvals.devicefilter) > 0): 4208 data.deviceFilter(sysvals.dev 3424 data.deviceFilter(sysvals.devicefilter) 4209 data.fixupInitcallsThatDidntReturn() 3425 data.fixupInitcallsThatDidntReturn() 4210 return True 3426 return True 4211 3427 4212 def callgraphHTML(sv, hf, num, cg, title, col 3428 def callgraphHTML(sv, hf, num, cg, title, color, devid): 4213 html_func_top = '<article id="{0}" cl 3429 html_func_top = '<article id="{0}" class="atop" style="background:{1}">\n<input type="checkbox" class="pf" id="f{2}" checked/><label for="f{2}">{3} {4}</label>\n' 4214 html_func_start = '<article>\n<input 3430 html_func_start = '<article>\n<input type="checkbox" class="pf" id="f{0}" checked/><label for="f{0}">{1} {2}</label>\n' 4215 html_func_end = '</article>\n' 3431 html_func_end = '</article>\n' 4216 html_func_leaf = '<article>{0} {1}</a 3432 html_func_leaf = '<article>{0} {1}</article>\n' 4217 3433 4218 cgid = devid 3434 cgid = devid 4219 if cg.id: 3435 if cg.id: 4220 cgid += cg.id 3436 cgid += cg.id 4221 cglen = (cg.end - cg.start) * 1000 3437 cglen = (cg.end - cg.start) * 1000 4222 if cglen < sv.mincglen: 3438 if cglen < sv.mincglen: 4223 return num 3439 return num 4224 3440 4225 fmt = '<r>(%.3f ms @ '+sv.timeformat+' 3441 fmt = '<r>(%.3f ms @ '+sv.timeformat+' to '+sv.timeformat+')</r>' 4226 flen = fmt % (cglen, cg.start, cg.end 3442 flen = fmt % (cglen, cg.start, cg.end) 4227 hf.write(html_func_top.format(cgid, c 3443 hf.write(html_func_top.format(cgid, color, num, title, flen)) 4228 num += 1 3444 num += 1 4229 for line in cg.list: 3445 for line in cg.list: 4230 if(line.length < 0.000000001) 3446 if(line.length < 0.000000001): 4231 flen = '' 3447 flen = '' 4232 else: 3448 else: 4233 fmt = '<n>(%.3f ms @ ' 3449 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>' 4234 flen = fmt % (line.le 3450 flen = fmt % (line.length*1000, line.time) 4235 if line.isLeaf(): 3451 if line.isLeaf(): 4236 if line.length * 1000 << 4237 continue << 4238 hf.write(html_func_le 3452 hf.write(html_func_leaf.format(line.name, flen)) 4239 elif line.freturn: 3453 elif line.freturn: 4240 hf.write(html_func_en 3454 hf.write(html_func_end) 4241 else: 3455 else: 4242 hf.write(html_func_st 3456 hf.write(html_func_start.format(num, line.name, flen)) 4243 num += 1 3457 num += 1 4244 hf.write(html_func_end) 3458 hf.write(html_func_end) 4245 return num 3459 return num 4246 3460 4247 def addCallgraphs(sv, hf, data): 3461 def addCallgraphs(sv, hf, data): 4248 hf.write('<section id="callgraphs" cl 3462 hf.write('<section id="callgraphs" class="callgraph">\n') 4249 # write out the ftrace data converted 3463 # write out the ftrace data converted to html 4250 num = 0 3464 num = 0 4251 for p in data.sortedPhases(): !! 3465 for p in data.phases: 4252 if sv.cgphase and p != sv.cgp 3466 if sv.cgphase and p != sv.cgphase: 4253 continue 3467 continue 4254 list = data.dmesg[p]['list'] 3468 list = data.dmesg[p]['list'] 4255 for d in data.sortedDevices(p !! 3469 for devname in data.sortedDevices(p): 4256 if len(sv.cgfilter) > !! 3470 if len(sv.cgfilter) > 0 and devname not in sv.cgfilter: 4257 continue 3471 continue 4258 dev = list[d] !! 3472 dev = list[devname] 4259 color = 'white' 3473 color = 'white' 4260 if 'color' in data.dm 3474 if 'color' in data.dmesg[p]: 4261 color = data. 3475 color = data.dmesg[p]['color'] 4262 if 'color' in dev: 3476 if 'color' in dev: 4263 color = dev[' 3477 color = dev['color'] 4264 name = d if '[' not i !! 3478 name = devname 4265 if(d in sv.devprops): !! 3479 if(devname in sv.devprops): 4266 name = sv.dev !! 3480 name = sv.devprops[devname].altName(devname) 4267 if 'drv' in dev and d << 4268 name += ' {%s << 4269 if sv.suspendmode in 3481 if sv.suspendmode in suspendmodename: 4270 name += ' '+p 3482 name += ' '+p 4271 if('ftrace' in dev): 3483 if('ftrace' in dev): 4272 cg = dev['ftr 3484 cg = dev['ftrace'] 4273 if cg.name == << 4274 name << 4275 num = callgra 3485 num = callgraphHTML(sv, hf, num, cg, 4276 name, 3486 name, color, dev['id']) 4277 if('ftraces' in dev): 3487 if('ftraces' in dev): 4278 for cg in dev 3488 for cg in dev['ftraces']: 4279 num = 3489 num = callgraphHTML(sv, hf, num, cg, 4280 3490 name+' → '+cg.name, color, dev['id']) 4281 hf.write('\n\n </section>\n') 3491 hf.write('\n\n </section>\n') 4282 3492 4283 def summaryCSS(title, center=True): !! 3493 # Function: createHTMLSummarySimple 4284 tdcenter = 'text-align:center;' if ce !! 3494 # Description: 4285 out = '<!DOCTYPE html>\n<html>\n<head !! 3495 # Create summary html file for a series of tests >> 3496 # Arguments: >> 3497 # testruns: array of Data objects from parseTraceLog >> 3498 def createHTMLSummarySimple(testruns, htmlfile, folder): >> 3499 # write the html header first (html head, css code, up to body start) >> 3500 html = '<!DOCTYPE html>\n<html>\n<head>\n\ 4286 <meta http-equiv="content-type" conte 3501 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 4287 <title>'+title+'</title>\n\ !! 3502 <title>SleepGraph Summary</title>\n\ 4288 <style type=\'text/css\'>\n\ 3503 <style type=\'text/css\'>\n\ 4289 .stamp {width: 100%;text-alig 3504 .stamp {width: 100%;text-align:center;background:#888;line-height:30px;color:white;font: 25px Arial;}\n\ 4290 table {width:100%;border-coll !! 3505 table {width:100%;border-collapse: collapse;}\n\ >> 3506 .summary {border:1px solid;}\n\ 4291 th {border: 1px solid black;b 3507 th {border: 1px solid black;background:#222;color:white;}\n\ 4292 td {font: 14px "Times New Rom !! 3508 td {font: 16px "Times New Roman";text-align: center;}\n\ 4293 tr.head td {border: 1px solid 3509 tr.head td {border: 1px solid black;background:#aaa;}\n\ 4294 tr.alt {background-color:#ddd 3510 tr.alt {background-color:#ddd;}\n\ 4295 tr.notice {color:red;}\n\ 3511 tr.notice {color:red;}\n\ 4296 .minval {background-color:#BB 3512 .minval {background-color:#BBFFBB;}\n\ 4297 .medval {background-color:#BB 3513 .medval {background-color:#BBBBFF;}\n\ 4298 .maxval {background-color:#FF 3514 .maxval {background-color:#FFBBBB;}\n\ 4299 .head a {color:#000;text-deco 3515 .head a {color:#000;text-decoration: none;}\n\ 4300 </style>\n</head>\n<body>\n' 3516 </style>\n</head>\n<body>\n' 4301 return out << 4302 << 4303 # Function: createHTMLSummarySimple << 4304 # Description: << 4305 # Create summary html file for a serie << 4306 # Arguments: << 4307 # testruns: array of Data objects from << 4308 def createHTMLSummarySimple(testruns, htmlfil << 4309 # write the html header first (html h << 4310 html = summaryCSS('Summary - SleepGra << 4311 3517 4312 # extract the test data into list 3518 # extract the test data into list 4313 list = dict() 3519 list = dict() 4314 tAvg, tMin, tMax, tMed = [0.0, 0.0], !! 3520 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []] 4315 iMin, iMed, iMax = [0, 0], [0, 0], [0 3521 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0] 4316 num = 0 3522 num = 0 4317 useturbo = usewifi = False << 4318 lastmode = '' 3523 lastmode = '' 4319 cnt = dict() !! 3524 cnt = {'pass':0, 'fail':0, 'hang':0} 4320 for data in sorted(testruns, key=lamb 3525 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])): 4321 mode = data['mode'] 3526 mode = data['mode'] 4322 if mode not in list: 3527 if mode not in list: 4323 list[mode] = {'data': 3528 list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]} 4324 if lastmode and lastmode != m 3529 if lastmode and lastmode != mode and num > 0: 4325 for i in range(2): 3530 for i in range(2): 4326 s = sorted(tM 3531 s = sorted(tMed[i]) 4327 list[lastmode !! 3532 list[lastmode]['med'][i] = s[int(len(s)/2)] 4328 iMed[i] = tMe !! 3533 iMed[i] = tMed[i].index(list[lastmode]['med'][i]) 4329 list[lastmode]['avg'] 3534 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 4330 list[lastmode]['min'] 3535 list[lastmode]['min'] = tMin 4331 list[lastmode]['max'] 3536 list[lastmode]['max'] = tMax 4332 list[lastmode]['idx'] 3537 list[lastmode]['idx'] = (iMin, iMed, iMax) 4333 tAvg, tMin, tMax, tMe !! 3538 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []] 4334 iMin, iMed, iMax = [0 3539 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0] 4335 num = 0 3540 num = 0 4336 pkgpc10 = syslpi = wifi = '' << 4337 if 'pkgpc10' in data and 'sys << 4338 pkgpc10, syslpi, uset << 4339 if 'wifi' in data: << 4340 wifi, usewifi = data[ << 4341 res = data['result'] << 4342 tVal = [float(data['suspend'] 3541 tVal = [float(data['suspend']), float(data['resume'])] 4343 list[mode]['data'].append([da 3542 list[mode]['data'].append([data['host'], data['kernel'], 4344 data['time'], tVal[0] !! 3543 data['time'], tVal[0], tVal[1], data['url'], data['result'], 4345 data['issues'], data[ !! 3544 data['issues']]) 4346 data['res_worst'], da << 4347 (data['fullmode'] if << 4348 idx = len(list[mode]['data']) 3545 idx = len(list[mode]['data']) - 1 4349 if res.startswith('fail in'): !! 3546 if data['result'] == 'pass': 4350 res = 'fail' !! 3547 cnt['pass'] += 1 4351 if res not in cnt: << 4352 cnt[res] = 1 << 4353 else: << 4354 cnt[res] += 1 << 4355 if res == 'pass': << 4356 for i in range(2): 3548 for i in range(2): 4357 tMed[i][tVal[ !! 3549 tMed[i].append(tVal[i]) 4358 tAvg[i] += tV 3550 tAvg[i] += tVal[i] 4359 if tMin[i] == 3551 if tMin[i] == 0 or tVal[i] < tMin[i]: 4360 iMin[ 3552 iMin[i] = idx 4361 tMin[ 3553 tMin[i] = tVal[i] 4362 if tMax[i] == 3554 if tMax[i] == 0 or tVal[i] > tMax[i]: 4363 iMax[ 3555 iMax[i] = idx 4364 tMax[ 3556 tMax[i] = tVal[i] 4365 num += 1 3557 num += 1 >> 3558 elif data['result'] == 'hang': >> 3559 cnt['hang'] += 1 >> 3560 elif data['result'] == 'fail': >> 3561 cnt['fail'] += 1 4366 lastmode = mode 3562 lastmode = mode 4367 if lastmode and num > 0: 3563 if lastmode and num > 0: 4368 for i in range(2): 3564 for i in range(2): 4369 s = sorted(tMed[i]) 3565 s = sorted(tMed[i]) 4370 list[lastmode]['med'] !! 3566 list[lastmode]['med'][i] = s[int(len(s)/2)] 4371 iMed[i] = tMed[i][lis !! 3567 iMed[i] = tMed[i].index(list[lastmode]['med'][i]) 4372 list[lastmode]['avg'] = [tAvg 3568 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 4373 list[lastmode]['min'] = tMin 3569 list[lastmode]['min'] = tMin 4374 list[lastmode]['max'] = tMax 3570 list[lastmode]['max'] = tMax 4375 list[lastmode]['idx'] = (iMin 3571 list[lastmode]['idx'] = (iMin, iMed, iMax) 4376 3572 4377 # group test header 3573 # group test header 4378 desc = [] 3574 desc = [] 4379 for ilk in sorted(cnt, reverse=True): 3575 for ilk in sorted(cnt, reverse=True): 4380 if cnt[ilk] > 0: 3576 if cnt[ilk] > 0: 4381 desc.append('%d %s' % 3577 desc.append('%d %s' % (cnt[ilk], ilk)) 4382 html += '<div class="stamp">%s (%d te !! 3578 html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (folder, len(testruns), ', '.join(desc)) 4383 th = '\t<th>{0}</th>\n' 3579 th = '\t<th>{0}</th>\n' 4384 td = '\t<td>{0}</td>\n' 3580 td = '\t<td>{0}</td>\n' 4385 tdh = '\t<td{1}>{0}</td>\n' 3581 tdh = '\t<td{1}>{0}</td>\n' 4386 tdlink = '\t<td><a href="{0}">html</a 3582 tdlink = '\t<td><a href="{0}">html</a></td>\n' 4387 cols = 12 << 4388 if useturbo: << 4389 cols += 2 << 4390 if usewifi: << 4391 cols += 1 << 4392 colspan = '%d' % cols << 4393 3583 4394 # table header 3584 # table header 4395 html += '<table>\n<tr>\n' + th.format !! 3585 html += '<table class="summary">\n<tr>\n' + th.format('#') +\ 4396 th.format('Mode') + th.format 3586 th.format('Mode') + th.format('Host') + th.format('Kernel') +\ 4397 th.format('Test Time') + th.f 3587 th.format('Test Time') + th.format('Result') + th.format('Issues') +\ 4398 th.format('Suspend') + th.for !! 3588 th.format('Suspend') + th.format('Resume') + th.format('Detail') + '</tr>\n' 4399 th.format('Worst Suspend Devi !! 3589 4400 th.format('Worst Resume Devic << 4401 if useturbo: << 4402 html += th.format('PkgPC10') << 4403 if usewifi: << 4404 html += th.format('Wifi') << 4405 html += th.format('Detail')+'</tr>\n' << 4406 # export list into html 3590 # export list into html 4407 head = '<tr class="head"><td>{0}</td> 3591 head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\ 4408 '<td colspan='+colspan+' clas !! 3592 '<td colspan=8 class="sus">Suspend Avg={2} '+\ 4409 '<span class=minval><a href=" 3593 '<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\ 4410 '<span class=medval><a href=" 3594 '<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\ 4411 '<span class=maxval><a href=" 3595 '<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\ 4412 'Resume Avg={6} '+\ 3596 'Resume Avg={6} '+\ 4413 '<span class=minval><a href=" 3597 '<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\ 4414 '<span class=medval><a href=" 3598 '<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\ 4415 '<span class=maxval><a href=" 3599 '<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\ 4416 '</tr>\n' 3600 '</tr>\n' 4417 headnone = '<tr class="head"><td>{0}< !! 3601 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan=8></td></tr>\n' 4418 colspan+'></td></tr>\n' !! 3602 for mode in list: 4419 for mode in sorted(list): << 4420 # header line for each suspen 3603 # header line for each suspend mode 4421 num = 0 3604 num = 0 4422 tAvg, tMin, tMax, tMed = list 3605 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\ 4423 list[mode]['max'], li 3606 list[mode]['max'], list[mode]['med'] 4424 count = len(list[mode]['data' 3607 count = len(list[mode]['data']) 4425 if 'idx' in list[mode]: 3608 if 'idx' in list[mode]: 4426 iMin, iMed, iMax = li 3609 iMin, iMed, iMax = list[mode]['idx'] 4427 html += head.format(' 3610 html += head.format('%d' % count, mode.upper(), 4428 '%.3f' % tAvg 3611 '%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0], 4429 '%.3f' % tAvg 3612 '%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1], 4430 mode.lower() 3613 mode.lower() 4431 ) 3614 ) 4432 else: 3615 else: 4433 iMin = iMed = iMax = 3616 iMin = iMed = iMax = [-1, -1, -1] 4434 html += headnone.form 3617 html += headnone.format('%d' % count, mode.upper()) 4435 for d in list[mode]['data']: 3618 for d in list[mode]['data']: 4436 # row classes - alter 3619 # row classes - alternate row color 4437 rcls = ['alt'] if num 3620 rcls = ['alt'] if num % 2 == 1 else [] 4438 if d[6] != 'pass': 3621 if d[6] != 'pass': 4439 rcls.append(' 3622 rcls.append('notice') 4440 html += '<tr class="' 3623 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n' 4441 # figure out if the l 3624 # figure out if the line has sus or res highlighted 4442 idx = list[mode]['dat 3625 idx = list[mode]['data'].index(d) 4443 tHigh = ['', ''] 3626 tHigh = ['', ''] 4444 for i in range(2): 3627 for i in range(2): 4445 tag = 's%s' % 3628 tag = 's%s' % mode if i == 0 else 'r%s' % mode 4446 if idx == iMi 3629 if idx == iMin[i]: 4447 tHigh 3630 tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag 4448 elif idx == i 3631 elif idx == iMax[i]: 4449 tHigh 3632 tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag 4450 elif idx == i 3633 elif idx == iMed[i]: 4451 tHigh 3634 tHigh[i] = ' id="%smed" class=medval title="Median"' % tag 4452 html += td.format("%d 3635 html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row 4453 html += td.format(d[1 !! 3636 html += td.format(mode) # mode 4454 html += td.format(d[0 3637 html += td.format(d[0]) # host 4455 html += td.format(d[1 3638 html += td.format(d[1]) # kernel 4456 html += td.format(d[2 3639 html += td.format(d[2]) # time 4457 html += td.format(d[6 3640 html += td.format(d[6]) # result 4458 html += td.format(d[7 3641 html += td.format(d[7]) # issues 4459 html += tdh.format('% 3642 html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('') # suspend 4460 html += tdh.format('% 3643 html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('') # resume 4461 html += td.format(d[8 << 4462 html += td.format('%. << 4463 html += td.format(d[1 << 4464 html += td.format('%. << 4465 if useturbo: << 4466 html += td.fo << 4467 html += td.fo << 4468 if usewifi: << 4469 html += td.fo << 4470 html += tdlink.format 3644 html += tdlink.format(d[5]) if d[5] else td.format('') # url 4471 html += '</tr>\n' 3645 html += '</tr>\n' 4472 num += 1 3646 num += 1 4473 3647 4474 # flush the data to file 3648 # flush the data to file 4475 hf = open(htmlfile, 'w') 3649 hf = open(htmlfile, 'w') 4476 hf.write(html+'</table>\n</body>\n</h 3650 hf.write(html+'</table>\n</body>\n</html>\n') 4477 hf.close() 3651 hf.close() 4478 3652 4479 def createHTMLDeviceSummary(testruns, htmlfil << 4480 html = summaryCSS('Device Summary - S << 4481 << 4482 # create global device list from all << 4483 devall = dict() << 4484 for data in testruns: << 4485 host, url, devlist = data['ho << 4486 for type in devlist: << 4487 if type not in devall << 4488 devall[type] << 4489 mdevlist, devlist = d << 4490 for name in devlist: << 4491 length = devl << 4492 if name not i << 4493 mdevl << 4494 << 4495 << 4496 else: << 4497 if le << 4498 << 4499 << 4500 << 4501 mdevl << 4502 mdevl << 4503 << 4504 # generate the html << 4505 th = '\t<th>{0}</th>\n' << 4506 td = '\t<td align=center>{0}</td>\n' << 4507 tdr = '\t<td align=right>{0}</td>\n' << 4508 tdlink = '\t<td align=center><a href= << 4509 limit = 1 << 4510 for type in sorted(devall, reverse=Tr << 4511 num = 0 << 4512 devlist = devall[type] << 4513 # table header << 4514 html += '<div class="stamp">% << 4515 (title, type.upper(), << 4516 html += '<tr>\n' + '<th align << 4517 th.format('Average Ti << 4518 th.format('Worst Time << 4519 th.format('Link (wors << 4520 for name in sorted(devlist, k << 4521 devlist[k]['total'], << 4522 data = devall[type][n << 4523 data['average'] = dat << 4524 if data['average'] < << 4525 continue << 4526 # row classes - alter << 4527 rcls = ['alt'] if num << 4528 html += '<tr class="' << 4529 html += tdr.format(da << 4530 html += td.format('%. << 4531 html += td.format(dat << 4532 html += td.format('%. << 4533 html += td.format(dat << 4534 html += tdlink.format << 4535 html += '</tr>\n' << 4536 num += 1 << 4537 html += '</table>\n' << 4538 << 4539 # flush the data to file << 4540 hf = open(htmlfile, 'w') << 4541 hf.write(html+'</body>\n</html>\n') << 4542 hf.close() << 4543 return devall << 4544 << 4545 def createHTMLIssuesSummary(testruns, issues, << 4546 multihost = len([e for e in issues if << 4547 html = summaryCSS('Issues Summary - S << 4548 total = len(testruns) << 4549 << 4550 # generate the html << 4551 th = '\t<th>{0}</th>\n' << 4552 td = '\t<td align={0}>{1}</td>\n' << 4553 tdlink = '<a href="{1}">{0}</a>' << 4554 subtitle = '%d issues' % len(issues) << 4555 html += '<div class="stamp">%s (%s)</ << 4556 html += '<tr>\n' + th.format('Issue') << 4557 if multihost: << 4558 html += th.format('Hosts') << 4559 html += th.format('Tests') + th.forma << 4560 th.format('First Instance') + << 4561 << 4562 num = 0 << 4563 for e in sorted(issues, key=lambda v: << 4564 testtotal = 0 << 4565 links = [] << 4566 for host in sorted(e['urls']) << 4567 links.append(tdlink.f << 4568 testtotal += len(e['u << 4569 rate = '%d/%d (%.2f%%)' % (te << 4570 # row classes - alternate row << 4571 rcls = ['alt'] if num % 2 == << 4572 html += '<tr class="'+(' '.jo << 4573 html += td.format('left', e[' << 4574 html += td.format('center', e << 4575 if multihost: << 4576 html += td.format('ce << 4577 html += td.format('center', t << 4578 html += td.format('center', r << 4579 html += td.format('center now << 4580 html += '</tr>\n' << 4581 num += 1 << 4582 << 4583 # flush the data to file << 4584 hf = open(htmlfile, 'w') << 4585 hf.write(html+'</table>\n'+extra+'</b << 4586 hf.close() << 4587 return issues << 4588 << 4589 def ordinal(value): 3653 def ordinal(value): 4590 suffix = 'th' 3654 suffix = 'th' 4591 if value < 10 or value > 19: 3655 if value < 10 or value > 19: 4592 if value % 10 == 1: 3656 if value % 10 == 1: 4593 suffix = 'st' 3657 suffix = 'st' 4594 elif value % 10 == 2: 3658 elif value % 10 == 2: 4595 suffix = 'nd' 3659 suffix = 'nd' 4596 elif value % 10 == 3: 3660 elif value % 10 == 3: 4597 suffix = 'rd' 3661 suffix = 'rd' 4598 return '%d%s' % (value, suffix) 3662 return '%d%s' % (value, suffix) 4599 3663 4600 # Function: createHTML 3664 # Function: createHTML 4601 # Description: 3665 # Description: 4602 # Create the output html file from the 3666 # Create the output html file from the resident test data 4603 # Arguments: 3667 # Arguments: 4604 # testruns: array of Data objects from 3668 # testruns: array of Data objects from parseKernelLog or parseTraceLog 4605 # Output: 3669 # Output: 4606 # True if the html file was created, f 3670 # True if the html file was created, false if it failed 4607 def createHTML(testruns, testfail): 3671 def createHTML(testruns, testfail): 4608 if len(testruns) < 1: 3672 if len(testruns) < 1: 4609 pprint('ERROR: Not enough tes !! 3673 print('ERROR: Not enough test data to build a timeline') 4610 return 3674 return 4611 3675 4612 kerror = False 3676 kerror = False 4613 for data in testruns: 3677 for data in testruns: 4614 if data.kerror: 3678 if data.kerror: 4615 kerror = True 3679 kerror = True 4616 if(sysvals.suspendmode in ['f !! 3680 data.normalizeTime(testruns[-1].tSuspended) 4617 data.trimFreezeTime(t << 4618 else: << 4619 data.getMemTime() << 4620 3681 4621 # html function templates 3682 # html function templates 4622 html_error = '<div id="{1}" title="ke 3683 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}→</div>\n' 4623 html_traceevent = '<div title="{0}" c 3684 html_traceevent = '<div title="{0}" class="traceevent{6}" style="left:{1}%;top:{2}px;height:{3}px;width:{4}%;line-height:{3}px;{7}">{5}</div>\n' 4624 html_cpuexec = '<div class="jiffie" s 3685 html_cpuexec = '<div class="jiffie" style="left:{0}%;top:{1}px;height:{2}px;width:{3}%;background:{4};"></div>\n' 4625 html_timetotal = '<table class="time1 3686 html_timetotal = '<table class="time1">\n<tr>'\ 4626 '<td class="green" title="{3} 3687 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\ 4627 '<td class="yellow" title="{4 3688 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\ 4628 '</tr>\n</table>\n' 3689 '</tr>\n</table>\n' 4629 html_timetotal2 = '<table class="time 3690 html_timetotal2 = '<table class="time1">\n<tr>'\ 4630 '<td class="green" title="{4} 3691 '<td class="green" title="{4}">{3} Suspend Time: <b>{0} ms</b></td>'\ 4631 '<td class="gray" title="time 3692 '<td class="gray" title="time spent in low-power mode with clock running">'+sysvals.suspendmode+' time: <b>{1} ms</b></td>'\ 4632 '<td class="yellow" title="{5 3693 '<td class="yellow" title="{5}">{3} Resume Time: <b>{2} ms</b></td>'\ 4633 '</tr>\n</table>\n' 3694 '</tr>\n</table>\n' 4634 html_timetotal3 = '<table class="time 3695 html_timetotal3 = '<table class="time1">\n<tr>'\ 4635 '<td class="green">Execution 3696 '<td class="green">Execution Time: <b>{0} ms</b></td>'\ 4636 '<td class="yellow">Command: 3697 '<td class="yellow">Command: <b>{1}</b></td>'\ 4637 '</tr>\n</table>\n' 3698 '</tr>\n</table>\n' >> 3699 html_timegroups = '<table class="time2">\n<tr>'\ >> 3700 '<td class="green" title="time from kernel enter_state({5}) to firmware mode [kernel time only]">{4}Kernel Suspend: {0} ms</td>'\ >> 3701 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\ >> 3702 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\ >> 3703 '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\ >> 3704 '</tr>\n</table>\n' 4638 html_fail = '<table class="testfail"> 3705 html_fail = '<table class="testfail"><tr><td>{0}</td></tr></table>\n' 4639 html_kdesc = '<td class="{3}" title=" << 4640 html_fwdesc = '<td class="{3}" title= << 4641 html_wifdesc = '<td class="yellow" ti << 4642 3706 4643 # html format variables 3707 # html format variables 4644 scaleH = 20 3708 scaleH = 20 4645 if kerror: 3709 if kerror: 4646 scaleH = 40 3710 scaleH = 40 4647 3711 4648 # device timeline 3712 # device timeline 4649 devtl = Timeline(30, scaleH) 3713 devtl = Timeline(30, scaleH) 4650 3714 4651 # write the test title and general in 3715 # write the test title and general info header 4652 devtl.createHeader(sysvals, testruns[ 3716 devtl.createHeader(sysvals, testruns[0].stamp) 4653 3717 4654 # Generate the header for this timeli 3718 # Generate the header for this timeline 4655 for data in testruns: 3719 for data in testruns: 4656 tTotal = data.end - data.star 3720 tTotal = data.end - data.start >> 3721 sktime, rktime = data.getTimeValues() 4657 if(tTotal == 0): 3722 if(tTotal == 0): 4658 doError('No timeline 3723 doError('No timeline data') >> 3724 if(data.tLow > 0): >> 3725 low_time = '%.0f'%(data.tLow*1000) 4659 if sysvals.suspendmode == 'co 3726 if sysvals.suspendmode == 'command': 4660 run_time = '%.0f' % ( !! 3727 run_time = '%.0f'%((data.end-data.start)*1000) 4661 if sysvals.testcomman 3728 if sysvals.testcommand: 4662 testdesc = sy 3729 testdesc = sysvals.testcommand 4663 else: 3730 else: 4664 testdesc = 'u 3731 testdesc = 'unknown' 4665 if(len(testruns) > 1) 3732 if(len(testruns) > 1): 4666 testdesc = or 3733 testdesc = ordinal(data.testnumber+1)+' '+testdesc 4667 thtml = html_timetota 3734 thtml = html_timetotal3.format(run_time, testdesc) 4668 devtl.html += thtml 3735 devtl.html += thtml 4669 continue !! 3736 elif data.fwValid: 4670 # typical full suspend/resume !! 3737 suspend_time = '%.0f'%(sktime + (data.fwSuspend/1000000.0)) 4671 stot, rtot = sktime, rktime = !! 3738 resume_time = '%.0f'%(rktime + (data.fwResume/1000000.0)) 4672 ssrc, rsrc, testdesc, testdes !! 3739 testdesc1 = 'Total' 4673 if data.fwValid: !! 3740 testdesc2 = '' 4674 stot += (data.fwSuspe !! 3741 stitle = 'time from kernel enter_state(%s) to low-power mode [kernel & firmware time]' % sysvals.suspendmode 4675 rtot += (data.fwResum !! 3742 rtitle = 'time from low-power mode to return from kernel enter_state(%s) [firmware & kernel time]' % sysvals.suspendmode 4676 ssrc.append('firmware !! 3743 if(len(testruns) > 1): 4677 rsrc.append('firmware !! 3744 testdesc1 = testdesc2 = ordinal(data.testnumber+1) 4678 testdesc = 'Total' !! 3745 testdesc2 += ' ' 4679 if 'time' in data.wifi and da !! 3746 if(data.tLow == 0): 4680 rtot += data.end - da !! 3747 thtml = html_timetotal.format(suspend_time, \ 4681 rsrc.append('wifi') !! 3748 resume_time, testdesc1, stitle, rtitle) 4682 testdesc = 'Total' !! 3749 else: 4683 suspend_time, resume_time = ' !! 3750 thtml = html_timetotal2.format(suspend_time, low_time, \ 4684 stitle = 'time from kernel su !! 3751 resume_time, testdesc1, stitle, rtitle) 4685 (sysvals.suspendmode, !! 3752 devtl.html += thtml 4686 rtitle = 'time from %s mode t << 4687 (sysvals.suspendmode, << 4688 if(len(testruns) > 1): << 4689 testdesc = testdesc2 << 4690 testdesc2 += ' ' << 4691 if(len(data.tLow) == 0): << 4692 thtml = html_timetota << 4693 resume_time, << 4694 else: << 4695 low_time = '+'.join(d << 4696 thtml = html_timetota << 4697 resume_time, << 4698 devtl.html += thtml << 4699 if not data.fwValid and 'dev' << 4700 continue << 4701 # extra detail when the times << 4702 thtml = '<table class="time2" << 4703 thtml += html_kdesc.format(te << 4704 if data.fwValid: << 4705 sftime = '%.3f'%(data 3753 sftime = '%.3f'%(data.fwSuspend / 1000000.0) 4706 rftime = '%.3f'%(data 3754 rftime = '%.3f'%(data.fwResume / 1000000.0) 4707 thtml += html_fwdesc. !! 3755 devtl.html += html_timegroups.format('%.3f'%sktime, \ 4708 thtml += html_fwdesc. !! 3756 sftime, rftime, '%.3f'%rktime, testdesc2, sysvals.suspendmode) 4709 thtml += html_kdesc.format(te !! 3757 else: 4710 if 'time' in data.wifi: !! 3758 suspend_time = '%.3f' % sktime 4711 if data.wifi['stat'] !! 3759 resume_time = '%.3f' % rktime 4712 wtime = '%.0f !! 3760 testdesc = 'Kernel' >> 3761 stitle = 'time from kernel enter_state(%s) to firmware mode [kernel time only]' % sysvals.suspendmode >> 3762 rtitle = 'time from firmware mode to return from kernel enter_state(%s) [kernel time only]' % sysvals.suspendmode >> 3763 if(len(testruns) > 1): >> 3764 testdesc = ordinal(data.testnumber+1)+' '+testdesc >> 3765 if(data.tLow == 0): >> 3766 thtml = html_timetotal.format(suspend_time, \ >> 3767 resume_time, testdesc, stitle, rtitle) 4713 else: 3768 else: 4714 wtime = 'TIME !! 3769 thtml = html_timetotal2.format(suspend_time, low_time, \ 4715 thtml += html_wifdesc !! 3770 resume_time, testdesc, stitle, rtitle) 4716 thtml += '</tr>\n</table>\n' !! 3771 devtl.html += thtml 4717 devtl.html += thtml !! 3772 4718 if testfail: 3773 if testfail: 4719 devtl.html += html_fail.forma 3774 devtl.html += html_fail.format(testfail) 4720 3775 4721 # time scale for potentially multiple 3776 # time scale for potentially multiple datasets 4722 t0 = testruns[0].start 3777 t0 = testruns[0].start 4723 tMax = testruns[-1].end 3778 tMax = testruns[-1].end 4724 tTotal = tMax - t0 3779 tTotal = tMax - t0 4725 3780 4726 # determine the maximum number of row 3781 # determine the maximum number of rows we need to draw 4727 fulllist = [] 3782 fulllist = [] 4728 threadlist = [] 3783 threadlist = [] 4729 pscnt = 0 3784 pscnt = 0 4730 devcnt = 0 3785 devcnt = 0 4731 for data in testruns: 3786 for data in testruns: 4732 data.selectTimelineDevices('% 3787 data.selectTimelineDevices('%f', tTotal, sysvals.mindevlen) 4733 for group in data.devicegroup 3788 for group in data.devicegroups: 4734 devlist = [] 3789 devlist = [] 4735 for phase in group: 3790 for phase in group: 4736 for devname i !! 3791 for devname in data.tdevlist[phase]: 4737 d = D 3792 d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname]) 4738 devli 3793 devlist.append(d) 4739 if d. 3794 if d.isa('kth'): 4740 3795 threadlist.append(d) 4741 else: 3796 else: 4742 3797 if d.isa('ps'): 4743 3798 pscnt += 1 4744 3799 else: 4745 3800 devcnt += 1 4746 3801 fulllist.append(d) 4747 if sysvals.mixedphase 3802 if sysvals.mixedphaseheight: 4748 devtl.getPhas 3803 devtl.getPhaseRows(devlist) 4749 if not sysvals.mixedphaseheight: 3804 if not sysvals.mixedphaseheight: 4750 if len(threadlist) > 0 and le 3805 if len(threadlist) > 0 and len(fulllist) > 0: 4751 if pscnt > 0 and devc 3806 if pscnt > 0 and devcnt > 0: 4752 msg = 'user p 3807 msg = 'user processes & device pm callbacks' 4753 elif pscnt > 0: 3808 elif pscnt > 0: 4754 msg = 'user p 3809 msg = 'user processes' 4755 else: 3810 else: 4756 msg = 'device 3811 msg = 'device pm callbacks' 4757 d = testruns[0].addHo 3812 d = testruns[0].addHorizontalDivider(msg, testruns[-1].end) 4758 fulllist.insert(0, d) 3813 fulllist.insert(0, d) 4759 devtl.getPhaseRows(fulllist) 3814 devtl.getPhaseRows(fulllist) 4760 if len(threadlist) > 0: 3815 if len(threadlist) > 0: 4761 d = testruns[0].addHo 3816 d = testruns[0].addHorizontalDivider('asynchronous kernel threads', testruns[-1].end) 4762 threadlist.insert(0, 3817 threadlist.insert(0, d) 4763 devtl.getPhaseRows(th 3818 devtl.getPhaseRows(threadlist, devtl.rows) 4764 devtl.calcTotalRows() 3819 devtl.calcTotalRows() 4765 3820 4766 # draw the full timeline 3821 # draw the full timeline 4767 devtl.createZoomBox(sysvals.suspendmo 3822 devtl.createZoomBox(sysvals.suspendmode, len(testruns)) >> 3823 phases = {'suspend':[],'resume':[]} >> 3824 for phase in data.dmesg: >> 3825 if 'resume' in phase: >> 3826 phases['resume'].append(phase) >> 3827 else: >> 3828 phases['suspend'].append(phase) >> 3829 >> 3830 # draw each test run chronologically 4768 for data in testruns: 3831 for data in testruns: 4769 # draw each test run and bloc << 4770 phases = {'suspend':[],'resum << 4771 for phase in data.sortedPhase << 4772 if data.dmesg[phase][ << 4773 phases['resum << 4774 else: << 4775 phases['suspe << 4776 # now draw the actual timelin 3832 # now draw the actual timeline blocks 4777 for dir in phases: 3833 for dir in phases: 4778 # draw suspend and re 3834 # draw suspend and resume blocks separately 4779 bname = '%s%d' % (dir 3835 bname = '%s%d' % (dir[0], data.testnumber) 4780 if dir == 'suspend': 3836 if dir == 'suspend': 4781 m0 = data.sta 3837 m0 = data.start 4782 mMax = data.t 3838 mMax = data.tSuspended 4783 left = '%f' % 3839 left = '%f' % (((m0-t0)*100.0)/tTotal) 4784 else: 3840 else: 4785 m0 = data.tSu 3841 m0 = data.tSuspended 4786 mMax = data.e 3842 mMax = data.end 4787 # in an x2 ru 3843 # in an x2 run, remove any gap between blocks 4788 if len(testru 3844 if len(testruns) > 1 and data.testnumber == 0: 4789 mMax 3845 mMax = testruns[1].start 4790 left = '%f' % 3846 left = '%f' % ((((m0-t0)*100.0)+sysvals.srgap/2)/tTotal) 4791 mTotal = mMax - m0 3847 mTotal = mMax - m0 4792 # if a timeline block 3848 # if a timeline block is 0 length, skip altogether 4793 if mTotal == 0: 3849 if mTotal == 0: 4794 continue 3850 continue 4795 width = '%f' % (((mTo 3851 width = '%f' % (((mTotal*100.0)-sysvals.srgap/2)/tTotal) 4796 devtl.html += devtl.h 3852 devtl.html += devtl.html_tblock.format(bname, left, width, devtl.scaleH) 4797 for b in phases[dir]: !! 3853 for b in sorted(phases[dir]): 4798 # draw the ph 3854 # draw the phase color background 4799 phase = data. 3855 phase = data.dmesg[b] 4800 length = phas 3856 length = phase['end']-phase['start'] 4801 left = '%f' % 3857 left = '%f' % (((phase['start']-m0)*100.0)/mTotal) 4802 width = '%f' 3858 width = '%f' % ((length*100.0)/mTotal) 4803 devtl.html += 3859 devtl.html += devtl.html_phase.format(left, width, \ 4804 '%.3f 3860 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \ 4805 data. 3861 data.dmesg[b]['color'], '') 4806 for e in data.errorin 3862 for e in data.errorinfo[dir]: 4807 # draw red li 3863 # draw red lines for any kernel errors found 4808 type, t, idx1 3864 type, t, idx1, idx2 = e 4809 id = '%d_%d' 3865 id = '%d_%d' % (idx1, idx2) 4810 right = '%f' 3866 right = '%f' % (((mMax-t)*100.0)/mTotal) 4811 devtl.html += 3867 devtl.html += html_error.format(right, id, type) 4812 for b in phases[dir]: !! 3868 for b in sorted(phases[dir]): 4813 # draw the de 3869 # draw the devices for this phase 4814 phaselist = d 3870 phaselist = data.dmesg[b]['list'] 4815 for d in sort !! 3871 for d in data.tdevlist[b]: 4816 dname !! 3872 name = d 4817 name, !! 3873 drv = '' 4818 drv = !! 3874 dev = phaselist[d] >> 3875 xtraclass = '' >> 3876 xtrainfo = '' >> 3877 xtrastyle = '' 4819 if 'h 3878 if 'htmlclass' in dev: 4820 3879 xtraclass = dev['htmlclass'] 4821 if 'c 3880 if 'color' in dev: 4822 3881 xtrastyle = 'background:%s;' % dev['color'] 4823 if(d 3882 if(d in sysvals.devprops): 4824 3883 name = sysvals.devprops[d].altName(d) 4825 3884 xtraclass = sysvals.devprops[d].xtraClass() 4826 3885 xtrainfo = sysvals.devprops[d].xtraInfo() 4827 elif 3886 elif xtraclass == ' kth': 4828 3887 xtrainfo = ' kernel_thread' 4829 if('d 3888 if('drv' in dev and dev['drv']): 4830 3889 drv = ' {%s}' % dev['drv'] 4831 rowhe 3890 rowheight = devtl.phaseRowHeight(data.testnumber, b, dev['row']) 4832 rowto 3891 rowtop = devtl.phaseRowTop(data.testnumber, b, dev['row']) 4833 top = 3892 top = '%.3f' % (rowtop + devtl.scaleH) 4834 left 3893 left = '%f' % (((dev['start']-m0)*100)/mTotal) 4835 width 3894 width = '%f' % (((dev['end']-dev['start'])*100)/mTotal) 4836 lengt 3895 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) 4837 title 3896 title = name+drv+xtrainfo+length 4838 if sy 3897 if sysvals.suspendmode == 'command': 4839 3898 title += sysvals.testcommand 4840 elif 3899 elif xtraclass == ' ps': 4841 3900 if 'suspend' in b: 4842 3901 title += 'pre_suspend_process' 4843 3902 else: 4844 3903 title += 'post_resume_process' 4845 else: 3904 else: 4846 3905 title += b 4847 devtl 3906 devtl.html += devtl.html_device.format(dev['id'], \ 4848 3907 title, left, top, '%.3f'%rowheight, width, \ 4849 !! 3908 d+drv, xtraclass, xtrastyle) 4850 if('c 3909 if('cpuexec' in dev): 4851 3910 for t in sorted(dev['cpuexec']): 4852 3911 start, end = t >> 3912 j = float(dev['cpuexec'][t]) / 5 >> 3913 if j > 1.0: >> 3914 j = 1.0 4853 3915 height = '%.3f' % (rowheight/3) 4854 3916 top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3) 4855 3917 left = '%f' % (((start-m0)*100)/mTotal) 4856 3918 width = '%f' % ((end-start)*100/mTotal) 4857 !! 3919 color = 'rgba(255, 0, 0, %f)' % j 4858 3920 devtl.html += \ 4859 3921 html_cpuexec.format(left, top, height, width, color) 4860 if('s 3922 if('src' not in dev): 4861 3923 continue 4862 # dra 3924 # draw any trace events for this device 4863 for e 3925 for e in dev['src']: 4864 << 4865 << 4866 3926 height = '%.3f' % devtl.rowH 4867 3927 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH)) 4868 3928 left = '%f' % (((e.time-m0)*100)/mTotal) 4869 3929 width = '%f' % (e.length*100/mTotal) 4870 3930 xtrastyle = '' 4871 3931 if e.color: 4872 3932 xtrastyle = 'background:%s;' % e.color 4873 3933 devtl.html += \ 4874 3934 html_traceevent.format(e.title(), \ 4875 3935 left, top, height, width, e.text(), '', xtrastyle) 4876 # draw the time scale 3936 # draw the time scale, try to make the number of labels readable 4877 devtl.createTimeScale 3937 devtl.createTimeScale(m0, mMax, tTotal, dir) 4878 devtl.html += '</div> 3938 devtl.html += '</div>\n' 4879 3939 4880 # timeline is finished 3940 # timeline is finished 4881 devtl.html += '</div>\n</div>\n' 3941 devtl.html += '</div>\n</div>\n' 4882 3942 4883 # draw a legend which describes the p 3943 # draw a legend which describes the phases by color 4884 if sysvals.suspendmode != 'command': 3944 if sysvals.suspendmode != 'command': 4885 phasedef = testruns[-1].phase !! 3945 data = testruns[-1] 4886 devtl.html += '<div class="le 3946 devtl.html += '<div class="legend">\n' 4887 pdelta = 100.0/len(phasedef.k !! 3947 pdelta = 100.0/len(data.phases) 4888 pmargin = pdelta / 4.0 3948 pmargin = pdelta / 4.0 4889 for phase in sorted(phasedef, !! 3949 for phase in data.phases: 4890 id, p = '', phasedef[ !! 3950 tmp = phase.split('_') 4891 for word in phase.spl !! 3951 id = tmp[0][0] 4892 id += word[0] !! 3952 if(len(tmp) > 1): 4893 order = '%.2f' % ((p[ !! 3953 id += tmp[1][0] 4894 name = phase.replace( !! 3954 order = '%.2f' % ((data.dmesg[phase]['order'] * pdelta) + pmargin) 4895 devtl.html += devtl.h !! 3955 name = string.replace(phase, '_', ' ') >> 3956 devtl.html += devtl.html_legend.format(order, \ >> 3957 data.dmesg[phase]['color'], name, id) 4896 devtl.html += '</div>\n' 3958 devtl.html += '</div>\n' 4897 3959 4898 hf = open(sysvals.htmlfile, 'w') 3960 hf = open(sysvals.htmlfile, 'w') 4899 addCSS(hf, sysvals, len(testruns), ke 3961 addCSS(hf, sysvals, len(testruns), kerror) 4900 3962 4901 # write the device timeline 3963 # write the device timeline 4902 hf.write(devtl.html) 3964 hf.write(devtl.html) 4903 hf.write('<div id="devicedetailtitle" 3965 hf.write('<div id="devicedetailtitle"></div>\n') 4904 hf.write('<div id="devicedetail" styl 3966 hf.write('<div id="devicedetail" style="display:none;">\n') 4905 # draw the colored boxes for the devi 3967 # draw the colored boxes for the device detail section 4906 for data in testruns: 3968 for data in testruns: 4907 hf.write('<div id="devicedeta 3969 hf.write('<div id="devicedetail%d">\n' % data.testnumber) 4908 pscolor = 'linear-gradient(to 3970 pscolor = 'linear-gradient(to top left, #ccc, #eee)' 4909 hf.write(devtl.html_phaselet. 3971 hf.write(devtl.html_phaselet.format('pre_suspend_process', \ 4910 '0', '0', pscolor)) 3972 '0', '0', pscolor)) 4911 for b in data.sortedPhases(): !! 3973 for b in data.phases: 4912 phase = data.dmesg[b] 3974 phase = data.dmesg[b] 4913 length = phase['end'] 3975 length = phase['end']-phase['start'] 4914 left = '%.3f' % (((ph 3976 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal) 4915 width = '%.3f' % ((le 3977 width = '%.3f' % ((length*100.0)/tTotal) 4916 hf.write(devtl.html_p 3978 hf.write(devtl.html_phaselet.format(b, left, width, \ 4917 data.dmesg[b] 3979 data.dmesg[b]['color'])) 4918 hf.write(devtl.html_phaselet. 3980 hf.write(devtl.html_phaselet.format('post_resume_process', \ 4919 '0', '0', pscolor)) 3981 '0', '0', pscolor)) 4920 if sysvals.suspendmode == 'co 3982 if sysvals.suspendmode == 'command': 4921 hf.write(devtl.html_p 3983 hf.write(devtl.html_phaselet.format('cmdexec', '0', '0', pscolor)) 4922 hf.write('</div>\n') 3984 hf.write('</div>\n') 4923 hf.write('</div>\n') 3985 hf.write('</div>\n') 4924 3986 4925 # write the ftrace data (callgraph) 3987 # write the ftrace data (callgraph) 4926 if sysvals.cgtest >= 0 and len(testru 3988 if sysvals.cgtest >= 0 and len(testruns) > sysvals.cgtest: 4927 data = testruns[sysvals.cgtes 3989 data = testruns[sysvals.cgtest] 4928 else: 3990 else: 4929 data = testruns[-1] 3991 data = testruns[-1] 4930 if sysvals.usecallgraph: 3992 if sysvals.usecallgraph: 4931 addCallgraphs(sysvals, hf, da 3993 addCallgraphs(sysvals, hf, data) 4932 3994 4933 # add the test log as a hidden div 3995 # add the test log as a hidden div 4934 if sysvals.testlog and sysvals.logmsg 3996 if sysvals.testlog and sysvals.logmsg: 4935 hf.write('<div id="testlog" s 3997 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n') 4936 # add the dmesg log as a hidden div 3998 # add the dmesg log as a hidden div 4937 if sysvals.dmesglog and sysvals.dmesg 3999 if sysvals.dmesglog and sysvals.dmesgfile: 4938 hf.write('<div id="dmesglog" 4000 hf.write('<div id="dmesglog" style="display:none;">\n') 4939 lf = sysvals.openlog(sysvals. 4001 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 4940 for line in lf: 4002 for line in lf: 4941 line = line.replace(' 4003 line = line.replace('<', '<').replace('>', '>') 4942 hf.write(line) 4004 hf.write(line) 4943 lf.close() 4005 lf.close() 4944 hf.write('</div>\n') 4006 hf.write('</div>\n') 4945 # add the ftrace log as a hidden div 4007 # add the ftrace log as a hidden div 4946 if sysvals.ftracelog and sysvals.ftra 4008 if sysvals.ftracelog and sysvals.ftracefile: 4947 hf.write('<div id="ftracelog" 4009 hf.write('<div id="ftracelog" style="display:none;">\n') 4948 lf = sysvals.openlog(sysvals. 4010 lf = sysvals.openlog(sysvals.ftracefile, 'r') 4949 for line in lf: 4011 for line in lf: 4950 hf.write(line) 4012 hf.write(line) 4951 lf.close() 4013 lf.close() 4952 hf.write('</div>\n') 4014 hf.write('</div>\n') 4953 4015 4954 # write the footer and close 4016 # write the footer and close 4955 addScriptCode(hf, testruns) 4017 addScriptCode(hf, testruns) 4956 hf.write('</body>\n</html>\n') 4018 hf.write('</body>\n</html>\n') 4957 hf.close() 4019 hf.close() 4958 return True 4020 return True 4959 4021 4960 def addCSS(hf, sv, testcount=1, kerror=False, 4022 def addCSS(hf, sv, testcount=1, kerror=False, extra=''): 4961 kernel = sv.stamp['kernel'] 4023 kernel = sv.stamp['kernel'] 4962 host = sv.hostname[0].upper()+sv.host 4024 host = sv.hostname[0].upper()+sv.hostname[1:] 4963 mode = sv.suspendmode 4025 mode = sv.suspendmode 4964 if sv.suspendmode in suspendmodename: 4026 if sv.suspendmode in suspendmodename: 4965 mode = suspendmodename[sv.sus 4027 mode = suspendmodename[sv.suspendmode] 4966 title = host+' '+mode+' '+kernel 4028 title = host+' '+mode+' '+kernel 4967 4029 4968 # various format changes by flags 4030 # various format changes by flags 4969 cgchk = 'checked' 4031 cgchk = 'checked' 4970 cgnchk = 'not(:checked)' 4032 cgnchk = 'not(:checked)' 4971 if sv.cgexp: 4033 if sv.cgexp: 4972 cgchk = 'not(:checked)' 4034 cgchk = 'not(:checked)' 4973 cgnchk = 'checked' 4035 cgnchk = 'checked' 4974 4036 4975 hoverZ = 'z-index:8;' 4037 hoverZ = 'z-index:8;' 4976 if sv.usedevsrc: 4038 if sv.usedevsrc: 4977 hoverZ = '' 4039 hoverZ = '' 4978 4040 4979 devlistpos = 'absolute' 4041 devlistpos = 'absolute' 4980 if testcount > 1: 4042 if testcount > 1: 4981 devlistpos = 'relative' 4043 devlistpos = 'relative' 4982 4044 4983 scaleTH = 20 4045 scaleTH = 20 4984 if kerror: 4046 if kerror: 4985 scaleTH = 60 4047 scaleTH = 60 4986 4048 4987 # write the html header first (html h 4049 # write the html header first (html head, css code, up to body start) 4988 html_header = '<!DOCTYPE html>\n<html 4050 html_header = '<!DOCTYPE html>\n<html>\n<head>\n\ 4989 <meta http-equiv="content-type" conte 4051 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 4990 <title>'+title+'</title>\n\ 4052 <title>'+title+'</title>\n\ 4991 <style type=\'text/css\'>\n\ 4053 <style type=\'text/css\'>\n\ 4992 body {overflow-y:scroll;}\n\ 4054 body {overflow-y:scroll;}\n\ 4993 .stamp {width:100%;text-align 4055 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\ 4994 .stamp.sysinfo {font:10px Ari 4056 .stamp.sysinfo {font:10px Arial;}\n\ 4995 .callgraph {margin-top:30px;b 4057 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\ 4996 .callgraph article * {padding 4058 .callgraph article * {padding-left:28px;}\n\ 4997 h1 {color:black;font:bold 30p 4059 h1 {color:black;font:bold 30px Times;}\n\ 4998 t0 {color:black;font:bold 30p 4060 t0 {color:black;font:bold 30px Times;}\n\ 4999 t1 {color:black;font:30px Tim 4061 t1 {color:black;font:30px Times;}\n\ 5000 t2 {color:black;font:25px Tim 4062 t2 {color:black;font:25px Times;}\n\ 5001 t3 {color:black;font:20px Tim 4063 t3 {color:black;font:20px Times;white-space:nowrap;}\n\ 5002 t4 {color:black;font:bold 30p 4064 t4 {color:black;font:bold 30px Times;line-height:60px;white-space:nowrap;}\n\ 5003 cS {font:bold 13px Times;}\n\ 4065 cS {font:bold 13px Times;}\n\ 5004 table {width:100%;}\n\ 4066 table {width:100%;}\n\ 5005 .gray {background:rgba(80,80, 4067 .gray {background:rgba(80,80,80,0.1);}\n\ 5006 .green {background:rgba(204,2 4068 .green {background:rgba(204,255,204,0.4);}\n\ 5007 .purple {background:rgba(128, 4069 .purple {background:rgba(128,0,128,0.2);}\n\ 5008 .yellow {background:rgba(255, 4070 .yellow {background:rgba(255,255,204,0.4);}\n\ 5009 .blue {background:rgba(169,20 4071 .blue {background:rgba(169,208,245,0.4);}\n\ 5010 .time1 {font:22px Arial;borde 4072 .time1 {font:22px Arial;border:1px solid;}\n\ 5011 .time2 {font:15px Arial;borde 4073 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\ 5012 .testfail {font:bold 22px Ari 4074 .testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\ 5013 td {text-align:center;}\n\ 4075 td {text-align:center;}\n\ 5014 r {color:#500000;font:15px Ta 4076 r {color:#500000;font:15px Tahoma;}\n\ 5015 n {color:#505050;font:15px Ta 4077 n {color:#505050;font:15px Tahoma;}\n\ 5016 .tdhl {color:red;}\n\ 4078 .tdhl {color:red;}\n\ 5017 .hide {display:none;}\n\ 4079 .hide {display:none;}\n\ 5018 .pf {display:none;}\n\ 4080 .pf {display:none;}\n\ 5019 .pf:'+cgchk+' + label {backgr 4081 .pf:'+cgchk+' + label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/><rect x="8" y="4" width="2" height="10" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ 5020 .pf:'+cgnchk+' ~ label {backg 4082 .pf:'+cgnchk+' ~ label {background:url(\'data:image/svg+xml;utf,<?xml version="1.0" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" height="18" width="18" version="1.1"><circle cx="9" cy="9" r="8" stroke="black" stroke-width="1" fill="white"/><rect x="4" y="8" width="10" height="2" style="fill:black;stroke-width:0"/></svg>\') no-repeat left center;}\n\ 5021 .pf:'+cgchk+' ~ *:not(:nth-ch 4083 .pf:'+cgchk+' ~ *:not(:nth-child(2)) {display:none;}\n\ 5022 .zoombox {position:relative;w 4084 .zoombox {position:relative;width:100%;overflow-x:scroll;-webkit-user-select:none;-moz-user-select:none;user-select:none;}\n\ 5023 .timeline {position:relative; 4085 .timeline {position:relative;font-size:14px;cursor:pointer;width:100%; overflow:hidden;background:linear-gradient(#cccccc, white);}\n\ 5024 .thread {position:absolute;he 4086 .thread {position:absolute;height:0%;overflow:hidden;z-index:7;line-height:30px;font-size:14px;border:1px solid;text-align:center;white-space:nowrap;}\n\ 5025 .thread.ps {border-radius:3px 4087 .thread.ps {border-radius:3px;background:linear-gradient(to top, #ccc, #eee);}\n\ 5026 .thread:hover {background:whi 4088 .thread:hover {background:white;border:1px solid red;'+hoverZ+'}\n\ 5027 .thread.sec,.thread.sec:hover 4089 .thread.sec,.thread.sec:hover {background:black;border:0;color:white;line-height:15px;font-size:10px;}\n\ 5028 .hover {background:white;bord 4090 .hover {background:white;border:1px solid red;'+hoverZ+'}\n\ 5029 .hover.sync {background:white 4091 .hover.sync {background:white;}\n\ 5030 .hover.bg,.hover.kth,.hover.s 4092 .hover.bg,.hover.kth,.hover.sync,.hover.ps {background:white;}\n\ 5031 .jiffie {position:absolute;po 4093 .jiffie {position:absolute;pointer-events: none;z-index:8;}\n\ 5032 .traceevent {position:absolut 4094 .traceevent {position:absolute;font-size:10px;z-index:7;overflow:hidden;color:black;text-align:center;white-space:nowrap;border-radius:5px;border:1px solid black;background:linear-gradient(to bottom right,#CCC,#969696);}\n\ 5033 .traceevent:hover {color:whit 4095 .traceevent:hover {color:white;font-weight:bold;border:1px solid white;}\n\ 5034 .phase {position:absolute;ove 4096 .phase {position:absolute;overflow:hidden;border:0px;text-align:center;}\n\ 5035 .phaselet {float:left;overflo 4097 .phaselet {float:left;overflow:hidden;border:0px;text-align:center;min-height:100px;font-size:24px;}\n\ 5036 .t {position:absolute;line-he 4098 .t {position:absolute;line-height:'+('%d'%scaleTH)+'px;pointer-events:none;top:0;height:100%;border-right:1px solid black;z-index:6;}\n\ 5037 .err {position:absolute;top:0 4099 .err {position:absolute;top:0%;height:100%;border-right:3px solid red;color:red;font:bold 14px Times;line-height:18px;}\n\ 5038 .legend {position:relative; w 4100 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\ 5039 .legend .square {position:abs 4101 .legend .square {position:absolute;cursor:pointer;top:10px; width:0px;height:20px;border:1px solid;padding-left:20px;}\n\ 5040 button {height:40px;width:200 4102 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ 5041 .btnfmt {position:relative;fl 4103 .btnfmt {position:relative;float:right;height:25px;width:auto;margin-top:3px;margin-bottom:0;font-size:10px;text-align:center;}\n\ 5042 .devlist {position:'+devlistp 4104 .devlist {position:'+devlistpos+';width:190px;}\n\ 5043 a:link {color:white;text-deco 4105 a:link {color:white;text-decoration:none;}\n\ 5044 a:visited {color:white;}\n\ 4106 a:visited {color:white;}\n\ 5045 a:hover {color:white;}\n\ 4107 a:hover {color:white;}\n\ 5046 a:active {color:white;}\n\ 4108 a:active {color:white;}\n\ 5047 .version {position:relative;f 4109 .version {position:relative;float:left;color:white;font-size:10px;line-height:30px;margin-left:10px;}\n\ 5048 #devicedetail {min-height:100 4110 #devicedetail {min-height:100px;box-shadow:5px 5px 20px black;}\n\ 5049 .tblock {position:absolute;he 4111 .tblock {position:absolute;height:100%;background:#ddd;}\n\ 5050 .tback {position:absolute;wid 4112 .tback {position:absolute;width:100%;background:linear-gradient(#ccc, #ddd);}\n\ 5051 .bg {z-index:1;}\n\ 4113 .bg {z-index:1;}\n\ 5052 '+extra+'\ 4114 '+extra+'\ 5053 </style>\n</head>\n<body>\n' 4115 </style>\n</head>\n<body>\n' 5054 hf.write(html_header) 4116 hf.write(html_header) 5055 4117 5056 # Function: addScriptCode 4118 # Function: addScriptCode 5057 # Description: 4119 # Description: 5058 # Adds the javascript code to the outp 4120 # Adds the javascript code to the output html 5059 # Arguments: 4121 # Arguments: 5060 # hf: the open html file pointer 4122 # hf: the open html file pointer 5061 # testruns: array of Data objects from 4123 # testruns: array of Data objects from parseKernelLog or parseTraceLog 5062 def addScriptCode(hf, testruns): 4124 def addScriptCode(hf, testruns): 5063 t0 = testruns[0].start * 1000 4125 t0 = testruns[0].start * 1000 5064 tMax = testruns[-1].end * 1000 4126 tMax = testruns[-1].end * 1000 5065 hf.write('<script type="text/javascri << 5066 # create an array in javascript memor 4127 # create an array in javascript memory with the device details 5067 detail = ' var devtable = [];\n' 4128 detail = ' var devtable = [];\n' 5068 for data in testruns: 4129 for data in testruns: 5069 topo = data.deviceTopology() 4130 topo = data.deviceTopology() 5070 detail += ' devtable[%d] 4131 detail += ' devtable[%d] = "%s";\n' % (data.testnumber, topo) 5071 detail += ' var bounds = [%f,%f]; 4132 detail += ' var bounds = [%f,%f];\n' % (t0, tMax) 5072 # add the code which will manipulate 4133 # add the code which will manipulate the data in the browser 5073 hf.write(detail); !! 4134 script_code = \ 5074 script_code = r""" var resolutio !! 4135 '<script type="text/javascript">\n'+detail+\ 5075 var dragval = [0, 0]; !! 4136 ' var resolution = -1;\n'\ 5076 function redrawTimescale(t0, tMax, tS !! 4137 ' var dragval = [0, 0];\n'\ 5077 var rline = '<div class="t" s !! 4138 ' function redrawTimescale(t0, tMax, tS) {\n'\ 5078 var tTotal = tMax - t0; !! 4139 ' var rline = \'<div class="t" style="left:0;border-left:1px solid black;border-right:0;">\';\n'\ 5079 var list = document.getElemen !! 4140 ' var tTotal = tMax - t0;\n'\ 5080 for (var i = 0; i < list.leng !! 4141 ' var list = document.getElementsByClassName("tblock");\n'\ 5081 var timescale = list[ !! 4142 ' for (var i = 0; i < list.length; i++) {\n'\ 5082 var m0 = t0 + (tTotal !! 4143 ' var timescale = list[i].getElementsByClassName("timescale")[0];\n'\ 5083 var mTotal = tTotal*p !! 4144 ' var m0 = t0 + (tTotal*parseFloat(list[i].style.left)/100);\n'\ 5084 var mMax = m0 + mTota !! 4145 ' var mTotal = tTotal*parseFloat(list[i].style.width)/100;\n'\ 5085 var html = ""; !! 4146 ' var mMax = m0 + mTotal;\n'\ 5086 var divTotal = Math.f !! 4147 ' var html = "";\n'\ 5087 if(divTotal > 1000) c !! 4148 ' var divTotal = Math.floor(mTotal/tS) + 1;\n'\ 5088 var divEdge = (mTotal !! 4149 ' if(divTotal > 1000) continue;\n'\ 5089 var pos = 0.0, val = !! 4150 ' var divEdge = (mTotal - tS*(divTotal-1))*100/mTotal;\n'\ 5090 for (var j = 0; j < d !! 4151 ' var pos = 0.0, val = 0.0;\n'\ 5091 var htmlline !! 4152 ' for (var j = 0; j < divTotal; j++) {\n'\ 5092 var mode = li !! 4153 ' var htmlline = "";\n'\ 5093 if(mode == "s !! 4154 ' var mode = list[i].id[5];\n'\ 5094 pos = !! 4155 ' if(mode == "s") {\n'\ 5095 val = !! 4156 ' pos = 100 - (((j)*tS*100)/mTotal) - divEdge;\n'\ 5096 if(j !! 4157 ' val = (j-divTotal+1)*tS;\n'\ 5097 !! 4158 ' if(j == divTotal - 1)\n'\ 5098 else !! 4159 ' htmlline = \'<div class="t" style="right:\'+pos+\'%"><cS>S→</cS></div>\';\n'\ 5099 !! 4160 ' else\n'\ 5100 } else { !! 4161 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\ 5101 pos = !! 4162 ' } else {\n'\ 5102 val = !! 4163 ' pos = 100 - (((j)*tS*100)/mTotal);\n'\ 5103 htmll !! 4164 ' val = (j)*tS;\n'\ 5104 if(j !! 4165 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\ 5105 !! 4166 ' if(j == 0)\n'\ 5106 !! 4167 ' if(mode == "r")\n'\ 5107 !! 4168 ' htmlline = rline+"<cS>←R</cS></div>";\n'\ 5108 !! 4169 ' else\n'\ 5109 } !! 4170 ' htmlline = rline+"<cS>0ms</div>";\n'\ 5110 html += htmll !! 4171 ' }\n'\ 5111 } !! 4172 ' html += htmlline;\n'\ 5112 timescale.innerHTML = !! 4173 ' }\n'\ 5113 } !! 4174 ' timescale.innerHTML = html;\n'\ 5114 } !! 4175 ' }\n'\ 5115 function zoomTimeline() { !! 4176 ' }\n'\ 5116 var dmesg = document.getEleme !! 4177 ' function zoomTimeline() {\n'\ 5117 var zoombox = document.getEle !! 4178 ' var dmesg = document.getElementById("dmesg");\n'\ 5118 var left = zoombox.scrollLeft !! 4179 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 5119 var val = parseFloat(dmesg.st !! 4180 ' var left = zoombox.scrollLeft;\n'\ 5120 var newval = 100; !! 4181 ' var val = parseFloat(dmesg.style.width);\n'\ 5121 var sh = window.outerWidth / !! 4182 ' var newval = 100;\n'\ 5122 if(this.id == "zoomin") { !! 4183 ' var sh = window.outerWidth / 2;\n'\ 5123 newval = val * 1.2; !! 4184 ' if(this.id == "zoomin") {\n'\ 5124 if(newval > 910034) n !! 4185 ' newval = val * 1.2;\n'\ 5125 dmesg.style.width = n !! 4186 ' if(newval > 910034) newval = 910034;\n'\ 5126 zoombox.scrollLeft = !! 4187 ' dmesg.style.width = newval+"%";\n'\ 5127 } else if (this.id == "zoomou !! 4188 ' zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\ 5128 newval = val / 1.2; !! 4189 ' } else if (this.id == "zoomout") {\n'\ 5129 if(newval < 100) newv !! 4190 ' newval = val / 1.2;\n'\ 5130 dmesg.style.width = n !! 4191 ' if(newval < 100) newval = 100;\n'\ 5131 zoombox.scrollLeft = !! 4192 ' dmesg.style.width = newval+"%";\n'\ 5132 } else { !! 4193 ' zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\ 5133 zoombox.scrollLeft = !! 4194 ' } else {\n'\ 5134 dmesg.style.width = " !! 4195 ' zoombox.scrollLeft = 0;\n'\ 5135 } !! 4196 ' dmesg.style.width = "100%";\n'\ 5136 var tS = [10000, 5000, 2000, !! 4197 ' }\n'\ 5137 var t0 = bounds[0]; !! 4198 ' var tS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1];\n'\ 5138 var tMax = bounds[1]; !! 4199 ' var t0 = bounds[0];\n'\ 5139 var tTotal = tMax - t0; !! 4200 ' var tMax = bounds[1];\n'\ 5140 var wTotal = tTotal * 100.0 / !! 4201 ' var tTotal = tMax - t0;\n'\ 5141 var idx = 7*window.innerWidth !! 4202 ' var wTotal = tTotal * 100.0 / newval;\n'\ 5142 for(var i = 0; (i < tS.length !! 4203 ' var idx = 7*window.innerWidth/1100;\n'\ 5143 if(i >= tS.length) i = tS.len !! 4204 ' for(var i = 0; (i < tS.length)&&((wTotal / tS[i]) < idx); i++);\n'\ 5144 if(tS[i] == resolution) retur !! 4205 ' if(i >= tS.length) i = tS.length - 1;\n'\ 5145 resolution = tS[i]; !! 4206 ' if(tS[i] == resolution) return;\n'\ 5146 redrawTimescale(t0, tMax, tS[ !! 4207 ' resolution = tS[i];\n'\ 5147 } !! 4208 ' redrawTimescale(t0, tMax, tS[i]);\n'\ 5148 function deviceName(title) { !! 4209 ' }\n'\ 5149 var name = title.slice(0, tit !! 4210 ' function deviceName(title) {\n'\ 5150 return name; !! 4211 ' var name = title.slice(0, title.indexOf(" ("));\n'\ 5151 } !! 4212 ' return name;\n'\ 5152 function deviceHover() { !! 4213 ' }\n'\ 5153 var name = deviceName(this.ti !! 4214 ' function deviceHover() {\n'\ 5154 var dmesg = document.getEleme !! 4215 ' var name = deviceName(this.title);\n'\ 5155 var dev = dmesg.getElementsBy !! 4216 ' var dmesg = document.getElementById("dmesg");\n'\ 5156 var cpu = -1; !! 4217 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5157 if(name.match("CPU_ON\[[0-9]* !! 4218 ' var cpu = -1;\n'\ 5158 cpu = parseInt(name.s !! 4219 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ 5159 else if(name.match("CPU_OFF\[ !! 4220 ' cpu = parseInt(name.slice(7));\n'\ 5160 cpu = parseInt(name.s !! 4221 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ 5161 for (var i = 0; i < dev.lengt !! 4222 ' cpu = parseInt(name.slice(8));\n'\ 5162 dname = deviceName(de !! 4223 ' for (var i = 0; i < dev.length; i++) {\n'\ 5163 var cname = dev[i].cl !! 4224 ' dname = deviceName(dev[i].title);\n'\ 5164 if((cpu >= 0 && dname !! 4225 ' var cname = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\ 5165 (name == dnam !! 4226 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 5166 { !! 4227 ' (name == dname))\n'\ 5167 dev[i].classN !! 4228 ' {\n'\ 5168 } else { !! 4229 ' dev[i].className = "hover "+cname;\n'\ 5169 dev[i].classN !! 4230 ' } else {\n'\ 5170 } !! 4231 ' dev[i].className = cname;\n'\ 5171 } !! 4232 ' }\n'\ 5172 } !! 4233 ' }\n'\ 5173 function deviceUnhover() { !! 4234 ' }\n'\ 5174 var dmesg = document.getEleme !! 4235 ' function deviceUnhover() {\n'\ 5175 var dev = dmesg.getElementsBy !! 4236 ' var dmesg = document.getElementById("dmesg");\n'\ 5176 for (var i = 0; i < dev.lengt !! 4237 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5177 dev[i].className = de !! 4238 ' for (var i = 0; i < dev.length; i++) {\n'\ 5178 } !! 4239 ' dev[i].className = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\ 5179 } !! 4240 ' }\n'\ 5180 function deviceTitle(title, total, cp !! 4241 ' }\n'\ 5181 var prefix = "Total"; !! 4242 ' function deviceTitle(title, total, cpu) {\n'\ 5182 if(total.length > 3) { !! 4243 ' var prefix = "Total";\n'\ 5183 prefix = "Average"; !! 4244 ' if(total.length > 3) {\n'\ 5184 total[1] = (total[1]+ !! 4245 ' prefix = "Average";\n'\ 5185 total[2] = (total[2]+ !! 4246 ' total[1] = (total[1]+total[3])/2;\n'\ 5186 } !! 4247 ' total[2] = (total[2]+total[4])/2;\n'\ 5187 var devtitle = document.getEl !! 4248 ' }\n'\ 5188 var name = deviceName(title); !! 4249 ' var devtitle = document.getElementById("devicedetailtitle");\n'\ 5189 if(cpu >= 0) name = "CPU"+cpu !! 4250 ' var name = deviceName(title);\n'\ 5190 var driver = ""; !! 4251 ' if(cpu >= 0) name = "CPU"+cpu;\n'\ 5191 var tS = "<t2>(</t2>"; !! 4252 ' var driver = "";\n'\ 5192 var tR = "<t2>)</t2>"; !! 4253 ' var tS = "<t2>(</t2>";\n'\ 5193 if(total[1] > 0) !! 4254 ' var tR = "<t2>)</t2>";\n'\ 5194 tS = "<t2>("+prefix+" !! 4255 ' if(total[1] > 0)\n'\ 5195 if(total[2] > 0) !! 4256 ' tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\ 5196 tR = " <t2>"+prefix+" !! 4257 ' if(total[2] > 0)\n'\ 5197 var s = title.indexOf("{"); !! 4258 ' tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\ 5198 var e = title.indexOf("}"); !! 4259 ' var s = title.indexOf("{");\n'\ 5199 if((s >= 0) && (e >= 0)) !! 4260 ' var e = title.indexOf("}");\n'\ 5200 driver = title.slice(< !! 4261 ' if((s >= 0) && (e >= 0))\n'\ 5201 if(total[1] > 0 && total[2] > !! 4262 ' driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\ 5202 devtitle.innerHTML = !! 4263 ' if(total[1] > 0 && total[2] > 0)\n'\ 5203 else !! 4264 ' devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\ 5204 devtitle.innerHTML = !! 4265 ' else\n'\ 5205 return name; !! 4266 ' devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\ 5206 } !! 4267 ' return name;\n'\ 5207 function deviceDetail() { !! 4268 ' }\n'\ 5208 var devinfo = document.getEle !! 4269 ' function deviceDetail() {\n'\ 5209 devinfo.style.display = "bloc !! 4270 ' var devinfo = document.getElementById("devicedetail");\n'\ 5210 var name = deviceName(this.ti !! 4271 ' devinfo.style.display = "block";\n'\ 5211 var cpu = -1; !! 4272 ' var name = deviceName(this.title);\n'\ 5212 if(name.match("CPU_ON\[[0-9]* !! 4273 ' var cpu = -1;\n'\ 5213 cpu = parseInt(name.s !! 4274 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ 5214 else if(name.match("CPU_OFF\[ !! 4275 ' cpu = parseInt(name.slice(7));\n'\ 5215 cpu = parseInt(name.s !! 4276 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ 5216 var dmesg = document.getEleme !! 4277 ' cpu = parseInt(name.slice(8));\n'\ 5217 var dev = dmesg.getElementsBy !! 4278 ' var dmesg = document.getElementById("dmesg");\n'\ 5218 var idlist = []; !! 4279 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5219 var pdata = [[]]; !! 4280 ' var idlist = [];\n'\ 5220 if(document.getElementById("d !! 4281 ' var pdata = [[]];\n'\ 5221 pdata = [[], []]; !! 4282 ' if(document.getElementById("devicedetail1"))\n'\ 5222 var pd = pdata[0]; !! 4283 ' pdata = [[], []];\n'\ 5223 var total = [0.0, 0.0, 0.0]; !! 4284 ' var pd = pdata[0];\n'\ 5224 for (var i = 0; i < dev.lengt !! 4285 ' var total = [0.0, 0.0, 0.0];\n'\ 5225 dname = deviceName(de !! 4286 ' for (var i = 0; i < dev.length; i++) {\n'\ 5226 if((cpu >= 0 && dname !! 4287 ' dname = deviceName(dev[i].title);\n'\ 5227 (name == dnam !! 4288 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 5228 { !! 4289 ' (name == dname))\n'\ 5229 idlist[idlist !! 4290 ' {\n'\ 5230 var tidx = 1; !! 4291 ' idlist[idlist.length] = dev[i].id;\n'\ 5231 if(dev[i].id[ !! 4292 ' var tidx = 1;\n'\ 5232 pd = !! 4293 ' if(dev[i].id[0] == "a") {\n'\ 5233 } else { !! 4294 ' pd = pdata[0];\n'\ 5234 if(pd !! 4295 ' } else {\n'\ 5235 if(to !! 4296 ' if(pdata.length == 1) pdata[1] = [];\n'\ 5236 pd = !! 4297 ' if(total.length == 3) total[3]=total[4]=0.0;\n'\ 5237 tidx !! 4298 ' pd = pdata[1];\n'\ 5238 } !! 4299 ' tidx = 3;\n'\ 5239 var info = de !! 4300 ' }\n'\ 5240 var pname = i !! 4301 ' var info = dev[i].title.split(" ");\n'\ 5241 pd[pname] = p !! 4302 ' var pname = info[info.length-1];\n'\ 5242 total[0] += p !! 4303 ' pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\ 5243 if(pname.inde !! 4304 ' total[0] += pd[pname];\n'\ 5244 total !! 4305 ' if(pname.indexOf("suspend") >= 0)\n'\ 5245 else !! 4306 ' total[tidx] += pd[pname];\n'\ 5246 total !! 4307 ' else\n'\ 5247 } !! 4308 ' total[tidx+1] += pd[pname];\n'\ 5248 } !! 4309 ' }\n'\ 5249 var devname = deviceTitle(thi !! 4310 ' }\n'\ 5250 var left = 0.0; !! 4311 ' var devname = deviceTitle(this.title, total, cpu);\n'\ 5251 for (var t = 0; t < pdata.len !! 4312 ' var left = 0.0;\n'\ 5252 pd = pdata[t]; !! 4313 ' for (var t = 0; t < pdata.length; t++) {\n'\ 5253 devinfo = document.ge !! 4314 ' pd = pdata[t];\n'\ 5254 var phases = devinfo. !! 4315 ' devinfo = document.getElementById("devicedetail"+t);\n'\ 5255 for (var i = 0; i < p !! 4316 ' var phases = devinfo.getElementsByClassName("phaselet");\n'\ 5256 if(phases[i]. !! 4317 ' for (var i = 0; i < phases.length; i++) {\n'\ 5257 var w !! 4318 ' if(phases[i].id in pd) {\n'\ 5258 var f !! 4319 ' var w = 100.0*pd[phases[i].id]/total[0];\n'\ 5259 if(w !! 4320 ' var fs = 32;\n'\ 5260 var f !! 4321 ' if(w < 8) fs = 4*w | 0;\n'\ 5261 phase !! 4322 ' var fs2 = fs*3/4;\n'\ 5262 phase !! 4323 ' phases[i].style.width = w+"%";\n'\ 5263 phase !! 4324 ' phases[i].style.left = left+"%";\n'\ 5264 left !! 4325 ' phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\ 5265 var t !! 4326 ' left += w;\n'\ 5266 var p !! 4327 ' var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\ 5267 phase !! 4328 ' var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace(new RegExp("_", "g"), " ")+"</t3>";\n'\ 5268 } else { !! 4329 ' phases[i].innerHTML = time+pname;\n'\ 5269 phase !! 4330 ' } else {\n'\ 5270 phase !! 4331 ' phases[i].style.width = "0%";\n'\ 5271 } !! 4332 ' phases[i].style.left = left+"%";\n'\ 5272 } !! 4333 ' }\n'\ 5273 } !! 4334 ' }\n'\ 5274 if(typeof devstats !== 'undef !! 4335 ' }\n'\ 5275 callDetail(this.id, t !! 4336 ' if(typeof devstats !== \'undefined\')\n'\ 5276 var cglist = document.getElem !! 4337 ' callDetail(this.id, this.title);\n'\ 5277 if(!cglist) return; !! 4338 ' var cglist = document.getElementById("callgraphs");\n'\ 5278 var cg = cglist.getElementsBy !! 4339 ' if(!cglist) return;\n'\ 5279 if(cg.length < 10) return; !! 4340 ' var cg = cglist.getElementsByClassName("atop");\n'\ 5280 for (var i = 0; i < cg.length !! 4341 ' if(cg.length < 10) return;\n'\ 5281 cgid = cg[i].id.split !! 4342 ' for (var i = 0; i < cg.length; i++) {\n'\ 5282 if(idlist.indexOf(cgi !! 4343 ' cgid = cg[i].id.split("x")[0]\n'\ 5283 cg[i].style.d !! 4344 ' if(idlist.indexOf(cgid) >= 0) {\n'\ 5284 } else { !! 4345 ' cg[i].style.display = "block";\n'\ 5285 cg[i].style.d !! 4346 ' } else {\n'\ 5286 } !! 4347 ' cg[i].style.display = "none";\n'\ 5287 } !! 4348 ' }\n'\ 5288 } !! 4349 ' }\n'\ 5289 function callDetail(devid, devtitle) !! 4350 ' }\n'\ 5290 if(!(devid in devstats) || de !! 4351 ' function callDetail(devid, devtitle) {\n'\ 5291 return; !! 4352 ' if(!(devid in devstats) || devstats[devid].length < 1)\n'\ 5292 var list = devstats[devid]; !! 4353 ' return;\n'\ 5293 var tmp = devtitle.split(" ") !! 4354 ' var list = devstats[devid];\n'\ 5294 var name = tmp[0], phase = tm !! 4355 ' var tmp = devtitle.split(" ");\n'\ 5295 var dd = document.getElementB !! 4356 ' var name = tmp[0], phase = tmp[tmp.length-1];\n'\ 5296 var total = parseFloat(tmp[1] !! 4357 ' var dd = document.getElementById(phase);\n'\ 5297 var mlist = []; !! 4358 ' var total = parseFloat(tmp[1].slice(1));\n'\ 5298 var maxlen = 0; !! 4359 ' var mlist = [];\n'\ 5299 var info = [] !! 4360 ' var maxlen = 0;\n'\ 5300 for(var i in list) { !! 4361 ' var info = []\n'\ 5301 if(list[i][0] == "@") !! 4362 ' for(var i in list) {\n'\ 5302 info = list[i !! 4363 ' if(list[i][0] == "@") {\n'\ 5303 continue; !! 4364 ' info = list[i].split("|");\n'\ 5304 } !! 4365 ' continue;\n'\ 5305 var tmp = list[i].spl !! 4366 ' }\n'\ 5306 var t = parseFloat(tm !! 4367 ' var tmp = list[i].split("|");\n'\ 5307 var p = (t*100.0/tota !! 4368 ' var t = parseFloat(tmp[0]), f = tmp[1], c = parseInt(tmp[2]);\n'\ 5308 mlist[mlist.length] = !! 4369 ' var p = (t*100.0/total).toFixed(2);\n'\ 5309 if(f.length > maxlen) !! 4370 ' mlist[mlist.length] = [f, c, t.toFixed(2), p+"%"];\n'\ 5310 maxlen = f.le !! 4371 ' if(f.length > maxlen)\n'\ 5311 } !! 4372 ' maxlen = f.length;\n'\ 5312 var pad = 5; !! 4373 ' }\n'\ 5313 if(mlist.length == 0) pad = 3 !! 4374 ' var pad = 5;\n'\ 5314 var html = '<div style="paddi !! 4375 ' if(mlist.length == 0) pad = 30;\n'\ 5315 if(info.length > 2) !! 4376 ' var html = \'<div style="padding-top:\'+pad+\'px"><t3> <b>\'+name+\':</b>\';\n'\ 5316 html += " start=<b>"+ !! 4377 ' if(info.length > 2)\n'\ 5317 if(info.length > 3) !! 4378 ' html += " start=<b>"+info[1]+"</b>, end=<b>"+info[2]+"</b>";\n'\ 5318 html += ", length<i>( !! 4379 ' if(info.length > 3)\n'\ 5319 if(info.length > 4) !! 4380 ' html += ", length<i>(w/o overhead)</i>=<b>"+info[3]+" ms</b>";\n'\ 5320 html += ", return=<b> !! 4381 ' if(info.length > 4)\n'\ 5321 html += "</t3></div>"; !! 4382 ' html += ", return=<b>"+info[4]+"</b>";\n'\ 5322 if(mlist.length > 0) { !! 4383 ' html += "</t3></div>";\n'\ 5323 html += '<table class !! 4384 ' if(mlist.length > 0) {\n'\ 5324 for(var i in mlist) !! 4385 ' html += \'<table class=fstat style="padding-top:\'+(maxlen*5)+\'px;"><tr><th>Function</th>\';\n'\ 5325 html += "<td !! 4386 ' for(var i in mlist)\n'\ 5326 html += "</tr><tr><th !! 4387 ' html += "<td class=vt>"+mlist[i][0]+"</td>";\n'\ 5327 for(var i in mlist) !! 4388 ' html += "</tr><tr><th>Calls</th>";\n'\ 5328 html += "<td> !! 4389 ' for(var i in mlist)\n'\ 5329 html += "</tr><tr><th !! 4390 ' html += "<td>"+mlist[i][1]+"</td>";\n'\ 5330 for(var i in mlist) !! 4391 ' html += "</tr><tr><th>Time(ms)</th>";\n'\ 5331 html += "<td> !! 4392 ' for(var i in mlist)\n'\ 5332 html += "</tr><tr><th !! 4393 ' html += "<td>"+mlist[i][2]+"</td>";\n'\ 5333 for(var i in mlist) !! 4394 ' html += "</tr><tr><th>Percent</th>";\n'\ 5334 html += "<td> !! 4395 ' for(var i in mlist)\n'\ 5335 html += "</tr></table !! 4396 ' html += "<td>"+mlist[i][3]+"</td>";\n'\ 5336 } !! 4397 ' html += "</tr></table>";\n'\ 5337 dd.innerHTML = html; !! 4398 ' }\n'\ 5338 var height = (maxlen*5)+100; !! 4399 ' dd.innerHTML = html;\n'\ 5339 dd.style.height = height+"px" !! 4400 ' var height = (maxlen*5)+100;\n'\ 5340 document.getElementById("devi !! 4401 ' dd.style.height = height+"px";\n'\ 5341 } !! 4402 ' document.getElementById("devicedetail").style.height = height+"px";\n'\ 5342 function callSelect() { !! 4403 ' }\n'\ 5343 var cglist = document.getElem !! 4404 ' function callSelect() {\n'\ 5344 if(!cglist) return; !! 4405 ' var cglist = document.getElementById("callgraphs");\n'\ 5345 var cg = cglist.getElementsBy !! 4406 ' if(!cglist) return;\n'\ 5346 for (var i = 0; i < cg.length !! 4407 ' var cg = cglist.getElementsByClassName("atop");\n'\ 5347 if(this.id == cg[i].i !! 4408 ' for (var i = 0; i < cg.length; i++) {\n'\ 5348 cg[i].style.d !! 4409 ' if(this.id == cg[i].id) {\n'\ 5349 } else { !! 4410 ' cg[i].style.display = "block";\n'\ 5350 cg[i].style.d !! 4411 ' } else {\n'\ 5351 } !! 4412 ' cg[i].style.display = "none";\n'\ 5352 } !! 4413 ' }\n'\ 5353 } !! 4414 ' }\n'\ 5354 function devListWindow(e) { !! 4415 ' }\n'\ 5355 var win = window.open(); !! 4416 ' function devListWindow(e) {\n'\ 5356 var html = "<title>"+e.target !! 4417 ' var win = window.open();\n'\ 5357 "<style type=\"text/c !! 4418 ' var html = "<title>"+e.target.innerHTML+"</title>"+\n'\ 5358 " ul {list-style-ty !! 4419 ' "<style type=\\"text/css\\">"+\n'\ 5359 "</style>" !! 4420 ' " ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\ 5360 var dt = devtable[0]; !! 4421 ' "</style>"\n'\ 5361 if(e.target.id != "devlist1") !! 4422 ' var dt = devtable[0];\n'\ 5362 dt = devtable[1]; !! 4423 ' if(e.target.id != "devlist1")\n'\ 5363 win.document.write(html+dt); !! 4424 ' dt = devtable[1];\n'\ 5364 } !! 4425 ' win.document.write(html+dt);\n'\ 5365 function errWindow() { !! 4426 ' }\n'\ 5366 var range = this.id.split("_" !! 4427 ' function errWindow() {\n'\ 5367 var idx1 = parseInt(range[0]) !! 4428 ' var range = this.id.split("_");\n'\ 5368 var idx2 = parseInt(range[1]) !! 4429 ' var idx1 = parseInt(range[0]);\n'\ 5369 var win = window.open(); !! 4430 ' var idx2 = parseInt(range[1]);\n'\ 5370 var log = document.getElement !! 4431 ' var win = window.open();\n'\ 5371 var title = "<title>dmesg log !! 4432 ' var log = document.getElementById("dmesglog");\n'\ 5372 var text = log.innerHTML.spli !! 4433 ' var title = "<title>dmesg log</title>";\n'\ 5373 var html = ""; !! 4434 ' var text = log.innerHTML.split("\\n");\n'\ 5374 for(var i = 0; i < text.lengt !! 4435 ' var html = "";\n'\ 5375 if(i == idx1) { !! 4436 ' for(var i = 0; i < text.length; i++) {\n'\ 5376 html += "<e i !! 4437 ' if(i == idx1) {\n'\ 5377 } else if(i > idx1 && !! 4438 ' html += "<e id=target>"+text[i]+"</e>\\n";\n'\ 5378 html += "<e>" !! 4439 ' } else if(i > idx1 && i <= idx2) {\n'\ 5379 } else { !! 4440 ' html += "<e>"+text[i]+"</e>\\n";\n'\ 5380 html += text[ !! 4441 ' } else {\n'\ 5381 } !! 4442 ' html += text[i]+"\\n";\n'\ 5382 } !! 4443 ' }\n'\ 5383 win.document.write("<style>e{ !! 4444 ' }\n'\ 5384 win.location.hash = "#target" !! 4445 ' win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\ 5385 win.document.close(); !! 4446 ' win.location.hash = "#target";\n'\ 5386 } !! 4447 ' win.document.close();\n'\ 5387 function logWindow(e) { !! 4448 ' }\n'\ 5388 var name = e.target.id.slice( !! 4449 ' function logWindow(e) {\n'\ 5389 var win = window.open(); !! 4450 ' var name = e.target.id.slice(4);\n'\ 5390 var log = document.getElement !! 4451 ' var win = window.open();\n'\ 5391 var title = "<title>"+documen !! 4452 ' var log = document.getElementById(name+"log");\n'\ 5392 win.document.write(title+"<pr !! 4453 ' var title = "<title>"+document.title.split(" ")[0]+" "+name+" log</title>";\n'\ 5393 win.document.close(); !! 4454 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\ 5394 } !! 4455 ' win.document.close();\n'\ 5395 function onMouseDown(e) { !! 4456 ' }\n'\ 5396 dragval[0] = e.clientX; !! 4457 ' function onMouseDown(e) {\n'\ 5397 dragval[1] = document.getElem !! 4458 ' dragval[0] = e.clientX;\n'\ 5398 document.onmousemove = onMous !! 4459 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\ 5399 } !! 4460 ' document.onmousemove = onMouseMove;\n'\ 5400 function onMouseMove(e) { !! 4461 ' }\n'\ 5401 var zoombox = document.getEle !! 4462 ' function onMouseMove(e) {\n'\ 5402 zoombox.scrollLeft = dragval[ !! 4463 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 5403 } !! 4464 ' zoombox.scrollLeft = dragval[1] + dragval[0] - e.clientX;\n'\ 5404 function onMouseUp(e) { !! 4465 ' }\n'\ 5405 document.onmousemove = null; !! 4466 ' function onMouseUp(e) {\n'\ 5406 } !! 4467 ' document.onmousemove = null;\n'\ 5407 function onKeyPress(e) { !! 4468 ' }\n'\ 5408 var c = e.charCode; !! 4469 ' function onKeyPress(e) {\n'\ 5409 if(c != 42 && c != 43 && c != !! 4470 ' var c = e.charCode;\n'\ 5410 var click = document.createEv !! 4471 ' if(c != 42 && c != 43 && c != 45) return;\n'\ 5411 click.initEvent("click", true !! 4472 ' var click = document.createEvent("Events");\n'\ 5412 if(c == 43) !! 4473 ' click.initEvent("click", true, false);\n'\ 5413 document.getElementBy !! 4474 ' if(c == 43) \n'\ 5414 else if(c == 45) !! 4475 ' document.getElementById("zoomin").dispatchEvent(click);\n'\ 5415 document.getElementBy !! 4476 ' else if(c == 45)\n'\ 5416 else if(c == 42) !! 4477 ' document.getElementById("zoomout").dispatchEvent(click);\n'\ 5417 document.getElementBy !! 4478 ' else if(c == 42)\n'\ 5418 } !! 4479 ' document.getElementById("zoomdef").dispatchEvent(click);\n'\ 5419 window.addEventListener("resize", fun !! 4480 ' }\n'\ 5420 window.addEventListener("load", funct !! 4481 ' window.addEventListener("resize", function () {zoomTimeline();});\n'\ 5421 var dmesg = document.getEleme !! 4482 ' window.addEventListener("load", function () {\n'\ 5422 dmesg.style.width = "100%" !! 4483 ' var dmesg = document.getElementById("dmesg");\n'\ 5423 dmesg.onmousedown = onMouseDo !! 4484 ' dmesg.style.width = "100%"\n'\ 5424 document.onmouseup = onMouseU !! 4485 ' dmesg.onmousedown = onMouseDown;\n'\ 5425 document.onkeypress = onKeyPr !! 4486 ' document.onmouseup = onMouseUp;\n'\ 5426 document.getElementById("zoom !! 4487 ' document.onkeypress = onKeyPress;\n'\ 5427 document.getElementById("zoom !! 4488 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 5428 document.getElementById("zoom !! 4489 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 5429 var list = document.getElemen !! 4490 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 5430 for (var i = 0; i < list.leng !! 4491 ' var list = document.getElementsByClassName("err");\n'\ 5431 list[i].onclick = err !! 4492 ' for (var i = 0; i < list.length; i++)\n'\ 5432 var list = document.getElemen !! 4493 ' list[i].onclick = errWindow;\n'\ 5433 for (var i = 0; i < list.leng !! 4494 ' var list = document.getElementsByClassName("logbtn");\n'\ 5434 list[i].onclick = log !! 4495 ' for (var i = 0; i < list.length; i++)\n'\ 5435 list = document.getElementsBy !! 4496 ' list[i].onclick = logWindow;\n'\ 5436 for (var i = 0; i < list.leng !! 4497 ' list = document.getElementsByClassName("devlist");\n'\ 5437 list[i].onclick = dev !! 4498 ' for (var i = 0; i < list.length; i++)\n'\ 5438 var dev = dmesg.getElementsBy !! 4499 ' list[i].onclick = devListWindow;\n'\ 5439 for (var i = 0; i < dev.lengt !! 4500 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5440 dev[i].onclick = devi !! 4501 ' for (var i = 0; i < dev.length; i++) {\n'\ 5441 dev[i].onmouseover = !! 4502 ' dev[i].onclick = deviceDetail;\n'\ 5442 dev[i].onmouseout = d !! 4503 ' dev[i].onmouseover = deviceHover;\n'\ 5443 } !! 4504 ' dev[i].onmouseout = deviceUnhover;\n'\ 5444 var dev = dmesg.getElementsBy !! 4505 ' }\n'\ 5445 for (var i = 0; i < dev.lengt !! 4506 ' var dev = dmesg.getElementsByClassName("srccall");\n'\ 5446 dev[i].onclick = call !! 4507 ' for (var i = 0; i < dev.length; i++)\n'\ 5447 zoomTimeline(); !! 4508 ' dev[i].onclick = callSelect;\n'\ 5448 }); !! 4509 ' zoomTimeline();\n'\ 5449 </script> """ !! 4510 ' });\n'\ >> 4511 '</script>\n' 5450 hf.write(script_code); 4512 hf.write(script_code); 5451 4513 >> 4514 def setRuntimeSuspend(before=True): >> 4515 global sysvals >> 4516 sv = sysvals >> 4517 if sv.rs == 0: >> 4518 return >> 4519 if before: >> 4520 # runtime suspend disable or enable >> 4521 if sv.rs > 0: >> 4522 sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled' >> 4523 else: >> 4524 sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled' >> 4525 print('CONFIGURING RUNTIME SUSPEND...') >> 4526 sv.rslist = deviceInfo(sv.rstgt) >> 4527 for i in sv.rslist: >> 4528 sv.setVal(sv.rsval, i) >> 4529 print('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist))) >> 4530 print('waiting 5 seconds...') >> 4531 time.sleep(5) >> 4532 else: >> 4533 # runtime suspend re-enable or re-disable >> 4534 for i in sv.rslist: >> 4535 sv.setVal(sv.rstgt, i) >> 4536 print('runtime suspend settings restored on %d devices' % len(sv.rslist)) >> 4537 5452 # Function: executeSuspend 4538 # Function: executeSuspend 5453 # Description: 4539 # Description: 5454 # Execute system suspend through the s 4540 # Execute system suspend through the sysfs interface, then copy the output 5455 # dmesg and ftrace files to the test o 4541 # dmesg and ftrace files to the test output directory. 5456 def executeSuspend(quiet=False): !! 4542 def executeSuspend(): 5457 sv, tp, pm = sysvals, sysvals.tpath, !! 4543 pm = ProcessMonitor() 5458 if sv.wifi: !! 4544 tp = sysvals.tpath 5459 wifi = sv.checkWifi() !! 4545 fwdata = [] 5460 sv.dlog('wifi check, connecte << 5461 testdata = [] << 5462 # run these commands to prepare the s 4546 # run these commands to prepare the system for suspend 5463 if sv.display: !! 4547 if sysvals.display: 5464 if not quiet: !! 4548 if sysvals.display > 0: 5465 pprint('SET DISPLAY T !! 4549 print('TURN DISPLAY ON') 5466 ret = sv.displayControl(sv.di !! 4550 call('xset -d :0.0 dpms force suspend', shell=True) 5467 sv.dlog('xset display %s, ret !! 4551 call('xset -d :0.0 dpms force on', shell=True) >> 4552 else: >> 4553 print('TURN DISPLAY OFF') >> 4554 call('xset -d :0.0 dpms force suspend', shell=True) 5468 time.sleep(1) 4555 time.sleep(1) 5469 if sv.sync: !! 4556 if sysvals.sync: 5470 if not quiet: !! 4557 print('SYNCING FILESYSTEMS') 5471 pprint('SYNCING FILES << 5472 sv.dlog('syncing filesystems' << 5473 call('sync', shell=True) 4558 call('sync', shell=True) 5474 sv.dlog('read dmesg') !! 4559 # mark the start point in the kernel ring buffer just as we start 5475 sv.initdmesg() !! 4560 sysvals.initdmesg() 5476 sv.dlog('cmdinfo before') !! 4561 # start ftrace 5477 sv.cmdinfo(True) !! 4562 if(sysvals.usecallgraph or sysvals.usetraceevents): 5478 sv.start(pm) !! 4563 print('START TRACING') >> 4564 sysvals.fsetVal('1', 'tracing_on') >> 4565 if sysvals.useprocmon: >> 4566 pm.start() 5479 # execute however many s/r runs reque 4567 # execute however many s/r runs requested 5480 for count in range(1,sv.execcount+1): !! 4568 for count in range(1,sysvals.execcount+1): 5481 # x2delay in between test run 4569 # x2delay in between test runs 5482 if(count > 1 and sv.x2delay > !! 4570 if(count > 1 and sysvals.x2delay > 0): 5483 sv.fsetVal('WAIT %d' !! 4571 sysvals.fsetVal('WAIT %d' % sysvals.x2delay, 'trace_marker') 5484 time.sleep(sv.x2delay !! 4572 time.sleep(sysvals.x2delay/1000.0) 5485 sv.fsetVal('WAIT END' !! 4573 sysvals.fsetVal('WAIT END', 'trace_marker') 5486 # start message 4574 # start message 5487 if sv.testcommand != '': !! 4575 if sysvals.testcommand != '': 5488 pprint('COMMAND START !! 4576 print('COMMAND START') 5489 else: 4577 else: 5490 if(sv.rtcwake): !! 4578 if(sysvals.rtcwake): 5491 pprint('SUSPE !! 4579 print('SUSPEND START') 5492 else: 4580 else: 5493 pprint('SUSPE !! 4581 print('SUSPEND START (press a key to resume)') 5494 # set rtcwake 4582 # set rtcwake 5495 if(sv.rtcwake): !! 4583 if(sysvals.rtcwake): 5496 if not quiet: !! 4584 print('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime) 5497 pprint('will !! 4585 sysvals.rtcWakeAlarmOn() 5498 sv.dlog('enable RTC w << 5499 sv.rtcWakeAlarmOn() << 5500 # start of suspend trace mark 4586 # start of suspend trace marker 5501 sv.fsetVal(datetime.now().str !! 4587 if(sysvals.usecallgraph or sysvals.usetraceevents): >> 4588 sysvals.fsetVal('SUSPEND START', 'trace_marker') 5502 # predelay delay 4589 # predelay delay 5503 if(count == 1 and sv.predelay !! 4590 if(count == 1 and sysvals.predelay > 0): 5504 sv.fsetVal('WAIT %d' !! 4591 sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker') 5505 time.sleep(sv.predela !! 4592 time.sleep(sysvals.predelay/1000.0) 5506 sv.fsetVal('WAIT END' !! 4593 sysvals.fsetVal('WAIT END', 'trace_marker') 5507 # initiate suspend or command 4594 # initiate suspend or command 5508 sv.dlog('system executing a s !! 4595 if sysvals.testcommand != '': 5509 tdata = {'error': ''} !! 4596 call(sysvals.testcommand+' 2>&1', shell=True); 5510 if sv.testcommand != '': << 5511 res = call(sv.testcom << 5512 if res != 0: << 5513 tdata['error' << 5514 else: 4597 else: 5515 s0ixready = sv.s0ixSu !! 4598 mode = sysvals.suspendmode 5516 mode = sv.suspendmode !! 4599 if sysvals.memmode and os.path.exists(sysvals.mempowerfile): 5517 if sv.memmode and os. << 5518 mode = 'mem' 4600 mode = 'mem' 5519 sv.testVal(sv !! 4601 pf = open(sysvals.mempowerfile, 'w') 5520 if sv.diskmode and os !! 4602 pf.write(sysvals.memmode) 5521 mode = 'disk' !! 4603 pf.close() 5522 sv.testVal(sv !! 4604 pf = open(sysvals.powerfile, 'w') 5523 if sv.acpidebug: !! 4605 pf.write(mode) 5524 sv.testVal(sv !! 4606 # execution will pause here 5525 if ((mode == 'freeze' !! 4607 try: 5526 and sv.haveTu !! 4608 pf.close() 5527 # execution w !! 4609 except: 5528 retval, turbo !! 4610 pass 5529 if retval != !! 4611 if(sysvals.rtcwake): 5530 tdata !! 4612 sysvals.rtcWakeAlarmOff() 5531 if turbo: << 5532 tdata << 5533 else: << 5534 pf = open(sv. << 5535 pf.write(mode << 5536 # execution w << 5537 try: << 5538 pf.fl << 5539 pf.cl << 5540 except Except << 5541 tdata << 5542 sv.fsetVal('CMD COMPLETE', 't << 5543 sv.dlog('system returned') << 5544 # reset everything << 5545 sv.testVal('restoreall') << 5546 if(sv.rtcwake): << 5547 sv.dlog('disable RTC << 5548 sv.rtcWakeAlarmOff() << 5549 # postdelay delay 4613 # postdelay delay 5550 if(count == sv.execcount and !! 4614 if(count == sysvals.execcount and sysvals.postdelay > 0): 5551 sv.fsetVal('WAIT %d' !! 4615 sysvals.fsetVal('WAIT %d' % sysvals.postdelay, 'trace_marker') 5552 time.sleep(sv.postdel !! 4616 time.sleep(sysvals.postdelay/1000.0) 5553 sv.fsetVal('WAIT END' !! 4617 sysvals.fsetVal('WAIT END', 'trace_marker') 5554 # return from suspend 4618 # return from suspend 5555 pprint('RESUME COMPLETE') !! 4619 print('RESUME COMPLETE') 5556 if(count < sv.execcount): !! 4620 if(sysvals.usecallgraph or sysvals.usetraceevents): 5557 sv.fsetVal(datetime.n !! 4621 sysvals.fsetVal('RESUME COMPLETE', 'trace_marker') 5558 elif(not sv.wifitrace): !! 4622 if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'): 5559 sv.fsetVal(datetime.n !! 4623 fwdata.append(getFPDT(False)) 5560 sv.stop(pm) !! 4624 # stop ftrace 5561 if sv.wifi and wifi: !! 4625 if(sysvals.usecallgraph or sysvals.usetraceevents): 5562 tdata['wifi'] = sv.po !! 4626 if sysvals.useprocmon: 5563 sv.dlog('wifi check, !! 4627 pm.stop() 5564 if(count == sv.execcount and !! 4628 sysvals.fsetVal('0', 'tracing_on') 5565 sv.fsetVal(datetime.n !! 4629 print('CAPTURING TRACE') 5566 sv.stop(pm) !! 4630 op = sysvals.writeDatafileHeader(sysvals.ftracefile, fwdata) 5567 if sv.netfix: !! 4631 fp = open(tp+'trace', 'r') 5568 tdata['netfix'] = sv. !! 4632 for line in fp: 5569 sv.dlog('netfix, %s' !! 4633 op.write(line) 5570 if(sv.suspendmode == 'mem' or << 5571 sv.dlog('read the ACP << 5572 tdata['fw'] = getFPDT << 5573 testdata.append(tdata) << 5574 sv.dlog('cmdinfo after') << 5575 cmdafter = sv.cmdinfo(False) << 5576 # grab a copy of the dmesg output << 5577 if not quiet: << 5578 pprint('CAPTURING DMESG') << 5579 sv.getdmesg(testdata) << 5580 # grab a copy of the ftrace output << 5581 if sv.useftrace: << 5582 if not quiet: << 5583 pprint('CAPTURING TRA << 5584 op = sv.writeDatafileHeader(s << 5585 fp = open(tp+'trace', 'rb') << 5586 op.write(ascii(fp.read())) << 5587 op.close() 4634 op.close() 5588 sv.fsetVal('', 'trace') !! 4635 sysvals.fsetVal('', 'trace') 5589 sv.platforminfo(cmdafter) !! 4636 devProps() >> 4637 # grab a copy of the dmesg output >> 4638 print('CAPTURING DMESG') >> 4639 sysvals.getdmesg(fwdata) 5590 4640 5591 def readFile(file): 4641 def readFile(file): 5592 if os.path.islink(file): 4642 if os.path.islink(file): 5593 return os.readlink(file).spli 4643 return os.readlink(file).split('/')[-1] 5594 else: 4644 else: 5595 return sysvals.getVal(file).s 4645 return sysvals.getVal(file).strip() 5596 4646 5597 # Function: ms2nice 4647 # Function: ms2nice 5598 # Description: 4648 # Description: 5599 # Print out a very concise time string 4649 # Print out a very concise time string in minutes and seconds 5600 # Output: 4650 # Output: 5601 # The time string, e.g. "1901m16s" 4651 # The time string, e.g. "1901m16s" 5602 def ms2nice(val): 4652 def ms2nice(val): 5603 val = int(val) 4653 val = int(val) 5604 h = val // 3600000 !! 4654 h = val / 3600000 5605 m = (val // 60000) % 60 !! 4655 m = (val / 60000) % 60 5606 s = (val // 1000) % 60 !! 4656 s = (val / 1000) % 60 5607 if h > 0: 4657 if h > 0: 5608 return '%d:%02d:%02d' % (h, m 4658 return '%d:%02d:%02d' % (h, m, s) 5609 if m > 0: 4659 if m > 0: 5610 return '%02d:%02d' % (m, s) 4660 return '%02d:%02d' % (m, s) 5611 return '%ds' % s 4661 return '%ds' % s 5612 4662 5613 def yesno(val): 4663 def yesno(val): 5614 list = {'enabled':'A', 'disabled':'S' 4664 list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D', 5615 'active':'A', 'suspended':'S' 4665 'active':'A', 'suspended':'S', 'suspending':'S'} 5616 if val not in list: 4666 if val not in list: 5617 return ' ' 4667 return ' ' 5618 return list[val] 4668 return list[val] 5619 4669 5620 # Function: deviceInfo 4670 # Function: deviceInfo 5621 # Description: 4671 # Description: 5622 # Detect all the USB hosts and devices 4672 # Detect all the USB hosts and devices currently connected and add 5623 # a list of USB device names to sysval 4673 # a list of USB device names to sysvals for better timeline readability 5624 def deviceInfo(output=''): 4674 def deviceInfo(output=''): 5625 if not output: 4675 if not output: 5626 pprint('LEGEND\n'\ !! 4676 print('LEGEND') 5627 '---------------------------- !! 4677 print('---------------------------------------------------------------------------------------------') 5628 ' A = async/sync PM queue (A !! 4678 print(' A = async/sync PM queue (A/S) C = runtime active children') 5629 ' R = runtime suspend enable !! 4679 print(' R = runtime suspend enabled/disabled (E/D) rACTIVE = runtime active (min/sec)') 5630 ' S = runtime status active/ !! 4680 print(' S = runtime status active/suspended (A/S) rSUSPEND = runtime suspend (min/sec)') 5631 ' U = runtime usage count\n' !! 4681 print(' U = runtime usage count') 5632 '---------------------------- !! 4682 print('---------------------------------------------------------------------------------------------') 5633 'DEVICE N !! 4683 print('DEVICE NAME A R S U C rACTIVE rSUSPEND') 5634 '---------------------------- !! 4684 print('---------------------------------------------------------------------------------------------') 5635 4685 5636 res = [] 4686 res = [] 5637 tgtval = 'runtime_status' 4687 tgtval = 'runtime_status' 5638 lines = dict() 4688 lines = dict() 5639 for dirname, dirnames, filenames in o 4689 for dirname, dirnames, filenames in os.walk('/sys/devices'): 5640 if(not re.match(r'.*/power', !! 4690 if(not re.match('.*/power', dirname) or 5641 'control' not in file 4691 'control' not in filenames or 5642 tgtval not in filenam 4692 tgtval not in filenames): 5643 continue 4693 continue 5644 name = '' 4694 name = '' 5645 dirname = dirname[:-6] 4695 dirname = dirname[:-6] 5646 device = dirname.split('/')[- 4696 device = dirname.split('/')[-1] 5647 power = dict() 4697 power = dict() 5648 power[tgtval] = readFile('%s/ 4698 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval)) 5649 # only list devices which sup 4699 # only list devices which support runtime suspend 5650 if power[tgtval] not in ['act 4700 if power[tgtval] not in ['active', 'suspended', 'suspending']: 5651 continue 4701 continue 5652 for i in ['product', 'driver' 4702 for i in ['product', 'driver', 'subsystem']: 5653 file = '%s/%s' % (dir 4703 file = '%s/%s' % (dirname, i) 5654 if os.path.exists(fil 4704 if os.path.exists(file): 5655 name = readFi 4705 name = readFile(file) 5656 break 4706 break 5657 for i in ['async', 'control', 4707 for i in ['async', 'control', 'runtime_status', 'runtime_usage', 5658 'runtime_active_kids' 4708 'runtime_active_kids', 'runtime_active_time', 5659 'runtime_suspended_ti 4709 'runtime_suspended_time']: 5660 if i in filenames: 4710 if i in filenames: 5661 power[i] = re 4711 power[i] = readFile('%s/power/%s' % (dirname, i)) 5662 if output: 4712 if output: 5663 if power['control'] = 4713 if power['control'] == output: 5664 res.append('% 4714 res.append('%s/power/control' % dirname) 5665 continue 4715 continue 5666 lines[dirname] = '%-26s %-26s 4716 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \ 5667 (device[:26], name[:2 4717 (device[:26], name[:26], 5668 yesno(power['async']) 4718 yesno(power['async']), \ 5669 yesno(power['control' 4719 yesno(power['control']), \ 5670 yesno(power['runtime_ 4720 yesno(power['runtime_status']), \ 5671 power['runtime_usage' 4721 power['runtime_usage'], \ 5672 power['runtime_active 4722 power['runtime_active_kids'], \ 5673 ms2nice(power['runtim 4723 ms2nice(power['runtime_active_time']), \ 5674 ms2nice(power['runtim 4724 ms2nice(power['runtime_suspended_time'])) 5675 for i in sorted(lines): 4725 for i in sorted(lines): 5676 print(lines[i]) !! 4726 print lines[i] 5677 return res 4727 return res 5678 4728 >> 4729 # Function: devProps >> 4730 # Description: >> 4731 # Retrieve a list of properties for all devices in the trace log >> 4732 def devProps(data=0): >> 4733 props = dict() >> 4734 >> 4735 if data: >> 4736 idx = data.index(': ') + 2 >> 4737 if idx >= len(data): >> 4738 return >> 4739 devlist = data[idx:].split(';') >> 4740 for dev in devlist: >> 4741 f = dev.split(',') >> 4742 if len(f) < 3: >> 4743 continue >> 4744 dev = f[0] >> 4745 props[dev] = DevProps() >> 4746 props[dev].altname = f[1] >> 4747 if int(f[2]): >> 4748 props[dev].async = True >> 4749 else: >> 4750 props[dev].async = False >> 4751 sysvals.devprops = props >> 4752 if sysvals.suspendmode == 'command' and 'testcommandstring' in props: >> 4753 sysvals.testcommand = props['testcommandstring'].altname >> 4754 return >> 4755 >> 4756 if(os.path.exists(sysvals.ftracefile) == False): >> 4757 doError('%s does not exist' % sysvals.ftracefile) >> 4758 >> 4759 # first get the list of devices we need properties for >> 4760 msghead = 'Additional data added by AnalyzeSuspend' >> 4761 alreadystamped = False >> 4762 tp = TestProps() >> 4763 tf = sysvals.openlog(sysvals.ftracefile, 'r') >> 4764 for line in tf: >> 4765 if msghead in line: >> 4766 alreadystamped = True >> 4767 continue >> 4768 # determine the trace data type (required for further parsing) >> 4769 m = re.match(sysvals.tracertypefmt, line) >> 4770 if(m): >> 4771 tp.setTracerType(m.group('t')) >> 4772 continue >> 4773 # parse only valid lines, if this is not one move on >> 4774 m = re.match(tp.ftrace_line_fmt, line) >> 4775 if(not m or 'device_pm_callback_start' not in line): >> 4776 continue >> 4777 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg')); >> 4778 if(not m): >> 4779 continue >> 4780 dev = m.group('d') >> 4781 if dev not in props: >> 4782 props[dev] = DevProps() >> 4783 tf.close() >> 4784 >> 4785 if not alreadystamped and sysvals.suspendmode == 'command': >> 4786 out = '#\n# '+msghead+'\n# Device Properties: ' >> 4787 out += 'testcommandstring,%s,0;' % (sysvals.testcommand) >> 4788 with sysvals.openlog(sysvals.ftracefile, 'a') as fp: >> 4789 fp.write(out+'\n') >> 4790 sysvals.devprops = props >> 4791 return >> 4792 >> 4793 # now get the syspath for each of our target devices >> 4794 for dirname, dirnames, filenames in os.walk('/sys/devices'): >> 4795 if(re.match('.*/power', dirname) and 'async' in filenames): >> 4796 dev = dirname.split('/')[-2] >> 4797 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): >> 4798 props[dev].syspath = dirname[:-6] >> 4799 >> 4800 # now fill in the properties for our target devices >> 4801 for dev in props: >> 4802 dirname = props[dev].syspath >> 4803 if not dirname or not os.path.exists(dirname): >> 4804 continue >> 4805 with open(dirname+'/power/async') as fp: >> 4806 text = fp.read() >> 4807 props[dev].async = False >> 4808 if 'enabled' in text: >> 4809 props[dev].async = True >> 4810 fields = os.listdir(dirname) >> 4811 if 'product' in fields: >> 4812 with open(dirname+'/product') as fp: >> 4813 props[dev].altname = fp.read() >> 4814 elif 'name' in fields: >> 4815 with open(dirname+'/name') as fp: >> 4816 props[dev].altname = fp.read() >> 4817 elif 'model' in fields: >> 4818 with open(dirname+'/model') as fp: >> 4819 props[dev].altname = fp.read() >> 4820 elif 'description' in fields: >> 4821 with open(dirname+'/description') as fp: >> 4822 props[dev].altname = fp.read() >> 4823 elif 'id' in fields: >> 4824 with open(dirname+'/id') as fp: >> 4825 props[dev].altname = fp.read() >> 4826 elif 'idVendor' in fields and 'idProduct' in fields: >> 4827 idv, idp = '', '' >> 4828 with open(dirname+'/idVendor') as fp: >> 4829 idv = fp.read().strip() >> 4830 with open(dirname+'/idProduct') as fp: >> 4831 idp = fp.read().strip() >> 4832 props[dev].altname = '%s:%s' % (idv, idp) >> 4833 >> 4834 if props[dev].altname: >> 4835 out = props[dev].altname.strip().replace('\n', ' ') >> 4836 out = out.replace(',', ' ') >> 4837 out = out.replace(';', ' ') >> 4838 props[dev].altname = out >> 4839 >> 4840 # and now write the data to the ftrace file >> 4841 if not alreadystamped: >> 4842 out = '#\n# '+msghead+'\n# Device Properties: ' >> 4843 for dev in sorted(props): >> 4844 out += props[dev].out(dev) >> 4845 with sysvals.openlog(sysvals.ftracefile, 'a') as fp: >> 4846 fp.write(out+'\n') >> 4847 >> 4848 sysvals.devprops = props >> 4849 5679 # Function: getModes 4850 # Function: getModes 5680 # Description: 4851 # Description: 5681 # Determine the supported power modes 4852 # Determine the supported power modes on this system 5682 # Output: 4853 # Output: 5683 # A string list of the available modes 4854 # A string list of the available modes 5684 def getModes(): 4855 def getModes(): 5685 modes = [] 4856 modes = [] 5686 if(os.path.exists(sysvals.powerfile)) 4857 if(os.path.exists(sysvals.powerfile)): 5687 fp = open(sysvals.powerfile, 4858 fp = open(sysvals.powerfile, 'r') 5688 modes = fp.read().split() !! 4859 modes = string.split(fp.read()) 5689 fp.close() 4860 fp.close() 5690 if(os.path.exists(sysvals.mempowerfil 4861 if(os.path.exists(sysvals.mempowerfile)): 5691 deep = False 4862 deep = False 5692 fp = open(sysvals.mempowerfil 4863 fp = open(sysvals.mempowerfile, 'r') 5693 for m in fp.read().split(): !! 4864 for m in string.split(fp.read()): 5694 memmode = m.strip('[] 4865 memmode = m.strip('[]') 5695 if memmode == 'deep': 4866 if memmode == 'deep': 5696 deep = True 4867 deep = True 5697 else: 4868 else: 5698 modes.append( 4869 modes.append('mem-%s' % memmode) 5699 fp.close() 4870 fp.close() 5700 if 'mem' in modes and not dee 4871 if 'mem' in modes and not deep: 5701 modes.remove('mem') 4872 modes.remove('mem') 5702 if('disk' in modes and os.path.exists << 5703 fp = open(sysvals.diskpowerfi << 5704 for m in fp.read().split(): << 5705 modes.append('disk-%s << 5706 fp.close() << 5707 return modes 4873 return modes 5708 4874 5709 def dmidecode_backup(out, fatal=False): << 5710 cpath, spath, info = '/proc/cpuinfo', << 5711 'bios-vendor': 'bios_vendor', << 5712 'bios-version': 'bios_version << 5713 'bios-release-date': 'bios_da << 5714 'system-manufacturer': 'sys_v << 5715 'system-product-name': 'produ << 5716 'system-version': 'product_ve << 5717 'system-serial-number': 'prod << 5718 'baseboard-manufacturer': 'bo << 5719 'baseboard-product-name': 'bo << 5720 'baseboard-version': 'board_v << 5721 'baseboard-serial-number': 'b << 5722 'chassis-manufacturer': 'chas << 5723 'chassis-version': 'chassis_v << 5724 'chassis-serial-number': 'cha << 5725 } << 5726 for key in info: << 5727 if key not in out: << 5728 val = sysvals.getVal( << 5729 if val and val.lower( << 5730 out[key] = va << 5731 if 'processor-version' not in out and << 5732 with open(cpath, 'r') as fp: << 5733 for line in fp: << 5734 m = re.match( << 5735 if m: << 5736 out[' << 5737 break << 5738 if fatal and len(out) < 1: << 5739 doError('dmidecode failed to << 5740 (sysvals.mempath, spa << 5741 return out << 5742 << 5743 # Function: dmidecode 4875 # Function: dmidecode 5744 # Description: 4876 # Description: 5745 # Read the bios tables and pull out sy 4877 # Read the bios tables and pull out system info 5746 # Arguments: 4878 # Arguments: 5747 # mempath: /dev/mem or custom mem path 4879 # mempath: /dev/mem or custom mem path 5748 # fatal: True to exit on error, False 4880 # fatal: True to exit on error, False to return empty dict 5749 # Output: 4881 # Output: 5750 # A dict object with all available key 4882 # A dict object with all available key/values 5751 def dmidecode(mempath, fatal=False): 4883 def dmidecode(mempath, fatal=False): 5752 out = dict() 4884 out = dict() 5753 if(not (os.path.exists(mempath) and o << 5754 return dmidecode_backup(out, << 5755 4885 5756 # the list of values to retrieve, wit 4886 # the list of values to retrieve, with hardcoded (type, idx) 5757 info = { 4887 info = { 5758 'bios-vendor': (0, 4), 4888 'bios-vendor': (0, 4), 5759 'bios-version': (0, 5), 4889 'bios-version': (0, 5), 5760 'bios-release-date': (0, 8), 4890 'bios-release-date': (0, 8), 5761 'system-manufacturer': (1, 4) 4891 'system-manufacturer': (1, 4), 5762 'system-product-name': (1, 5) 4892 'system-product-name': (1, 5), 5763 'system-version': (1, 6), 4893 'system-version': (1, 6), 5764 'system-serial-number': (1, 7 4894 'system-serial-number': (1, 7), 5765 'baseboard-manufacturer': (2, 4895 'baseboard-manufacturer': (2, 4), 5766 'baseboard-product-name': (2, 4896 'baseboard-product-name': (2, 5), 5767 'baseboard-version': (2, 6), 4897 'baseboard-version': (2, 6), 5768 'baseboard-serial-number': (2 4898 'baseboard-serial-number': (2, 7), 5769 'chassis-manufacturer': (3, 4 4899 'chassis-manufacturer': (3, 4), >> 4900 'chassis-type': (3, 5), 5770 'chassis-version': (3, 6), 4901 'chassis-version': (3, 6), 5771 'chassis-serial-number': (3, 4902 'chassis-serial-number': (3, 7), 5772 'processor-manufacturer': (4, 4903 'processor-manufacturer': (4, 7), 5773 'processor-version': (4, 16), 4904 'processor-version': (4, 16), 5774 } 4905 } >> 4906 if(not os.path.exists(mempath)): >> 4907 if(fatal): >> 4908 doError('file does not exist: %s' % mempath) >> 4909 return out >> 4910 if(not os.access(mempath, os.R_OK)): >> 4911 if(fatal): >> 4912 doError('file is not readable: %s' % mempath) >> 4913 return out 5775 4914 5776 # by default use legacy scan, but try 4915 # by default use legacy scan, but try to use EFI first 5777 memaddr, memsize = 0xf0000, 0x10000 !! 4916 memaddr = 0xf0000 >> 4917 memsize = 0x10000 5778 for ep in ['/sys/firmware/efi/systab' 4918 for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']: 5779 if not os.path.exists(ep) or 4919 if not os.path.exists(ep) or not os.access(ep, os.R_OK): 5780 continue 4920 continue 5781 fp = open(ep, 'r') 4921 fp = open(ep, 'r') 5782 buf = fp.read() 4922 buf = fp.read() 5783 fp.close() 4923 fp.close() 5784 i = buf.find('SMBIOS=') 4924 i = buf.find('SMBIOS=') 5785 if i >= 0: 4925 if i >= 0: 5786 try: 4926 try: 5787 memaddr = int 4927 memaddr = int(buf[i+7:], 16) 5788 memsize = 0x2 4928 memsize = 0x20 5789 except: 4929 except: 5790 continue 4930 continue 5791 4931 5792 # read in the memory for scanning 4932 # read in the memory for scanning >> 4933 fp = open(mempath, 'rb') 5793 try: 4934 try: 5794 fp = open(mempath, 'rb') << 5795 fp.seek(memaddr) 4935 fp.seek(memaddr) 5796 buf = fp.read(memsize) 4936 buf = fp.read(memsize) 5797 except: 4937 except: 5798 return dmidecode_backup(out, !! 4938 if(fatal): >> 4939 doError('DMI table is unreachable, sorry') >> 4940 else: >> 4941 return out 5799 fp.close() 4942 fp.close() 5800 4943 5801 # search for either an SM table or DM 4944 # search for either an SM table or DMI table 5802 i = base = length = num = 0 4945 i = base = length = num = 0 5803 while(i < memsize): 4946 while(i < memsize): 5804 if buf[i:i+4] == b'_SM_' and !! 4947 if buf[i:i+4] == '_SM_' and i < memsize - 16: 5805 length = struct.unpac 4948 length = struct.unpack('H', buf[i+22:i+24])[0] 5806 base, num = struct.un 4949 base, num = struct.unpack('IH', buf[i+24:i+30]) 5807 break 4950 break 5808 elif buf[i:i+5] == b'_DMI_': !! 4951 elif buf[i:i+5] == '_DMI_': 5809 length = struct.unpac 4952 length = struct.unpack('H', buf[i+6:i+8])[0] 5810 base, num = struct.un 4953 base, num = struct.unpack('IH', buf[i+8:i+14]) 5811 break 4954 break 5812 i += 16 4955 i += 16 5813 if base == 0 and length == 0 and num 4956 if base == 0 and length == 0 and num == 0: 5814 return dmidecode_backup(out, !! 4957 if(fatal): >> 4958 doError('Neither SMBIOS nor DMI were found') >> 4959 else: >> 4960 return out 5815 4961 5816 # read in the SM or DMI table 4962 # read in the SM or DMI table >> 4963 fp = open(mempath, 'rb') 5817 try: 4964 try: 5818 fp = open(mempath, 'rb') << 5819 fp.seek(base) 4965 fp.seek(base) 5820 buf = fp.read(length) 4966 buf = fp.read(length) 5821 except: 4967 except: 5822 return dmidecode_backup(out, !! 4968 if(fatal): >> 4969 doError('DMI table is unreachable, sorry') >> 4970 else: >> 4971 return out 5823 fp.close() 4972 fp.close() 5824 4973 5825 # scan the table for the values we wa 4974 # scan the table for the values we want 5826 count = i = 0 4975 count = i = 0 5827 while(count < num and i <= len(buf) - 4976 while(count < num and i <= len(buf) - 4): 5828 type, size, handle = struct.u 4977 type, size, handle = struct.unpack('BBH', buf[i:i+4]) 5829 n = i + size 4978 n = i + size 5830 while n < len(buf) - 1: 4979 while n < len(buf) - 1: 5831 if 0 == struct.unpack 4980 if 0 == struct.unpack('H', buf[n:n+2])[0]: 5832 break 4981 break 5833 n += 1 4982 n += 1 5834 data = buf[i+size:n+2].split( !! 4983 data = buf[i+size:n+2].split('\0') 5835 for name in info: 4984 for name in info: 5836 itype, idxadr = info[ 4985 itype, idxadr = info[name] 5837 if itype == type: 4986 if itype == type: 5838 idx = struct. !! 4987 idx = struct.unpack('B', buf[i+idxadr])[0] 5839 if idx > 0 an 4988 if idx > 0 and idx < len(data) - 1: 5840 s = d !! 4989 s = data[idx-1].strip() 5841 if s. !! 4990 if s and s.lower() != 'to be filled by o.e.m.': 5842 !! 4991 out[name] = data[idx-1] 5843 i = n + 2 4992 i = n + 2 5844 count += 1 4993 count += 1 5845 return out 4994 return out 5846 4995 >> 4996 def getBattery(): >> 4997 p = '/sys/class/power_supply' >> 4998 bat = dict() >> 4999 for d in os.listdir(p): >> 5000 type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower() >> 5001 if type != 'battery': >> 5002 continue >> 5003 for v in ['status', 'energy_now', 'capacity_now']: >> 5004 bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower() >> 5005 break >> 5006 ac = True >> 5007 if 'status' in bat and 'discharging' in bat['status']: >> 5008 ac = False >> 5009 charge = 0 >> 5010 for v in ['energy_now', 'capacity_now']: >> 5011 if v in bat and bat[v]: >> 5012 charge = int(bat[v]) >> 5013 return (ac, charge) >> 5014 5847 # Function: getFPDT 5015 # Function: getFPDT 5848 # Description: 5016 # Description: 5849 # Read the acpi bios tables and pull o 5017 # Read the acpi bios tables and pull out FPDT, the firmware data 5850 # Arguments: 5018 # Arguments: 5851 # output: True to output the info to s 5019 # output: True to output the info to stdout, False otherwise 5852 def getFPDT(output): 5020 def getFPDT(output): 5853 rectype = {} 5021 rectype = {} 5854 rectype[0] = 'Firmware Basic Boot Per 5022 rectype[0] = 'Firmware Basic Boot Performance Record' 5855 rectype[1] = 'S3 Performance Table Re 5023 rectype[1] = 'S3 Performance Table Record' 5856 prectype = {} 5024 prectype = {} 5857 prectype[0] = 'Basic S3 Resume Perfor 5025 prectype[0] = 'Basic S3 Resume Performance Record' 5858 prectype[1] = 'Basic S3 Suspend Perfo 5026 prectype[1] = 'Basic S3 Suspend Performance Record' 5859 5027 5860 sysvals.rootCheck(True) 5028 sysvals.rootCheck(True) 5861 if(not os.path.exists(sysvals.fpdtpat 5029 if(not os.path.exists(sysvals.fpdtpath)): 5862 if(output): 5030 if(output): 5863 doError('file does no 5031 doError('file does not exist: %s' % sysvals.fpdtpath) 5864 return False 5032 return False 5865 if(not os.access(sysvals.fpdtpath, os 5033 if(not os.access(sysvals.fpdtpath, os.R_OK)): 5866 if(output): 5034 if(output): 5867 doError('file is not 5035 doError('file is not readable: %s' % sysvals.fpdtpath) 5868 return False 5036 return False 5869 if(not os.path.exists(sysvals.mempath 5037 if(not os.path.exists(sysvals.mempath)): 5870 if(output): 5038 if(output): 5871 doError('file does no 5039 doError('file does not exist: %s' % sysvals.mempath) 5872 return False 5040 return False 5873 if(not os.access(sysvals.mempath, os. 5041 if(not os.access(sysvals.mempath, os.R_OK)): 5874 if(output): 5042 if(output): 5875 doError('file is not 5043 doError('file is not readable: %s' % sysvals.mempath) 5876 return False 5044 return False 5877 5045 5878 fp = open(sysvals.fpdtpath, 'rb') 5046 fp = open(sysvals.fpdtpath, 'rb') 5879 buf = fp.read() 5047 buf = fp.read() 5880 fp.close() 5048 fp.close() 5881 5049 5882 if(len(buf) < 36): 5050 if(len(buf) < 36): 5883 if(output): 5051 if(output): 5884 doError('Invalid FPDT 5052 doError('Invalid FPDT table data, should '+\ 5885 'be at least 5053 'be at least 36 bytes') 5886 return False 5054 return False 5887 5055 5888 table = struct.unpack('4sIBB6s8sI4sI' 5056 table = struct.unpack('4sIBB6s8sI4sI', buf[0:36]) 5889 if(output): 5057 if(output): 5890 pprint('\n'\ !! 5058 print('') 5891 'Firmware Performance Data Ta !! 5059 print('Firmware Performance Data Table (%s)' % table[0]) 5892 ' Signature !! 5060 print(' Signature : %s' % table[0]) 5893 ' Table Length !! 5061 print(' Table Length : %u' % table[1]) 5894 ' Revision !! 5062 print(' Revision : %u' % table[2]) 5895 ' Checksum !! 5063 print(' Checksum : 0x%x' % table[3]) 5896 ' OEM ID !! 5064 print(' OEM ID : %s' % table[4]) 5897 ' OEM Table ID !! 5065 print(' OEM Table ID : %s' % table[5]) 5898 ' OEM Revision !! 5066 print(' OEM Revision : %u' % table[6]) 5899 ' Creator ID !! 5067 print(' Creator ID : %s' % table[7]) 5900 ' Creator Revision !! 5068 print(' Creator Revision : 0x%x' % table[8]) 5901 '' % (ascii(table[0]), ascii( !! 5069 print('') 5902 table[3], ascii(table << 5903 ascii(table[7]), tabl << 5904 5070 5905 if(table[0] != b'FPDT'): !! 5071 if(table[0] != 'FPDT'): 5906 if(output): 5072 if(output): 5907 doError('Invalid FPDT 5073 doError('Invalid FPDT table') 5908 return False 5074 return False 5909 if(len(buf) <= 36): 5075 if(len(buf) <= 36): 5910 return False 5076 return False 5911 i = 0 5077 i = 0 5912 fwData = [0, 0] 5078 fwData = [0, 0] 5913 records = buf[36:] 5079 records = buf[36:] 5914 try: !! 5080 fp = open(sysvals.mempath, 'rb') 5915 fp = open(sysvals.mempath, 'r << 5916 except: << 5917 pprint('WARNING: /dev/mem is << 5918 return False << 5919 while(i < len(records)): 5081 while(i < len(records)): 5920 header = struct.unpack('HBB', 5082 header = struct.unpack('HBB', records[i:i+4]) 5921 if(header[0] not in rectype): 5083 if(header[0] not in rectype): 5922 i += header[1] 5084 i += header[1] 5923 continue 5085 continue 5924 if(header[1] != 16): 5086 if(header[1] != 16): 5925 i += header[1] 5087 i += header[1] 5926 continue 5088 continue 5927 addr = struct.unpack('Q', rec 5089 addr = struct.unpack('Q', records[i+8:i+16])[0] 5928 try: 5090 try: 5929 fp.seek(addr) 5091 fp.seek(addr) 5930 first = fp.read(8) 5092 first = fp.read(8) 5931 except: 5093 except: 5932 if(output): 5094 if(output): 5933 pprint('Bad a !! 5095 print('Bad address 0x%x in %s' % (addr, sysvals.mempath)) 5934 return [0, 0] 5096 return [0, 0] 5935 rechead = struct.unpack('4sI' 5097 rechead = struct.unpack('4sI', first) 5936 recdata = fp.read(rechead[1]- 5098 recdata = fp.read(rechead[1]-8) 5937 if(rechead[0] == b'FBPT'): !! 5099 if(rechead[0] == 'FBPT'): 5938 record = struct.unpac !! 5100 record = struct.unpack('HBBIQQQQQ', recdata) 5939 if(output): 5101 if(output): 5940 pprint('%s (% !! 5102 print('%s (%s)' % (rectype[header[0]], rechead[0])) 5941 ' !! 5103 print(' Reset END : %u ns' % record[4]) 5942 ' OS Loader !! 5104 print(' OS Loader LoadImage Start : %u ns' % record[5]) 5943 ' OS Loader S !! 5105 print(' OS Loader StartImage Start : %u ns' % record[6]) 5944 ' ExitBoo !! 5106 print(' ExitBootServices Entry : %u ns' % record[7]) 5945 ' ExitBo !! 5107 print(' ExitBootServices Exit : %u ns' % record[8]) 5946 '' % (rectype !! 5108 elif(rechead[0] == 'S3PT'): 5947 recor << 5948 elif(rechead[0] == b'S3PT'): << 5949 if(output): 5109 if(output): 5950 pprint('%s (% !! 5110 print('%s (%s)' % (rectype[header[0]], rechead[0])) 5951 j = 0 5111 j = 0 5952 while(j < len(recdata 5112 while(j < len(recdata)): 5953 prechead = st 5113 prechead = struct.unpack('HBB', recdata[j:j+4]) 5954 if(prechead[0 5114 if(prechead[0] not in prectype): 5955 conti 5115 continue 5956 if(prechead[0 5116 if(prechead[0] == 0): 5957 recor 5117 record = struct.unpack('IIQQ', recdata[j:j+prechead[1]]) 5958 fwDat 5118 fwData[1] = record[2] 5959 if(ou 5119 if(output): 5960 !! 5120 print(' %s' % prectype[prechead[0]]) 5961 !! 5121 print(' Resume Count : %u' % \ 5962 !! 5122 record[1]) 5963 !! 5123 print(' FullResume : %u ns' % \ 5964 !! 5124 record[2]) 5965 !! 5125 print(' AverageResume : %u ns' % \ >> 5126 record[3]) 5966 elif(prechead 5127 elif(prechead[0] == 1): 5967 recor 5128 record = struct.unpack('QQ', recdata[j+4:j+prechead[1]]) 5968 fwDat 5129 fwData[0] = record[1] - record[0] 5969 if(ou 5130 if(output): 5970 !! 5131 print(' %s' % prectype[prechead[0]]) 5971 !! 5132 print(' SuspendStart : %u ns' % \ 5972 !! 5133 record[0]) 5973 !! 5134 print(' SuspendEnd : %u ns' % \ 5974 !! 5135 record[1]) 5975 !! 5136 print(' SuspendTime : %u ns' % \ 5976 !! 5137 fwData[0]) 5977 j += prechead 5138 j += prechead[1] 5978 if(output): 5139 if(output): 5979 pprint('') !! 5140 print('') 5980 i += header[1] 5141 i += header[1] 5981 fp.close() 5142 fp.close() 5982 return fwData 5143 return fwData 5983 5144 5984 # Function: statusCheck 5145 # Function: statusCheck 5985 # Description: 5146 # Description: 5986 # Verify that the requested command an 5147 # Verify that the requested command and options will work, and 5987 # print the results to the terminal 5148 # print the results to the terminal 5988 # Output: 5149 # Output: 5989 # True if the test will work, False if 5150 # True if the test will work, False if not 5990 def statusCheck(probecheck=False): 5151 def statusCheck(probecheck=False): 5991 status = '' !! 5152 status = True 5992 5153 5993 pprint('Checking this system (%s)...' !! 5154 print('Checking this system (%s)...' % platform.node()) 5994 5155 5995 # check we have root access 5156 # check we have root access 5996 res = sysvals.colorText('NO (No featu 5157 res = sysvals.colorText('NO (No features of this tool will work!)') 5997 if(sysvals.rootCheck(False)): 5158 if(sysvals.rootCheck(False)): 5998 res = 'YES' 5159 res = 'YES' 5999 pprint(' have root access: %s' % r !! 5160 print(' have root access: %s' % res) 6000 if(res != 'YES'): 5161 if(res != 'YES'): 6001 pprint(' Try running this !! 5162 print(' Try running this script with sudo') 6002 return 'missing root access' !! 5163 return False 6003 5164 6004 # check sysfs is mounted 5165 # check sysfs is mounted 6005 res = sysvals.colorText('NO (No featu 5166 res = sysvals.colorText('NO (No features of this tool will work!)') 6006 if(os.path.exists(sysvals.powerfile)) 5167 if(os.path.exists(sysvals.powerfile)): 6007 res = 'YES' 5168 res = 'YES' 6008 pprint(' is sysfs mounted: %s' % r !! 5169 print(' is sysfs mounted: %s' % res) 6009 if(res != 'YES'): 5170 if(res != 'YES'): 6010 return 'sysfs is missing' !! 5171 return False 6011 5172 6012 # check target mode is a valid mode 5173 # check target mode is a valid mode 6013 if sysvals.suspendmode != 'command': 5174 if sysvals.suspendmode != 'command': 6014 res = sysvals.colorText('NO') 5175 res = sysvals.colorText('NO') 6015 modes = getModes() 5176 modes = getModes() 6016 if(sysvals.suspendmode in mod 5177 if(sysvals.suspendmode in modes): 6017 res = 'YES' 5178 res = 'YES' 6018 else: 5179 else: 6019 status = '%s mode is !! 5180 status = False 6020 pprint(' is "%s" a valid p !! 5181 print(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res)) 6021 if(res == 'NO'): 5182 if(res == 'NO'): 6022 pprint(' valid p !! 5183 print(' valid power modes are: %s' % modes) 6023 pprint(' please !! 5184 print(' please choose one with -m') 6024 5185 6025 # check if ftrace is available 5186 # check if ftrace is available 6026 if sysvals.useftrace: !! 5187 res = sysvals.colorText('NO') 6027 res = sysvals.colorText('NO') !! 5188 ftgood = sysvals.verifyFtrace() 6028 sysvals.useftrace = sysvals.v !! 5189 if(ftgood): 6029 efmt = '"{0}" uses ftrace, an !! 5190 res = 'YES' 6030 if sysvals.useftrace: !! 5191 elif(sysvals.usecallgraph): 6031 res = 'YES' !! 5192 status = False 6032 elif sysvals.usecallgraph: !! 5193 print(' is ftrace supported: %s' % res) 6033 status = efmt.format( << 6034 elif sysvals.usedevsrc: << 6035 status = efmt.format( << 6036 elif sysvals.useprocmon: << 6037 status = efmt.format( << 6038 pprint(' is ftrace support << 6039 5194 6040 # check if kprobes are available 5195 # check if kprobes are available 6041 if sysvals.usekprobes: !! 5196 res = sysvals.colorText('NO') 6042 res = sysvals.colorText('NO') !! 5197 sysvals.usekprobes = sysvals.verifyKprobes() 6043 sysvals.usekprobes = sysvals. !! 5198 if(sysvals.usekprobes): 6044 if(sysvals.usekprobes): !! 5199 res = 'YES' 6045 res = 'YES' !! 5200 else: 6046 else: !! 5201 sysvals.usedevsrc = False 6047 sysvals.usedevsrc = F !! 5202 print(' are kprobes supported: %s' % res) 6048 pprint(' are kprobes suppo << 6049 5203 6050 # what data source are we using 5204 # what data source are we using 6051 res = 'DMESG (very limited, ftrace is !! 5205 res = 'DMESG' 6052 if sysvals.useftrace: !! 5206 if(ftgood): 6053 sysvals.usetraceevents = True 5207 sysvals.usetraceevents = True 6054 for e in sysvals.traceevents: 5208 for e in sysvals.traceevents: 6055 if not os.path.exists 5209 if not os.path.exists(sysvals.epath+e): 6056 sysvals.usetr 5210 sysvals.usetraceevents = False 6057 if(sysvals.usetraceevents): 5211 if(sysvals.usetraceevents): 6058 res = 'FTRACE (all tr 5212 res = 'FTRACE (all trace events found)' 6059 pprint(' timeline data source: %s' !! 5213 print(' timeline data source: %s' % res) 6060 5214 6061 # check if rtcwake 5215 # check if rtcwake 6062 res = sysvals.colorText('NO') 5216 res = sysvals.colorText('NO') 6063 if(sysvals.rtcpath != ''): 5217 if(sysvals.rtcpath != ''): 6064 res = 'YES' 5218 res = 'YES' 6065 elif(sysvals.rtcwake): 5219 elif(sysvals.rtcwake): 6066 status = 'rtcwake is not prop !! 5220 status = False 6067 pprint(' is rtcwake supported: %s' !! 5221 print(' is rtcwake supported: %s' % res) 6068 << 6069 # check info commands << 6070 pprint(' optional commands this to << 6071 no = sysvals.colorText('MISSING') << 6072 yes = sysvals.colorText('FOUND', 32) << 6073 for c in ['turbostat', 'mcelog', 'lsp << 6074 if c == 'turbostat': << 6075 res = yes if sysvals. << 6076 else: << 6077 res = yes if sysvals. << 6078 pprint(' %s: %s' % (c, << 6079 5222 6080 if not probecheck: 5223 if not probecheck: 6081 return status 5224 return status 6082 5225 6083 # verify kprobes 5226 # verify kprobes 6084 if sysvals.usekprobes: 5227 if sysvals.usekprobes: 6085 for name in sysvals.tracefunc 5228 for name in sysvals.tracefuncs: 6086 sysvals.defaultKprobe 5229 sysvals.defaultKprobe(name, sysvals.tracefuncs[name]) 6087 if sysvals.usedevsrc: 5230 if sysvals.usedevsrc: 6088 for name in sysvals.d 5231 for name in sysvals.dev_tracefuncs: 6089 sysvals.defau 5232 sysvals.defaultKprobe(name, sysvals.dev_tracefuncs[name]) 6090 sysvals.addKprobes(True) 5233 sysvals.addKprobes(True) 6091 5234 6092 return status 5235 return status 6093 5236 6094 # Function: doError 5237 # Function: doError 6095 # Description: 5238 # Description: 6096 # generic error function for catastrph 5239 # generic error function for catastrphic failures 6097 # Arguments: 5240 # Arguments: 6098 # msg: the error message to print 5241 # msg: the error message to print 6099 # help: True if printHelp should be ca 5242 # help: True if printHelp should be called after, False otherwise 6100 def doError(msg, help=False): 5243 def doError(msg, help=False): 6101 if(help == True): 5244 if(help == True): 6102 printHelp() 5245 printHelp() 6103 pprint('ERROR: %s\n' % msg) !! 5246 print('ERROR: %s\n') % msg 6104 sysvals.outputResult({'error':msg}) 5247 sysvals.outputResult({'error':msg}) 6105 sys.exit(1) !! 5248 sys.exit() 6106 5249 6107 # Function: getArgInt 5250 # Function: getArgInt 6108 # Description: 5251 # Description: 6109 # pull out an integer argument from th 5252 # pull out an integer argument from the command line with checks 6110 def getArgInt(name, args, min, max, main=True 5253 def getArgInt(name, args, min, max, main=True): 6111 if main: 5254 if main: 6112 try: 5255 try: 6113 arg = next(args) !! 5256 arg = args.next() 6114 except: 5257 except: 6115 doError(name+': no ar 5258 doError(name+': no argument supplied', True) 6116 else: 5259 else: 6117 arg = args 5260 arg = args 6118 try: 5261 try: 6119 val = int(arg) 5262 val = int(arg) 6120 except: 5263 except: 6121 doError(name+': non-integer v 5264 doError(name+': non-integer value given', True) 6122 if(val < min or val > max): 5265 if(val < min or val > max): 6123 doError(name+': value should 5266 doError(name+': value should be between %d and %d' % (min, max), True) 6124 return val 5267 return val 6125 5268 6126 # Function: getArgFloat 5269 # Function: getArgFloat 6127 # Description: 5270 # Description: 6128 # pull out a float argument from the c 5271 # pull out a float argument from the command line with checks 6129 def getArgFloat(name, args, min, max, main=Tr 5272 def getArgFloat(name, args, min, max, main=True): 6130 if main: 5273 if main: 6131 try: 5274 try: 6132 arg = next(args) !! 5275 arg = args.next() 6133 except: 5276 except: 6134 doError(name+': no ar 5277 doError(name+': no argument supplied', True) 6135 else: 5278 else: 6136 arg = args 5279 arg = args 6137 try: 5280 try: 6138 val = float(arg) 5281 val = float(arg) 6139 except: 5282 except: 6140 doError(name+': non-numerical 5283 doError(name+': non-numerical value given', True) 6141 if(val < min or val > max): 5284 if(val < min or val > max): 6142 doError(name+': value should 5285 doError(name+': value should be between %f and %f' % (min, max), True) 6143 return val 5286 return val 6144 5287 6145 def processData(live=False, quiet=False): !! 5288 def processData(live=False): 6146 if not quiet: !! 5289 print('PROCESSING DATA') 6147 pprint('PROCESSING: %s' % sys << 6148 sysvals.vprint('usetraceevents=%s, us << 6149 (sysvals.usetraceevents, sysv << 6150 error = '' 5290 error = '' 6151 if(sysvals.usetraceevents): 5291 if(sysvals.usetraceevents): 6152 testruns, error = parseTraceL 5292 testruns, error = parseTraceLog(live) 6153 if sysvals.dmesgfile: 5293 if sysvals.dmesgfile: 6154 for data in testruns: 5294 for data in testruns: 6155 data.extractE 5295 data.extractErrorInfo() 6156 else: 5296 else: 6157 testruns = loadKernelLog() 5297 testruns = loadKernelLog() 6158 for data in testruns: 5298 for data in testruns: 6159 parseKernelLog(data) 5299 parseKernelLog(data) 6160 if(sysvals.ftracefile and (sy 5300 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 6161 appendIncompleteTrace 5301 appendIncompleteTraceLog(testruns) 6162 if not sysvals.stamp: << 6163 pprint('ERROR: data does not << 6164 return (testruns, {'error': ' << 6165 shown = ['os', 'bios', 'biosdate', 'c << 6166 'memsz', 'mode', 'num << 6167 sysvals.vprint('System Info:') << 6168 for key in sorted(sysvals.stamp): << 6169 if key in shown: << 6170 sysvals.vprint(' % << 6171 sysvals.vprint('Command:\n %s' % s 5302 sysvals.vprint('Command:\n %s' % sysvals.cmdline) 6172 for data in testruns: 5303 for data in testruns: 6173 if data.turbostat: << 6174 idx, s = 0, 'Turbosta << 6175 for val in data.turbo << 6176 idx += len(va << 6177 if idx >= 80: << 6178 idx = << 6179 s += << 6180 s += val + ' << 6181 sysvals.vprint(s) << 6182 data.printDetails() 5304 data.printDetails() 6183 if len(sysvals.platinfo) > 0: << 6184 sysvals.vprint('\nPlatform In << 6185 for info in sysvals.platinfo: << 6186 sysvals.vprint('[%s - << 6187 sysvals.vprint(info[2 << 6188 sysvals.vprint('') << 6189 if sysvals.cgdump: 5305 if sysvals.cgdump: 6190 for data in testruns: 5306 for data in testruns: 6191 data.debugPrint() 5307 data.debugPrint() 6192 sys.exit(0) !! 5308 sys.exit() 6193 if len(testruns) < 1: 5309 if len(testruns) < 1: 6194 pprint('ERROR: Not enough tes << 6195 return (testruns, {'error': ' 5310 return (testruns, {'error': 'timeline generation failed'}) 6196 sysvals.vprint('Creating the html tim 5311 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile) 6197 createHTML(testruns, error) 5312 createHTML(testruns, error) 6198 if not quiet: !! 5313 print('DONE') 6199 pprint('DONE: %s' % sys << 6200 data = testruns[0] 5314 data = testruns[0] 6201 stamp = data.stamp 5315 stamp = data.stamp 6202 stamp['suspend'], stamp['resume'] = d 5316 stamp['suspend'], stamp['resume'] = data.getTimeValues() 6203 if data.fwValid: 5317 if data.fwValid: 6204 stamp['fwsuspend'], stamp['fw 5318 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume 6205 if error: 5319 if error: 6206 stamp['error'] = error 5320 stamp['error'] = error 6207 return (testruns, stamp) 5321 return (testruns, stamp) 6208 5322 6209 # Function: rerunTest 5323 # Function: rerunTest 6210 # Description: 5324 # Description: 6211 # generate an output from an existing 5325 # generate an output from an existing set of ftrace/dmesg logs 6212 def rerunTest(htmlfile=''): !! 5326 def rerunTest(): 6213 if sysvals.ftracefile: 5327 if sysvals.ftracefile: 6214 doesTraceLogHaveTraceEvents() 5328 doesTraceLogHaveTraceEvents() 6215 if not sysvals.dmesgfile and not sysv 5329 if not sysvals.dmesgfile and not sysvals.usetraceevents: 6216 doError('recreating this html 5330 doError('recreating this html output requires a dmesg file') 6217 if htmlfile: !! 5331 sysvals.setOutputFile() 6218 sysvals.htmlfile = htmlfile << 6219 else: << 6220 sysvals.setOutputFile() << 6221 if os.path.exists(sysvals.htmlfile): 5332 if os.path.exists(sysvals.htmlfile): 6222 if not os.path.isfile(sysvals 5333 if not os.path.isfile(sysvals.htmlfile): 6223 doError('a directory 5334 doError('a directory already exists with this name: %s' % sysvals.htmlfile) 6224 elif not os.access(sysvals.ht 5335 elif not os.access(sysvals.htmlfile, os.W_OK): 6225 doError('missing perm 5336 doError('missing permission to write to %s' % sysvals.htmlfile) 6226 testruns, stamp = processData() !! 5337 testruns, stamp = processData(False) 6227 sysvals.resetlog() << 6228 return stamp 5338 return stamp 6229 5339 6230 # Function: runTest 5340 # Function: runTest 6231 # Description: 5341 # Description: 6232 # execute a suspend/resume, gather the 5342 # execute a suspend/resume, gather the logs, and generate the output 6233 def runTest(n=0, quiet=False): !! 5343 def runTest(n=0): 6234 # prepare for the test 5344 # prepare for the test >> 5345 sysvals.initFtrace() 6235 sysvals.initTestOutput('suspend') 5346 sysvals.initTestOutput('suspend') 6236 op = sysvals.writeDatafileHeader(sysv << 6237 op.write('# EXECUTION TRACE START\n') << 6238 op.close() << 6239 if n <= 1: << 6240 if sysvals.rs != 0: << 6241 sysvals.dlog('%sablin << 6242 sysvals.setRuntimeSus << 6243 if sysvals.display: << 6244 ret = sysvals.display << 6245 sysvals.dlog('xset di << 6246 sysvals.testVal(sysvals.pmdpath, 'bas << 6247 sysvals.testVal(sysvals.s0ixpath, 'ba << 6248 sysvals.dlog('initialize ftrace') << 6249 sysvals.initFtrace(quiet) << 6250 5347 6251 # execute the test 5348 # execute the test 6252 executeSuspend(quiet) !! 5349 executeSuspend() 6253 sysvals.cleanupFtrace() 5350 sysvals.cleanupFtrace() 6254 if sysvals.skiphtml: 5351 if sysvals.skiphtml: 6255 sysvals.outputResult({}, n) !! 5352 sysvals.sudouser(sysvals.testdir) 6256 sysvals.sudoUserchown(sysvals << 6257 return 5353 return 6258 testruns, stamp = processData(True, q !! 5354 testruns, stamp = processData(True) 6259 for data in testruns: 5355 for data in testruns: 6260 del data 5356 del data 6261 sysvals.sudoUserchown(sysvals.testdir !! 5357 sysvals.sudouser(sysvals.testdir) 6262 sysvals.outputResult(stamp, n) 5358 sysvals.outputResult(stamp, n) 6263 if 'error' in stamp: << 6264 return 2 << 6265 return 0 << 6266 5359 6267 def find_in_html(html, start, end, firstonly= 5360 def find_in_html(html, start, end, firstonly=True): 6268 cnt, out, list = len(html), [], [] !! 5361 n, out = 0, [] 6269 if firstonly: !! 5362 while n < len(html): 6270 m = re.search(start, html) !! 5363 m = re.search(start, html[n:]) 6271 if m: !! 5364 if not m: 6272 list.append(m) !! 5365 break 6273 else: !! 5366 i = m.end() 6274 list = re.finditer(start, htm !! 5367 m = re.search(end, html[n+i:]) 6275 for match in list: << 6276 s = match.end() << 6277 e = cnt if (len(out) < 1 or s << 6278 m = re.search(end, html[s:e]) << 6279 if not m: 5368 if not m: 6280 break 5369 break 6281 e = s + m.start() !! 5370 j = m.start() 6282 str = html[s:e] !! 5371 str = html[n+i:n+i+j] 6283 if end == 'ms': 5372 if end == 'ms': 6284 num = re.search(r'[-+ 5373 num = re.search(r'[-+]?\d*\.\d+|\d+', str) 6285 str = num.group() if 5374 str = num.group() if num else 'NaN' 6286 if firstonly: 5375 if firstonly: 6287 return str 5376 return str 6288 out.append(str) 5377 out.append(str) >> 5378 n += i+j 6289 if firstonly: 5379 if firstonly: 6290 return '' 5380 return '' 6291 return out 5381 return out 6292 5382 6293 def data_from_html(file, outpath, issues, ful << 6294 try: << 6295 html = open(file, 'r').read() << 6296 except: << 6297 html = ascii(open(file, 'rb') << 6298 sysvals.htmlfile = os.path.relpath(fi << 6299 # extract general info << 6300 suspend = find_in_html(html, 'Kernel << 6301 resume = find_in_html(html, 'Kernel R << 6302 sysinfo = find_in_html(html, '<div cl << 6303 line = find_in_html(html, '<div class << 6304 stmp = line.split() << 6305 if not suspend or not resume or len(s << 6306 return False << 6307 try: << 6308 dt = datetime.strptime(' '.jo << 6309 except: << 6310 return False << 6311 sysvals.hostname = stmp[0] << 6312 tstr = dt.strftime('%Y/%m/%d %H:%M:%S << 6313 error = find_in_html(html, '<table cl << 6314 if error: << 6315 m = re.match(r'[a-z0-9]* fail << 6316 if m: << 6317 result = 'fail in %s' << 6318 else: << 6319 result = 'fail' << 6320 else: << 6321 result = 'pass' << 6322 # extract error info << 6323 tp, ilist = False, [] << 6324 extra = dict() << 6325 log = find_in_html(html, '<div id="dm << 6326 '</div>').strip() << 6327 if log: << 6328 d = Data(0) << 6329 d.end = 999999999 << 6330 d.dmesgtext = log.split('\n') << 6331 tp = d.extractErrorInfo() << 6332 if len(issues) < 100: << 6333 for msg in tp.msglist << 6334 sysvals.error << 6335 if stmp[2] == 'freeze': << 6336 extra = d.turbostatIn << 6337 elist = dict() << 6338 for dir in d.errorinfo: << 6339 for err in d.errorinf << 6340 if err[0] not << 6341 elist << 6342 elist[err[0]] << 6343 for i in elist: << 6344 ilist.append('%sx%d' << 6345 line = find_in_html(log, '# w << 6346 if line: << 6347 extra['wifi'] = line << 6348 line = find_in_html(log, '# n << 6349 if line: << 6350 extra['netfix'] = lin << 6351 line = find_in_html(log, '# c << 6352 if line: << 6353 m = re.match(r'.* -m << 6354 if m: << 6355 extra['fullmo << 6356 low = find_in_html(html, 'freeze time << 6357 for lowstr in ['waking', '+']: << 6358 if not low: << 6359 break << 6360 if lowstr not in low: << 6361 continue << 6362 if lowstr == '+': << 6363 issue = 'S2LOOPx%d' % << 6364 else: << 6365 m = re.match(r'.*waki << 6366 issue = 'S2WAKEx%s' % << 6367 match = [i for i in issues if << 6368 if len(match) > 0: << 6369 match[0]['count'] += << 6370 if sysvals.hostname n << 6371 match[0]['url << 6372 elif sysvals.htmlfile << 6373 match[0]['url << 6374 else: << 6375 issues.append({ << 6376 'match': issu << 6377 'urls': {sysv << 6378 }) << 6379 ilist.append(issue) << 6380 # extract device info << 6381 devices = dict() << 6382 for line in html.split('\n'): << 6383 m = re.match(r' *<div id=\"[a << 6384 if not m or 'thread kth' in l << 6385 continue << 6386 m = re.match(r'(?P<n>.*) \((? << 6387 if not m: << 6388 continue << 6389 name, time, phase = m.group(' << 6390 if name == 'async_synchronize << 6391 continue << 6392 if ' async' in name or ' sync << 6393 name = ' '.join(name. << 6394 if phase.startswith('suspend' << 6395 d = 'suspend' << 6396 elif phase.startswith('resume << 6397 d = 'resume' << 6398 else: << 6399 continue << 6400 if d not in devices: << 6401 devices[d] = dict() << 6402 if name not in devices[d]: << 6403 devices[d][name] = 0. << 6404 devices[d][name] += float(tim << 6405 # create worst device info << 6406 worst = dict() << 6407 for d in ['suspend', 'resume']: << 6408 worst[d] = {'name':'', 'time' << 6409 dev = devices[d] if d in devi << 6410 if dev and len(dev.keys()) > << 6411 n = sorted(dev, key=l << 6412 worst[d]['name'], wor << 6413 data = { << 6414 'mode': stmp[2], << 6415 'host': stmp[0], << 6416 'kernel': stmp[1], << 6417 'sysinfo': sysinfo, << 6418 'time': tstr, << 6419 'result': result, << 6420 'issues': ' '.join(ilist), << 6421 'suspend': suspend, << 6422 'resume': resume, << 6423 'devlist': devices, << 6424 'sus_worst': worst['suspend'] << 6425 'sus_worsttime': worst['suspe << 6426 'res_worst': worst['resume'][ << 6427 'res_worsttime': worst['resum << 6428 'url': sysvals.htmlfile, << 6429 } << 6430 for key in extra: << 6431 data[key] = extra[key] << 6432 if fulldetail: << 6433 data['funclist'] = find_in_ht << 6434 if tp: << 6435 for arg in ['-multi ', '-info << 6436 if arg in tp.cmdline: << 6437 data['target' << 6438 break << 6439 return data << 6440 << 6441 def genHtml(subdir, force=False): << 6442 for dirname, dirnames, filenames in o << 6443 sysvals.dmesgfile = sysvals.f << 6444 for filename in filenames: << 6445 file = os.path.join(d << 6446 if sysvals.usable(fil << 6447 if(re.match(r << 6448 sysva << 6449 elif(re.match << 6450 sysva << 6451 sysvals.setOutputFile() << 6452 if (sysvals.dmesgfile or sysv << 6453 (force or not sysvals << 6454 pprint('FTRACE: %s' % << 6455 if sysvals.dmesgfile: << 6456 pprint('DMESG << 6457 rerunTest() << 6458 << 6459 # Function: runSummary 5383 # Function: runSummary 6460 # Description: 5384 # Description: 6461 # create a summary of tests in a sub-d 5385 # create a summary of tests in a sub-directory 6462 def runSummary(subdir, local=True, genhtml=Fa 5386 def runSummary(subdir, local=True, genhtml=False): 6463 inpath = os.path.abspath(subdir) 5387 inpath = os.path.abspath(subdir) 6464 outpath = os.path.abspath('.') if loc !! 5388 outpath = inpath 6465 pprint('Generating a summary of folde !! 5389 if local: >> 5390 outpath = os.path.abspath('.') >> 5391 print('Generating a summary of folder "%s"' % inpath) 6466 if genhtml: 5392 if genhtml: 6467 genHtml(subdir) !! 5393 for dirname, dirnames, filenames in os.walk(subdir): 6468 target, issues, testruns = '', [], [] !! 5394 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = '' 6469 desc = {'host':[],'mode':[],'kernel': !! 5395 for filename in filenames: >> 5396 if(re.match('.*_dmesg.txt', filename)): >> 5397 sysvals.dmesgfile = os.path.join(dirname, filename) >> 5398 elif(re.match('.*_ftrace.txt', filename)): >> 5399 sysvals.ftracefile = os.path.join(dirname, filename) >> 5400 sysvals.setOutputFile() >> 5401 if sysvals.ftracefile and sysvals.htmlfile and \ >> 5402 not os.path.exists(sysvals.htmlfile): >> 5403 print('FTRACE: %s' % sysvals.ftracefile) >> 5404 if sysvals.dmesgfile: >> 5405 print('DMESG : %s' % sysvals.dmesgfile) >> 5406 rerunTest() >> 5407 testruns = [] 6470 for dirname, dirnames, filenames in o 5408 for dirname, dirnames, filenames in os.walk(subdir): 6471 for filename in filenames: 5409 for filename in filenames: 6472 if(not re.match(r'.*. !! 5410 if(not re.match('.*.html', filename)): 6473 continue 5411 continue 6474 data = data_from_html !! 5412 file = os.path.join(dirname, filename) 6475 if(not data): !! 5413 html = open(file, 'r').read() >> 5414 suspend = find_in_html(html, 'Kernel Suspend', 'ms') >> 5415 resume = find_in_html(html, 'Kernel Resume', 'ms') >> 5416 line = find_in_html(html, '<div class="stamp">', '</div>') >> 5417 stmp = line.split() >> 5418 if not suspend or not resume or len(stmp) != 8: >> 5419 continue >> 5420 try: >> 5421 dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p') >> 5422 except: 6476 continue 5423 continue 6477 if 'target' in data: !! 5424 tstr = dt.strftime('%Y/%m/%d %H:%M:%S') 6478 target = data !! 5425 error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>') >> 5426 result = 'fail' if error else 'pass' >> 5427 ilist = [] >> 5428 e = find_in_html(html, 'class="err"[\w=":;\.%\- ]*>', '→</div>', False) >> 5429 for i in list(set(e)): >> 5430 ilist.append('%sx%d' % (i, e.count(i)) if e.count(i) > 1 else i) >> 5431 data = { >> 5432 'mode': stmp[2], >> 5433 'host': stmp[0], >> 5434 'kernel': stmp[1], >> 5435 'time': tstr, >> 5436 'result': result, >> 5437 'issues': ','.join(ilist), >> 5438 'suspend': suspend, >> 5439 'resume': resume, >> 5440 'url': os.path.relpath(file, outpath), >> 5441 } 6479 testruns.append(data) 5442 testruns.append(data) 6480 for key in desc: !! 5443 outfile = os.path.join(outpath, 'summary.html') 6481 if data[key] !! 5444 print('Summary file: %s' % outfile) 6482 desc[ !! 5445 createHTMLSummarySimple(testruns, outfile, inpath) 6483 pprint('Summary files:') << 6484 if len(desc['host']) == len(desc['mod << 6485 title = '%s %s %s' % (desc['h << 6486 if target: << 6487 title += ' %s' % targ << 6488 else: << 6489 title = inpath << 6490 createHTMLSummarySimple(testruns, os. << 6491 pprint(' summary.html - tab << 6492 createHTMLDeviceSummary(testruns, os. << 6493 pprint(' summary-devices.html - ker << 6494 createHTMLIssuesSummary(testruns, iss << 6495 pprint(' summary-issues.html - ker << 6496 5446 6497 # Function: checkArgBool 5447 # Function: checkArgBool 6498 # Description: 5448 # Description: 6499 # check if a boolean string value is t 5449 # check if a boolean string value is true or false 6500 def checkArgBool(name, value): 5450 def checkArgBool(name, value): 6501 if value in switchvalues: 5451 if value in switchvalues: 6502 if value in switchoff: 5452 if value in switchoff: 6503 return False 5453 return False 6504 return True 5454 return True 6505 doError('invalid boolean --> (%s: %s) 5455 doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True) 6506 return False 5456 return False 6507 5457 6508 # Function: configFromFile 5458 # Function: configFromFile 6509 # Description: 5459 # Description: 6510 # Configure the script via the info in 5460 # Configure the script via the info in a config file 6511 def configFromFile(file): 5461 def configFromFile(file): 6512 Config = configparser.ConfigParser() !! 5462 Config = ConfigParser.ConfigParser() 6513 5463 6514 Config.read(file) 5464 Config.read(file) 6515 sections = Config.sections() 5465 sections = Config.sections() 6516 overridekprobes = False 5466 overridekprobes = False 6517 overridedevkprobes = False 5467 overridedevkprobes = False 6518 if 'Settings' in sections: 5468 if 'Settings' in sections: 6519 for opt in Config.options('Se 5469 for opt in Config.options('Settings'): 6520 value = Config.get('S 5470 value = Config.get('Settings', opt).lower() 6521 option = opt.lower() 5471 option = opt.lower() 6522 if(option == 'verbose 5472 if(option == 'verbose'): 6523 sysvals.verbo 5473 sysvals.verbose = checkArgBool(option, value) 6524 elif(option == 'addlo 5474 elif(option == 'addlogs'): 6525 sysvals.dmesg 5475 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value) 6526 elif(option == 'dev') 5476 elif(option == 'dev'): 6527 sysvals.usede 5477 sysvals.usedevsrc = checkArgBool(option, value) 6528 elif(option == 'proc' 5478 elif(option == 'proc'): 6529 sysvals.usepr 5479 sysvals.useprocmon = checkArgBool(option, value) 6530 elif(option == 'x2'): 5480 elif(option == 'x2'): 6531 if checkArgBo 5481 if checkArgBool(option, value): 6532 sysva 5482 sysvals.execcount = 2 6533 elif(option == 'callg 5483 elif(option == 'callgraph'): 6534 sysvals.useca 5484 sysvals.usecallgraph = checkArgBool(option, value) 6535 elif(option == 'overr 5485 elif(option == 'override-timeline-functions'): 6536 overridekprob 5486 overridekprobes = checkArgBool(option, value) 6537 elif(option == 'overr 5487 elif(option == 'override-dev-timeline-functions'): 6538 overridedevkp 5488 overridedevkprobes = checkArgBool(option, value) 6539 elif(option == 'skiph 5489 elif(option == 'skiphtml'): 6540 sysvals.skiph 5490 sysvals.skiphtml = checkArgBool(option, value) 6541 elif(option == 'sync' 5491 elif(option == 'sync'): 6542 sysvals.sync 5492 sysvals.sync = checkArgBool(option, value) 6543 elif(option == 'rs' o 5493 elif(option == 'rs' or option == 'runtimesuspend'): 6544 if value in s 5494 if value in switchvalues: 6545 if va 5495 if value in switchoff: 6546 5496 sysvals.rs = -1 6547 else: 5497 else: 6548 5498 sysvals.rs = 1 6549 else: 5499 else: 6550 doErr 5500 doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True) 6551 elif(option == 'displ 5501 elif(option == 'display'): 6552 disopt = ['on !! 5502 if value in switchvalues: 6553 if value not !! 5503 if value in switchoff: 6554 doErr !! 5504 sysvals.display = -1 6555 sysvals.displ !! 5505 else: >> 5506 sysvals.display = 1 >> 5507 else: >> 5508 doError('invalid value --> (%s: %s), use "on/off"' % (option, value), True) 6556 elif(option == 'gzip' 5509 elif(option == 'gzip'): 6557 sysvals.gzip 5510 sysvals.gzip = checkArgBool(option, value) 6558 elif(option == 'cgfil 5511 elif(option == 'cgfilter'): 6559 sysvals.setCa 5512 sysvals.setCallgraphFilter(value) 6560 elif(option == 'cgski 5513 elif(option == 'cgskip'): 6561 if value in s 5514 if value in switchoff: 6562 sysva 5515 sysvals.cgskip = '' 6563 else: 5516 else: 6564 sysva 5517 sysvals.cgskip = sysvals.configFile(val) 6565 if(no 5518 if(not sysvals.cgskip): 6566 5519 doError('%s does not exist' % sysvals.cgskip) 6567 elif(option == 'cgtes 5520 elif(option == 'cgtest'): 6568 sysvals.cgtes 5521 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False) 6569 elif(option == 'cgpha 5522 elif(option == 'cgphase'): 6570 d = Data(0) 5523 d = Data(0) 6571 if value not !! 5524 if value not in d.phases: 6572 doErr 5525 doError('invalid phase --> (%s: %s), valid phases are %s'\ 6573 !! 5526 % (option, value, d.phases), True) 6574 sysvals.cgpha 5527 sysvals.cgphase = value 6575 elif(option == 'fadd' 5528 elif(option == 'fadd'): 6576 file = sysval 5529 file = sysvals.configFile(value) 6577 if(not file): 5530 if(not file): 6578 doErr 5531 doError('%s does not exist' % value) 6579 sysvals.addFt 5532 sysvals.addFtraceFilterFunctions(file) 6580 elif(option == 'resul 5533 elif(option == 'result'): 6581 sysvals.resul 5534 sysvals.result = value 6582 elif(option == 'multi 5535 elif(option == 'multi'): 6583 nums = value. 5536 nums = value.split() 6584 if len(nums) 5537 if len(nums) != 2: 6585 doErr 5538 doError('multi requires 2 integers (exec_count and delay)', True) 6586 sysvals.multi !! 5539 sysvals.multitest['run'] = True >> 5540 sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False) >> 5541 sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False) 6587 elif(option == 'devic 5542 elif(option == 'devicefilter'): 6588 sysvals.setDe 5543 sysvals.setDeviceFilter(value) 6589 elif(option == 'expan 5544 elif(option == 'expandcg'): 6590 sysvals.cgexp 5545 sysvals.cgexp = checkArgBool(option, value) 6591 elif(option == 'srgap 5546 elif(option == 'srgap'): 6592 if checkArgBo 5547 if checkArgBool(option, value): 6593 sysva 5548 sysvals.srgap = 5 6594 elif(option == 'mode' 5549 elif(option == 'mode'): 6595 sysvals.suspe 5550 sysvals.suspendmode = value 6596 elif(option == 'comma 5551 elif(option == 'command' or option == 'cmd'): 6597 sysvals.testc 5552 sysvals.testcommand = value 6598 elif(option == 'x2del 5553 elif(option == 'x2delay'): 6599 sysvals.x2del 5554 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False) 6600 elif(option == 'prede 5555 elif(option == 'predelay'): 6601 sysvals.prede 5556 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False) 6602 elif(option == 'postd 5557 elif(option == 'postdelay'): 6603 sysvals.postd 5558 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False) 6604 elif(option == 'maxde 5559 elif(option == 'maxdepth'): 6605 sysvals.max_g 5560 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False) 6606 elif(option == 'rtcwa 5561 elif(option == 'rtcwake'): 6607 if value in s 5562 if value in switchoff: 6608 sysva 5563 sysvals.rtcwake = False 6609 else: 5564 else: 6610 sysva 5565 sysvals.rtcwake = True 6611 sysva 5566 sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False) 6612 elif(option == 'timep 5567 elif(option == 'timeprec'): 6613 sysvals.setPr 5568 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False)) 6614 elif(option == 'minde 5569 elif(option == 'mindev'): 6615 sysvals.minde 5570 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False) 6616 elif(option == 'calll 5571 elif(option == 'callloop-maxgap'): 6617 sysvals.calll 5572 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False) 6618 elif(option == 'calll 5573 elif(option == 'callloop-maxlen'): 6619 sysvals.calll 5574 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False) 6620 elif(option == 'mincg 5575 elif(option == 'mincg'): 6621 sysvals.mincg 5576 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False) 6622 elif(option == 'bufsi 5577 elif(option == 'bufsize'): 6623 sysvals.bufsi 5578 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False) 6624 elif(option == 'outpu 5579 elif(option == 'output-dir'): 6625 sysvals.outdi 5580 sysvals.outdir = sysvals.setOutputFolder(value) 6626 5581 6627 if sysvals.suspendmode == 'command' a 5582 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 6628 doError('No command supplied 5583 doError('No command supplied for mode "command"') 6629 5584 6630 # compatibility errors 5585 # compatibility errors 6631 if sysvals.usedevsrc and sysvals.usec 5586 if sysvals.usedevsrc and sysvals.usecallgraph: 6632 doError('-dev is not compatib 5587 doError('-dev is not compatible with -f') 6633 if sysvals.usecallgraph and sysvals.u 5588 if sysvals.usecallgraph and sysvals.useprocmon: 6634 doError('-proc is not compati 5589 doError('-proc is not compatible with -f') 6635 5590 6636 if overridekprobes: 5591 if overridekprobes: 6637 sysvals.tracefuncs = dict() 5592 sysvals.tracefuncs = dict() 6638 if overridedevkprobes: 5593 if overridedevkprobes: 6639 sysvals.dev_tracefuncs = dict 5594 sysvals.dev_tracefuncs = dict() 6640 5595 6641 kprobes = dict() 5596 kprobes = dict() 6642 kprobesec = 'dev_timeline_functions_' 5597 kprobesec = 'dev_timeline_functions_'+platform.machine() 6643 if kprobesec in sections: 5598 if kprobesec in sections: 6644 for name in Config.options(kp 5599 for name in Config.options(kprobesec): 6645 text = Config.get(kpr 5600 text = Config.get(kprobesec, name) 6646 kprobes[name] = (text 5601 kprobes[name] = (text, True) 6647 kprobesec = 'timeline_functions_'+pla 5602 kprobesec = 'timeline_functions_'+platform.machine() 6648 if kprobesec in sections: 5603 if kprobesec in sections: 6649 for name in Config.options(kp 5604 for name in Config.options(kprobesec): 6650 if name in kprobes: 5605 if name in kprobes: 6651 doError('Dupl 5606 doError('Duplicate timeline function found "%s"' % (name)) 6652 text = Config.get(kpr 5607 text = Config.get(kprobesec, name) 6653 kprobes[name] = (text 5608 kprobes[name] = (text, False) 6654 5609 6655 for name in kprobes: 5610 for name in kprobes: 6656 function = name 5611 function = name 6657 format = name 5612 format = name 6658 color = '' 5613 color = '' 6659 args = dict() 5614 args = dict() 6660 text, dev = kprobes[name] 5615 text, dev = kprobes[name] 6661 data = text.split() 5616 data = text.split() 6662 i = 0 5617 i = 0 6663 for val in data: 5618 for val in data: 6664 # bracketted strings 5619 # bracketted strings are special formatting, read them separately 6665 if val[0] == '[' and 5620 if val[0] == '[' and val[-1] == ']': 6666 for prop in v 5621 for prop in val[1:-1].split(','): 6667 p = p 5622 p = prop.split('=') 6668 if p[ 5623 if p[0] == 'color': 6669 5624 try: 6670 5625 color = int(p[1], 16) 6671 5626 color = '#'+p[1] 6672 5627 except: 6673 5628 color = p[1] 6674 continue 5629 continue 6675 # first real arg shou 5630 # first real arg should be the format string 6676 if i == 0: 5631 if i == 0: 6677 format = val 5632 format = val 6678 # all other args are 5633 # all other args are actual function args 6679 else: 5634 else: 6680 d = val.split 5635 d = val.split('=') 6681 args[d[0]] = 5636 args[d[0]] = d[1] 6682 i += 1 5637 i += 1 6683 if not function or not format 5638 if not function or not format: 6684 doError('Invalid kpro 5639 doError('Invalid kprobe: %s' % name) 6685 for arg in re.findall('{(?P<n 5640 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', format): 6686 if arg not in args: 5641 if arg not in args: 6687 doError('Kpro 5642 doError('Kprobe "%s" is missing argument "%s"' % (name, arg)) 6688 if (dev and name in sysvals.d 5643 if (dev and name in sysvals.dev_tracefuncs) or (not dev and name in sysvals.tracefuncs): 6689 doError('Duplicate ti 5644 doError('Duplicate timeline function found "%s"' % (name)) 6690 5645 6691 kp = { 5646 kp = { 6692 'name': name, 5647 'name': name, 6693 'func': function, 5648 'func': function, 6694 'format': format, 5649 'format': format, 6695 sysvals.archargs: arg 5650 sysvals.archargs: args 6696 } 5651 } 6697 if color: 5652 if color: 6698 kp['color'] = color 5653 kp['color'] = color 6699 if dev: 5654 if dev: 6700 sysvals.dev_tracefunc 5655 sysvals.dev_tracefuncs[name] = kp 6701 else: 5656 else: 6702 sysvals.tracefuncs[na 5657 sysvals.tracefuncs[name] = kp 6703 5658 6704 # Function: printHelp 5659 # Function: printHelp 6705 # Description: 5660 # Description: 6706 # print out the help text 5661 # print out the help text 6707 def printHelp(): 5662 def printHelp(): 6708 pprint('\n%s v%s\n'\ !! 5663 print('') 6709 'Usage: sudo sleepgraph <options> <co !! 5664 print('%s v%s' % (sysvals.title, sysvals.version)) 6710 '\n'\ !! 5665 print('Usage: sudo sleepgraph <options> <commands>') 6711 'Description:\n'\ !! 5666 print('') 6712 ' This tool is designed to assist ke !! 5667 print('Description:') 6713 ' their linux stack\'s suspend/resum !! 5668 print(' This tool is designed to assist kernel and OS developers in optimizing') 6714 ' with a few extra options enabled, !! 5669 print(' their linux stack\'s suspend/resume time. Using a kernel image built') 6715 ' capture dmesg and ftrace data unti !! 5670 print(' with a few extra options enabled, the tool will execute a suspend and') 6716 ' transformed into a device timeline !! 5671 print(' capture dmesg and ftrace data until resume is complete. This data is') 6717 ' a detailed view of which devices/s !! 5672 print(' transformed into a device timeline and an optional callgraph to give') 6718 ' time in suspend/resume.\n'\ !! 5673 print(' a detailed view of which devices/subsystems are taking the most') 6719 '\n'\ !! 5674 print(' time in suspend/resume.') 6720 ' If no specific command is given, t !! 5675 print('') 6721 ' a suspend/resume and capture the d !! 5676 print(' If no specific command is given, the default behavior is to initiate') 6722 '\n'\ !! 5677 print(' a suspend/resume and capture the dmesg/ftrace output as an html timeline.') 6723 ' Generates output files in subdirec !! 5678 print('') 6724 ' HTML output: < !! 5679 print(' Generates output files in subdirectory: suspend-yymmdd-HHMMSS') 6725 ' raw dmesg output: < !! 5680 print(' HTML output: <hostname>_<mode>.html') 6726 ' raw ftrace output: < !! 5681 print(' raw dmesg output: <hostname>_<mode>_dmesg.txt') 6727 '\n'\ !! 5682 print(' raw ftrace output: <hostname>_<mode>_ftrace.txt') 6728 'Options:\n'\ !! 5683 print('') 6729 ' -h Print this help text !! 5684 print('Options:') 6730 ' -v Print the current to !! 5685 print(' -h Print this help text') 6731 ' -config fn Pull arguments and c !! 5686 print(' -v Print the current tool version') 6732 ' -verbose Print extra informat !! 5687 print(' -config fn Pull arguments and config options from file fn') 6733 ' -m mode Mode to initiate for !! 5688 print(' -verbose Print extra information during execution and analysis') 6734 ' -o name Overrides the output !! 5689 print(' -m mode Mode to initiate for suspend (default: %s)') % (sysvals.suspendmode) 6735 ' default: suspend-{da !! 5690 print(' -o name Overrides the output subdirectory name when running a new test') 6736 ' -rtcwake t Wakeup t seconds aft !! 5691 print(' default: suspend-{date}-{time}') 6737 ' -addlogs Add the dmesg and ft !! 5692 print(' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)') 6738 ' -noturbostat Dont use turbostat i !! 5693 print(' -addlogs Add the dmesg and ftrace logs to the html output') 6739 ' -srgap Add a visible gap in !! 5694 print(' -srgap Add a visible gap in the timeline between sus/res (default: disabled)') 6740 ' -skiphtml Run the test and cap !! 5695 print(' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)') 6741 ' -result fn Export a results tab !! 5696 print(' -result fn Export a results table to a text file for parsing.') 6742 ' -wifi If a wifi connection !! 5697 print(' [testprep]') 6743 ' -wifitrace Trace kernel executi !! 5698 print(' -sync Sync the filesystems before starting the test') 6744 ' -netfix Use netfix to reset !! 5699 print(' -rs on/off Enable/disable runtime suspend for all devices, restore all after test') 6745 ' [testprep]\n'\ !! 5700 print(' -display on/off Turn the display on or off for the test') 6746 ' -sync Sync the filesystems !! 5701 print(' [advanced]') 6747 ' -rs on/off Enable/disable runti !! 5702 print(' -gzip Gzip the trace and dmesg logs to save space') 6748 ' -display m Change the display m !! 5703 print(' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"') 6749 ' [advanced]\n'\ !! 5704 print(' -proc Add usermode process info into the timeline (default: disabled)') 6750 ' -gzip Gzip the trace and d !! 5705 print(' -dev Add kernel function calls and threads to the timeline (default: disabled)') 6751 ' -cmd {s} Run the timeline ove !! 5706 print(' -x2 Run two suspend/resumes back to back (default: disabled)') 6752 ' -proc Add usermode process !! 5707 print(' -x2delay t Include t ms delay between multiple test runs (default: 0 ms)') 6753 ' -dev Add kernel function !! 5708 print(' -predelay t Include t ms delay before 1st suspend (default: 0 ms)') 6754 ' -x2 Run two suspend/resu !! 5709 print(' -postdelay t Include t ms delay after last resume (default: 0 ms)') 6755 ' -x2delay t Include t ms delay b !! 5710 print(' -mindev ms Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)') 6756 ' -predelay t Include t ms delay b !! 5711 print(' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will') 6757 ' -postdelay t Include t ms delay a !! 5712 print(' be created in a new subdirectory with a summary page.') 6758 ' -mindev ms Discard all device b !! 5713 print(' [debug]') 6759 ' -multi n d Execute <n> consecut !! 5714 print(' -f Use ftrace to create device callgraphs (default: disabled)') 6760 ' by a "d", "h", or "m !! 5715 print(' -maxdepth N limit the callgraph data to N call levels (default: 0=all)') 6761 ' The outputs will be !! 5716 print(' -expandcg pre-expand the callgraph data in the html output (default: disabled)') 6762 ' -maxfail n Abort a -multi run a !! 5717 print(' -fadd file Add functions to be graphed in the timeline from a list in a text file') 6763 ' [debug]\n'\ !! 5718 print(' -filter "d1,d2,..." Filter out all but this comma-delimited list of device names') 6764 ' -f Use ftrace to create !! 5719 print(' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)') 6765 ' -ftop Use ftrace on the to !! 5720 print(' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)') 6766 ' -maxdepth N limit the callgraph !! 5721 print(' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)') 6767 ' -expandcg pre-expand the callg !! 5722 print(' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)') 6768 ' -fadd file Add functions to be !! 5723 print(' -cgfilter S Filter the callgraph output in the timeline') 6769 ' -filter "d1,d2,..." Filter out al !! 5724 print(' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)') 6770 ' -mincg ms Discard all callgrap !! 5725 print(' -bufsize N Set trace buffer size to N kilo-bytes (default: all of free memory)') 6771 ' -cgphase P Only show callgraph !! 5726 print('') 6772 ' -cgtest N Only show callgraph !! 5727 print('Other commands:') 6773 ' -timeprec N Number of significan !! 5728 print(' -modes List available suspend modes') 6774 ' -cgfilter S Filter the callgraph !! 5729 print(' -status Test to see if the system is enabled to run this tool') 6775 ' -cgskip file Callgraph functions !! 5730 print(' -fpdt Print out the contents of the ACPI Firmware Performance Data Table') 6776 ' -bufsize N Set trace buffer siz !! 5731 print(' -battery Print out battery info (if available)') 6777 ' -devdump Print out all the ra !! 5732 print(' -sysinfo Print out system info extracted from BIOS') 6778 ' -cgdump Print out all the ra !! 5733 print(' -devinfo Print out the pm settings of all devices which support runtime suspend') 6779 '\n'\ !! 5734 print(' -flist Print the list of functions currently being captured in ftrace') 6780 'Other commands:\n'\ !! 5735 print(' -flistall Print all functions capable of being captured in ftrace') 6781 ' -modes List available suspe !! 5736 print(' -summary dir Create a summary of tests in this dir [-genhtml builds missing html]') 6782 ' -status Test to see if the s !! 5737 print(' [redo]') 6783 ' -fpdt Print out the conten !! 5738 print(' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)') 6784 ' -wificheck Print out wifi conne !! 5739 print(' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)') 6785 ' -x<mode> Test xset by togglin !! 5740 print('') 6786 ' -sysinfo Print out system inf << 6787 ' -devinfo Print out the pm set << 6788 ' -cmdinfo Print out all the pl << 6789 ' -flist Print the list of fu << 6790 ' -flistall Print all functions << 6791 ' -summary dir Create a summary of << 6792 ' [redo]\n'\ << 6793 ' -ftrace ftracefile Create HTML o << 6794 ' -dmesg dmesgfile Create HTML o << 6795 '' % (sysvals.title, sysvals.version, << 6796 return True 5741 return True 6797 5742 6798 # ----------------- MAIN -------------------- 5743 # ----------------- MAIN -------------------- 6799 # exec start (skipped if script is loaded as 5744 # exec start (skipped if script is loaded as library) 6800 if __name__ == '__main__': 5745 if __name__ == '__main__': 6801 genhtml = False 5746 genhtml = False 6802 cmd = '' 5747 cmd = '' 6803 simplecmds = ['-sysinfo', '-modes', ' !! 5748 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', '-devinfo', '-status', '-battery'] 6804 '-devinfo', '-status', '-xon' << 6805 '-xinit', '-xreset', '-xstat' << 6806 if '-f' in sys.argv: 5749 if '-f' in sys.argv: 6807 sysvals.cgskip = sysvals.conf 5750 sysvals.cgskip = sysvals.configFile('cgskip.txt') 6808 # loop through the command line argum 5751 # loop through the command line arguments 6809 args = iter(sys.argv[1:]) 5752 args = iter(sys.argv[1:]) 6810 for arg in args: 5753 for arg in args: 6811 if(arg == '-m'): 5754 if(arg == '-m'): 6812 try: 5755 try: 6813 val = next(ar !! 5756 val = args.next() 6814 except: 5757 except: 6815 doError('No m 5758 doError('No mode supplied', True) 6816 if val == 'command' a 5759 if val == 'command' and not sysvals.testcommand: 6817 doError('No c 5760 doError('No command supplied for mode "command"', True) 6818 sysvals.suspendmode = 5761 sysvals.suspendmode = val 6819 elif(arg in simplecmds): 5762 elif(arg in simplecmds): 6820 cmd = arg[1:] 5763 cmd = arg[1:] 6821 elif(arg == '-h'): 5764 elif(arg == '-h'): 6822 printHelp() 5765 printHelp() 6823 sys.exit(0) !! 5766 sys.exit() 6824 elif(arg == '-v'): 5767 elif(arg == '-v'): 6825 pprint("Version %s" % !! 5768 print("Version %s" % sysvals.version) 6826 sys.exit(0) !! 5769 sys.exit() 6827 elif(arg == '-debugtiming'): << 6828 debugtiming = True << 6829 elif(arg == '-x2'): 5770 elif(arg == '-x2'): 6830 sysvals.execcount = 2 5771 sysvals.execcount = 2 6831 elif(arg == '-x2delay'): 5772 elif(arg == '-x2delay'): 6832 sysvals.x2delay = get 5773 sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000) 6833 elif(arg == '-predelay'): 5774 elif(arg == '-predelay'): 6834 sysvals.predelay = ge 5775 sysvals.predelay = getArgInt('-predelay', args, 0, 60000) 6835 elif(arg == '-postdelay'): 5776 elif(arg == '-postdelay'): 6836 sysvals.postdelay = g 5777 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000) 6837 elif(arg == '-f'): 5778 elif(arg == '-f'): 6838 sysvals.usecallgraph 5779 sysvals.usecallgraph = True 6839 elif(arg == '-ftop'): << 6840 sysvals.usecallgraph << 6841 sysvals.ftop = True << 6842 sysvals.usekprobes = << 6843 elif(arg == '-skiphtml'): 5780 elif(arg == '-skiphtml'): 6844 sysvals.skiphtml = Tr 5781 sysvals.skiphtml = True 6845 elif(arg == '-cgdump'): 5782 elif(arg == '-cgdump'): 6846 sysvals.cgdump = True 5783 sysvals.cgdump = True 6847 elif(arg == '-devdump'): << 6848 sysvals.devdump = Tru << 6849 elif(arg == '-genhtml'): 5784 elif(arg == '-genhtml'): 6850 genhtml = True 5785 genhtml = True 6851 elif(arg == '-addlogs'): 5786 elif(arg == '-addlogs'): 6852 sysvals.dmesglog = sy 5787 sysvals.dmesglog = sysvals.ftracelog = True 6853 elif(arg == '-nologs'): << 6854 sysvals.dmesglog = sy << 6855 elif(arg == '-addlogdmesg'): << 6856 sysvals.dmesglog = Tr << 6857 elif(arg == '-addlogftrace'): << 6858 sysvals.ftracelog = T << 6859 elif(arg == '-noturbostat'): << 6860 sysvals.tstat = False << 6861 elif(arg == '-verbose'): 5788 elif(arg == '-verbose'): 6862 sysvals.verbose = Tru 5789 sysvals.verbose = True 6863 elif(arg == '-proc'): 5790 elif(arg == '-proc'): 6864 sysvals.useprocmon = 5791 sysvals.useprocmon = True 6865 elif(arg == '-dev'): 5792 elif(arg == '-dev'): 6866 sysvals.usedevsrc = T 5793 sysvals.usedevsrc = True 6867 elif(arg == '-sync'): 5794 elif(arg == '-sync'): 6868 sysvals.sync = True 5795 sysvals.sync = True 6869 elif(arg == '-wifi'): << 6870 sysvals.wifi = True << 6871 elif(arg == '-wifitrace'): << 6872 sysvals.wifitrace = T << 6873 elif(arg == '-netfix'): << 6874 sysvals.netfix = True << 6875 elif(arg == '-gzip'): 5796 elif(arg == '-gzip'): 6876 sysvals.gzip = True 5797 sysvals.gzip = True 6877 elif(arg == '-info'): << 6878 try: << 6879 val = next(ar << 6880 except: << 6881 doError('-inf << 6882 elif(arg == '-desc'): << 6883 try: << 6884 val = next(ar << 6885 except: << 6886 doError('-des << 6887 elif(arg == '-rs'): 5798 elif(arg == '-rs'): 6888 try: 5799 try: 6889 val = next(ar !! 5800 val = args.next() 6890 except: 5801 except: 6891 doError('-rs 5802 doError('-rs requires "enable" or "disable"', True) 6892 if val.lower() in swi 5803 if val.lower() in switchvalues: 6893 if val.lower( 5804 if val.lower() in switchoff: 6894 sysva 5805 sysvals.rs = -1 6895 else: 5806 else: 6896 sysva 5807 sysvals.rs = 1 6897 else: 5808 else: 6898 doError('inva 5809 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True) 6899 elif(arg == '-display'): 5810 elif(arg == '-display'): 6900 try: 5811 try: 6901 val = next(ar !! 5812 val = args.next() 6902 except: 5813 except: 6903 doError('-dis !! 5814 doError('-display requires "on" or "off"', True) 6904 disopt = ['on', 'off' !! 5815 if val.lower() in switchvalues: 6905 if val.lower() not in !! 5816 if val.lower() in switchoff: 6906 doError('vali !! 5817 sysvals.display = -1 6907 sysvals.display = val !! 5818 else: >> 5819 sysvals.display = 1 >> 5820 else: >> 5821 doError('invalid option: %s, use "on/off"' % val, True) 6908 elif(arg == '-maxdepth'): 5822 elif(arg == '-maxdepth'): 6909 sysvals.max_graph_dep 5823 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 6910 elif(arg == '-rtcwake'): 5824 elif(arg == '-rtcwake'): 6911 try: 5825 try: 6912 val = next(ar !! 5826 val = args.next() 6913 except: 5827 except: 6914 doError('No r 5828 doError('No rtcwake time supplied', True) 6915 if val.lower() in swi 5829 if val.lower() in switchoff: 6916 sysvals.rtcwa 5830 sysvals.rtcwake = False 6917 else: 5831 else: 6918 sysvals.rtcwa 5832 sysvals.rtcwake = True 6919 sysvals.rtcwa 5833 sysvals.rtcwaketime = getArgInt('-rtcwake', val, 0, 3600, False) 6920 elif(arg == '-timeprec'): 5834 elif(arg == '-timeprec'): 6921 sysvals.setPrecision( 5835 sysvals.setPrecision(getArgInt('-timeprec', args, 0, 6)) 6922 elif(arg == '-mindev'): 5836 elif(arg == '-mindev'): 6923 sysvals.mindevlen = g 5837 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0) 6924 elif(arg == '-mincg'): 5838 elif(arg == '-mincg'): 6925 sysvals.mincglen = ge 5839 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0) 6926 elif(arg == '-bufsize'): 5840 elif(arg == '-bufsize'): 6927 sysvals.bufsize = get 5841 sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8) 6928 elif(arg == '-cgtest'): 5842 elif(arg == '-cgtest'): 6929 sysvals.cgtest = getA 5843 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 6930 elif(arg == '-cgphase'): 5844 elif(arg == '-cgphase'): 6931 try: 5845 try: 6932 val = next(ar !! 5846 val = args.next() 6933 except: 5847 except: 6934 doError('No p 5848 doError('No phase name supplied', True) 6935 d = Data(0) 5849 d = Data(0) 6936 if val not in d.phase !! 5850 if val not in d.phases: 6937 doError('inva 5851 doError('invalid phase --> (%s: %s), valid phases are %s'\ 6938 % (ar !! 5852 % (arg, val, d.phases), True) 6939 sysvals.cgphase = val 5853 sysvals.cgphase = val 6940 elif(arg == '-cgfilter'): 5854 elif(arg == '-cgfilter'): 6941 try: 5855 try: 6942 val = next(ar !! 5856 val = args.next() 6943 except: 5857 except: 6944 doError('No c 5858 doError('No callgraph functions supplied', True) 6945 sysvals.setCallgraphF 5859 sysvals.setCallgraphFilter(val) 6946 elif(arg == '-skipkprobe'): << 6947 try: << 6948 val = next(ar << 6949 except: << 6950 doError('No k << 6951 sysvals.skipKprobes(v << 6952 elif(arg == '-cgskip'): 5860 elif(arg == '-cgskip'): 6953 try: 5861 try: 6954 val = next(ar !! 5862 val = args.next() 6955 except: 5863 except: 6956 doError('No f 5864 doError('No file supplied', True) 6957 if val.lower() in swi 5865 if val.lower() in switchoff: 6958 sysvals.cgski 5866 sysvals.cgskip = '' 6959 else: 5867 else: 6960 sysvals.cgski 5868 sysvals.cgskip = sysvals.configFile(val) 6961 if(not sysval 5869 if(not sysvals.cgskip): 6962 doErr 5870 doError('%s does not exist' % sysvals.cgskip) 6963 elif(arg == '-callloop-maxgap 5871 elif(arg == '-callloop-maxgap'): 6964 sysvals.callloopmaxga 5872 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0) 6965 elif(arg == '-callloop-maxlen 5873 elif(arg == '-callloop-maxlen'): 6966 sysvals.callloopmaxle 5874 sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0) 6967 elif(arg == '-cmd'): 5875 elif(arg == '-cmd'): 6968 try: 5876 try: 6969 val = next(ar !! 5877 val = args.next() 6970 except: 5878 except: 6971 doError('No c 5879 doError('No command string supplied', True) 6972 sysvals.testcommand = 5880 sysvals.testcommand = val 6973 sysvals.suspendmode = 5881 sysvals.suspendmode = 'command' 6974 elif(arg == '-expandcg'): 5882 elif(arg == '-expandcg'): 6975 sysvals.cgexp = True 5883 sysvals.cgexp = True 6976 elif(arg == '-srgap'): 5884 elif(arg == '-srgap'): 6977 sysvals.srgap = 5 5885 sysvals.srgap = 5 6978 elif(arg == '-maxfail'): << 6979 sysvals.maxfail = get << 6980 elif(arg == '-multi'): 5886 elif(arg == '-multi'): 6981 try: !! 5887 sysvals.multitest['run'] = True 6982 c, d = next(a !! 5888 sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000) 6983 except: !! 5889 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600) 6984 doError('-mul << 6985 sysvals.multiinit(c, << 6986 elif(arg == '-o'): 5890 elif(arg == '-o'): 6987 try: 5891 try: 6988 val = next(ar !! 5892 val = args.next() 6989 except: 5893 except: 6990 doError('No s 5894 doError('No subdirectory name supplied', True) 6991 sysvals.outdir = sysv 5895 sysvals.outdir = sysvals.setOutputFolder(val) 6992 elif(arg == '-config'): 5896 elif(arg == '-config'): 6993 try: 5897 try: 6994 val = next(ar !! 5898 val = args.next() 6995 except: 5899 except: 6996 doError('No t 5900 doError('No text file supplied', True) 6997 file = sysvals.config 5901 file = sysvals.configFile(val) 6998 if(not file): 5902 if(not file): 6999 doError('%s d 5903 doError('%s does not exist' % val) 7000 configFromFile(file) 5904 configFromFile(file) 7001 elif(arg == '-fadd'): 5905 elif(arg == '-fadd'): 7002 try: 5906 try: 7003 val = next(ar !! 5907 val = args.next() 7004 except: 5908 except: 7005 doError('No t 5909 doError('No text file supplied', True) 7006 file = sysvals.config 5910 file = sysvals.configFile(val) 7007 if(not file): 5911 if(not file): 7008 doError('%s d 5912 doError('%s does not exist' % val) 7009 sysvals.addFtraceFilt 5913 sysvals.addFtraceFilterFunctions(file) 7010 elif(arg == '-dmesg'): 5914 elif(arg == '-dmesg'): 7011 try: 5915 try: 7012 val = next(ar !! 5916 val = args.next() 7013 except: 5917 except: 7014 doError('No d 5918 doError('No dmesg file supplied', True) 7015 sysvals.notestrun = T 5919 sysvals.notestrun = True 7016 sysvals.dmesgfile = v 5920 sysvals.dmesgfile = val 7017 if(os.path.exists(sys 5921 if(os.path.exists(sysvals.dmesgfile) == False): 7018 doError('%s d 5922 doError('%s does not exist' % sysvals.dmesgfile) 7019 elif(arg == '-ftrace'): 5923 elif(arg == '-ftrace'): 7020 try: 5924 try: 7021 val = next(ar !! 5925 val = args.next() 7022 except: 5926 except: 7023 doError('No f 5927 doError('No ftrace file supplied', True) 7024 sysvals.notestrun = T 5928 sysvals.notestrun = True 7025 sysvals.ftracefile = 5929 sysvals.ftracefile = val 7026 if(os.path.exists(sys 5930 if(os.path.exists(sysvals.ftracefile) == False): 7027 doError('%s d 5931 doError('%s does not exist' % sysvals.ftracefile) 7028 elif(arg == '-summary'): 5932 elif(arg == '-summary'): 7029 try: 5933 try: 7030 val = next(ar !! 5934 val = args.next() 7031 except: 5935 except: 7032 doError('No d 5936 doError('No directory supplied', True) 7033 cmd = 'summary' 5937 cmd = 'summary' 7034 sysvals.outdir = val 5938 sysvals.outdir = val 7035 sysvals.notestrun = T 5939 sysvals.notestrun = True 7036 if(os.path.isdir(val) 5940 if(os.path.isdir(val) == False): 7037 doError('%s i 5941 doError('%s is not accesible' % val) 7038 elif(arg == '-filter'): 5942 elif(arg == '-filter'): 7039 try: 5943 try: 7040 val = next(ar !! 5944 val = args.next() 7041 except: 5945 except: 7042 doError('No d 5946 doError('No devnames supplied', True) 7043 sysvals.setDeviceFilt 5947 sysvals.setDeviceFilter(val) 7044 elif(arg == '-result'): 5948 elif(arg == '-result'): 7045 try: 5949 try: 7046 val = next(ar !! 5950 val = args.next() 7047 except: 5951 except: 7048 doError('No r 5952 doError('No result file supplied', True) 7049 sysvals.result = val 5953 sysvals.result = val 7050 sysvals.signalHandler << 7051 else: 5954 else: 7052 doError('Invalid argu 5955 doError('Invalid argument: '+arg, True) 7053 5956 7054 # compatibility errors 5957 # compatibility errors 7055 if(sysvals.usecallgraph and sysvals.u 5958 if(sysvals.usecallgraph and sysvals.usedevsrc): 7056 doError('-dev is not compatib 5959 doError('-dev is not compatible with -f') 7057 if(sysvals.usecallgraph and sysvals.u 5960 if(sysvals.usecallgraph and sysvals.useprocmon): 7058 doError('-proc is not compati 5961 doError('-proc is not compatible with -f') 7059 5962 7060 if sysvals.usecallgraph and sysvals.c 5963 if sysvals.usecallgraph and sysvals.cgskip: 7061 sysvals.vprint('Using cgskip 5964 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip) 7062 sysvals.setCallgraphBlacklist 5965 sysvals.setCallgraphBlacklist(sysvals.cgskip) 7063 5966 7064 # callgraph size cannot exceed device 5967 # callgraph size cannot exceed device size 7065 if sysvals.mincglen < sysvals.mindevl 5968 if sysvals.mincglen < sysvals.mindevlen: 7066 sysvals.mincglen = sysvals.mi 5969 sysvals.mincglen = sysvals.mindevlen 7067 5970 7068 # remove existing buffers before calc 5971 # remove existing buffers before calculating memory 7069 if(sysvals.usecallgraph or sysvals.us 5972 if(sysvals.usecallgraph or sysvals.usedevsrc): 7070 sysvals.fsetVal('16', 'buffer 5973 sysvals.fsetVal('16', 'buffer_size_kb') 7071 sysvals.cpuInfo() 5974 sysvals.cpuInfo() 7072 5975 7073 # just run a utility command and exit 5976 # just run a utility command and exit 7074 if(cmd != ''): 5977 if(cmd != ''): 7075 ret = 0 << 7076 if(cmd == 'status'): 5978 if(cmd == 'status'): 7077 if not statusCheck(Tr !! 5979 statusCheck(True) 7078 ret = 1 << 7079 elif(cmd == 'fpdt'): 5980 elif(cmd == 'fpdt'): 7080 if not getFPDT(True): !! 5981 getFPDT(True) 7081 ret = 1 !! 5982 elif(cmd == 'battery'): >> 5983 print 'AC Connect: %s\nCharge: %d' % getBattery() 7082 elif(cmd == 'sysinfo'): 5984 elif(cmd == 'sysinfo'): 7083 sysvals.printSystemIn 5985 sysvals.printSystemInfo(True) 7084 elif(cmd == 'devinfo'): 5986 elif(cmd == 'devinfo'): 7085 deviceInfo() 5987 deviceInfo() 7086 elif(cmd == 'modes'): 5988 elif(cmd == 'modes'): 7087 pprint(getModes()) !! 5989 print getModes() 7088 elif(cmd == 'flist'): 5990 elif(cmd == 'flist'): 7089 sysvals.getFtraceFilt 5991 sysvals.getFtraceFilterFunctions(True) 7090 elif(cmd == 'flistall'): 5992 elif(cmd == 'flistall'): 7091 sysvals.getFtraceFilt 5993 sysvals.getFtraceFilterFunctions(False) 7092 elif(cmd == 'summary'): 5994 elif(cmd == 'summary'): 7093 runSummary(sysvals.ou 5995 runSummary(sysvals.outdir, True, genhtml) 7094 elif(cmd in ['xon', 'xoff', ' !! 5996 sys.exit() 7095 sysvals.verbose = Tru << 7096 ret = sysvals.display << 7097 elif(cmd == 'xstat'): << 7098 pprint('Display Statu << 7099 elif(cmd == 'wificheck'): << 7100 dev = sysvals.checkWi << 7101 if dev: << 7102 print('%s is << 7103 else: << 7104 print('No wif << 7105 elif(cmd == 'cmdinfo'): << 7106 for out in sysvals.cm << 7107 print('[%s - << 7108 sys.exit(ret) << 7109 5997 7110 # if instructed, re-analyze existing 5998 # if instructed, re-analyze existing data files 7111 if(sysvals.notestrun): 5999 if(sysvals.notestrun): 7112 stamp = rerunTest(sysvals.out !! 6000 stamp = rerunTest() 7113 sysvals.outputResult(stamp) 6001 sysvals.outputResult(stamp) 7114 sys.exit(0) !! 6002 sys.exit() 7115 6003 7116 # verify that we can run a test 6004 # verify that we can run a test 7117 error = statusCheck() !! 6005 if(not statusCheck()): 7118 if(error): !! 6006 doError('Check FAILED, aborting the test run!') 7119 doError(error) << 7120 6007 7121 # extract mem/disk extra modes and co !! 6008 # extract mem modes and convert 7122 mode = sysvals.suspendmode 6009 mode = sysvals.suspendmode 7123 if mode.startswith('mem'): !! 6010 if 'mem' == mode[:3]: 7124 memmode = mode.split('-', 1)[ !! 6011 if '-' in mode: >> 6012 memmode = mode.split('-')[-1] >> 6013 else: >> 6014 memmode = 'deep' 7125 if memmode == 'shallow': 6015 if memmode == 'shallow': 7126 mode = 'standby' 6016 mode = 'standby' 7127 elif memmode == 's2idle': 6017 elif memmode == 's2idle': 7128 mode = 'freeze' 6018 mode = 'freeze' 7129 else: 6019 else: 7130 mode = 'mem' 6020 mode = 'mem' 7131 sysvals.memmode = memmode 6021 sysvals.memmode = memmode 7132 sysvals.suspendmode = mode 6022 sysvals.suspendmode = mode 7133 if mode.startswith('disk-'): !! 6023 7134 sysvals.diskmode = mode.split << 7135 sysvals.suspendmode = 'disk' << 7136 sysvals.systemInfo(dmidecode(sysvals. 6024 sysvals.systemInfo(dmidecode(sysvals.mempath)) 7137 6025 7138 failcnt, ret = 0, 0 !! 6026 setRuntimeSuspend(True) >> 6027 if sysvals.display: >> 6028 call('xset -d :0.0 dpms 0 0 0', shell=True) >> 6029 call('xset -d :0.0 s off', shell=True) 7139 if sysvals.multitest['run']: 6030 if sysvals.multitest['run']: 7140 # run multiple tests in a sep 6031 # run multiple tests in a separate subdirectory 7141 if not sysvals.outdir: 6032 if not sysvals.outdir: 7142 if 'time' in sysvals. !! 6033 s = 'suspend-x%d' % sysvals.multitest['count'] 7143 s = '-%dm' % !! 6034 sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S') 7144 else: << 7145 s = '-x%d' % << 7146 sysvals.outdir = date << 7147 if not os.path.isdir(sysvals. 6035 if not os.path.isdir(sysvals.outdir): 7148 os.makedirs(sysvals.o !! 6036 os.mkdir(sysvals.outdir) 7149 sysvals.sudoUserchown(sysvals << 7150 finish = datetime.now() << 7151 if 'time' in sysvals.multites << 7152 finish += timedelta(m << 7153 for i in range(sysvals.multit 6037 for i in range(sysvals.multitest['count']): 7154 sysvals.multistat(Tru !! 6038 if(i != 0): 7155 if i != 0 and sysvals !! 6039 print('Waiting %d seconds...' % (sysvals.multitest['delay'])) 7156 pprint('Waiti << 7157 time.sleep(sy 6040 time.sleep(sysvals.multitest['delay']) >> 6041 print('TEST (%d/%d) START' % (i+1, sysvals.multitest['count'])) 7158 fmt = 'suspend-%y%m%d 6042 fmt = 'suspend-%y%m%d-%H%M%S' 7159 sysvals.testdir = os. 6043 sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt)) 7160 ret = runTest(i+1, no !! 6044 runTest(i+1) 7161 failcnt = 0 if not re !! 6045 print('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count'])) 7162 if sysvals.maxfail > !! 6046 sysvals.logmsg = '' 7163 pprint('Maxim << 7164 break << 7165 sysvals.resetlog() << 7166 sysvals.multistat(Fal << 7167 if 'time' in sysvals. << 7168 break << 7169 if not sysvals.skiphtml: 6047 if not sysvals.skiphtml: 7170 runSummary(sysvals.ou 6048 runSummary(sysvals.outdir, False, False) 7171 sysvals.sudoUserchown(sysvals !! 6049 sysvals.sudouser(sysvals.outdir) 7172 else: 6050 else: 7173 if sysvals.outdir: 6051 if sysvals.outdir: 7174 sysvals.testdir = sys 6052 sysvals.testdir = sysvals.outdir 7175 # run the test in the current 6053 # run the test in the current directory 7176 ret = runTest() !! 6054 runTest() 7177 << 7178 # reset to default values after testi << 7179 if sysvals.display: 6055 if sysvals.display: 7180 sysvals.displayControl('reset !! 6056 call('xset -d :0.0 s reset', shell=True) 7181 if sysvals.rs != 0: !! 6057 setRuntimeSuspend(False) 7182 sysvals.setRuntimeSuspend(Fal << 7183 sys.exit(ret) <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.