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 import signal 60 import codecs !! 58 from datetime import datetime 61 from datetime import datetime, timedelta << 62 import struct 59 import struct 63 import configparser !! 60 import ConfigParser 64 import gzip 61 import gzip 65 from threading import Thread 62 from threading import Thread 66 from subprocess import call, Popen, PIPE 63 from subprocess import call, Popen, PIPE 67 import base64 << 68 64 69 debugtiming = False << 70 mystarttime = time.time() << 71 def pprint(msg): 65 def pprint(msg): 72 if debugtiming: !! 66 print(msg) 73 print('[%09.3f] %s' % (time.ti << 74 else: << 75 print(msg) << 76 sys.stdout.flush() 67 sys.stdout.flush() 77 68 78 def ascii(text): << 79 return text.decode('ascii', 'ignore') << 80 << 81 # ----------------- CLASSES ------------------ 69 # ----------------- CLASSES -------------------- 82 70 83 # Class: SystemValues 71 # Class: SystemValues 84 # Description: 72 # Description: 85 # A global, single-instance container u 73 # A global, single-instance container used to 86 # store system values and test paramete 74 # store system values and test parameters 87 class SystemValues: 75 class SystemValues: 88 title = 'SleepGraph' 76 title = 'SleepGraph' 89 version = '5.12' !! 77 version = '5.2' 90 ansi = False 78 ansi = False 91 rs = 0 79 rs = 0 92 display = '' 80 display = '' 93 gzip = False 81 gzip = False 94 sync = False 82 sync = False 95 wifi = False << 96 netfix = False << 97 verbose = False 83 verbose = False 98 testlog = True 84 testlog = True 99 dmesglog = True !! 85 dmesglog = False 100 ftracelog = False 86 ftracelog = False 101 acpidebug = True !! 87 mindevlen = 0.0 102 tstat = True << 103 wifitrace = False << 104 mindevlen = 0.0001 << 105 mincglen = 0.0 88 mincglen = 0.0 106 cgphase = '' 89 cgphase = '' 107 cgtest = -1 90 cgtest = -1 108 cgskip = '' 91 cgskip = '' 109 maxfail = 0 !! 92 multitest = {'run': False, 'count': 0, 'delay': 0} 110 multitest = {'run': False, 'count': 10 << 111 max_graph_depth = 0 93 max_graph_depth = 0 112 callloopmaxgap = 0.0001 94 callloopmaxgap = 0.0001 113 callloopmaxlen = 0.005 95 callloopmaxlen = 0.005 114 bufsize = 0 96 bufsize = 0 115 cpucount = 0 97 cpucount = 0 116 memtotal = 204800 98 memtotal = 204800 117 memfree = 204800 99 memfree = 204800 118 osversion = '' << 119 srgap = 0 100 srgap = 0 120 cgexp = False 101 cgexp = False 121 testdir = '' 102 testdir = '' 122 outdir = '' 103 outdir = '' 123 tpath = '/sys/kernel/tracing/' !! 104 tpath = '/sys/kernel/debug/tracing/' 124 fpdtpath = '/sys/firmware/acpi/tables/ 105 fpdtpath = '/sys/firmware/acpi/tables/FPDT' 125 epath = '/sys/kernel/tracing/events/po !! 106 epath = '/sys/kernel/debug/tracing/events/power/' 126 pmdpath = '/sys/power/pm_debug_message 107 pmdpath = '/sys/power/pm_debug_messages' 127 s0ixpath = '/sys/module/intel_pmc_core << 128 s0ixres = '/sys/devices/system/cpu/cpu << 129 acpipath='/sys/module/acpi/parameters/ << 130 traceevents = [ 108 traceevents = [ 131 'suspend_resume', 109 'suspend_resume', 132 'wakeup_source_activate', << 133 'wakeup_source_deactivate', << 134 'device_pm_callback_end', 110 'device_pm_callback_end', 135 'device_pm_callback_start' 111 'device_pm_callback_start' 136 ] 112 ] 137 logmsg = '' 113 logmsg = '' 138 testcommand = '' 114 testcommand = '' 139 mempath = '/dev/mem' 115 mempath = '/dev/mem' 140 powerfile = '/sys/power/state' 116 powerfile = '/sys/power/state' 141 mempowerfile = '/sys/power/mem_sleep' 117 mempowerfile = '/sys/power/mem_sleep' 142 diskpowerfile = '/sys/power/disk' 118 diskpowerfile = '/sys/power/disk' 143 suspendmode = 'mem' 119 suspendmode = 'mem' 144 memmode = '' 120 memmode = '' 145 diskmode = '' 121 diskmode = '' 146 hostname = 'localhost' 122 hostname = 'localhost' 147 prefix = 'test' 123 prefix = 'test' 148 teststamp = '' 124 teststamp = '' 149 sysstamp = '' 125 sysstamp = '' 150 dmesgstart = 0.0 126 dmesgstart = 0.0 151 dmesgfile = '' 127 dmesgfile = '' 152 ftracefile = '' 128 ftracefile = '' 153 htmlfile = 'output.html' 129 htmlfile = 'output.html' 154 result = '' 130 result = '' 155 rtcwake = True 131 rtcwake = True 156 rtcwaketime = 15 132 rtcwaketime = 15 157 rtcpath = '' 133 rtcpath = '' 158 devicefilter = [] 134 devicefilter = [] 159 cgfilter = [] 135 cgfilter = [] 160 stamp = 0 136 stamp = 0 161 execcount = 1 137 execcount = 1 162 x2delay = 0 138 x2delay = 0 163 skiphtml = False 139 skiphtml = False 164 usecallgraph = False 140 usecallgraph = False 165 ftopfunc = 'pm_suspend' << 166 ftop = False << 167 usetraceevents = False 141 usetraceevents = False 168 usetracemarkers = True 142 usetracemarkers = True 169 useftrace = True << 170 usekprobes = True 143 usekprobes = True 171 usedevsrc = False 144 usedevsrc = False 172 useprocmon = False 145 useprocmon = False 173 notestrun = False 146 notestrun = False 174 cgdump = False 147 cgdump = False 175 devdump = False 148 devdump = False 176 mixedphaseheight = True 149 mixedphaseheight = True 177 devprops = dict() 150 devprops = dict() 178 cfgdef = dict() << 179 platinfo = [] << 180 predelay = 0 151 predelay = 0 181 postdelay = 0 152 postdelay = 0 182 tmstart = 'SUSPEND START %Y%m%d-%H:%M: !! 153 pmdebug = '' 183 tmend = 'RESUME COMPLETE %Y%m%d-%H:%M: << 184 tracefuncs = { 154 tracefuncs = { 185 'async_synchronize_full': {}, << 186 'sys_sync': {}, 155 'sys_sync': {}, 187 'ksys_sync': {}, 156 'ksys_sync': {}, 188 '__pm_notifier_call_chain': {} 157 '__pm_notifier_call_chain': {}, 189 'pm_prepare_console': {}, 158 'pm_prepare_console': {}, 190 'pm_notifier_call_chain': {}, 159 'pm_notifier_call_chain': {}, 191 'freeze_processes': {}, 160 'freeze_processes': {}, 192 'freeze_kernel_threads': {}, 161 'freeze_kernel_threads': {}, 193 'pm_restrict_gfp_mask': {}, 162 'pm_restrict_gfp_mask': {}, 194 'acpi_suspend_begin': {}, 163 'acpi_suspend_begin': {}, 195 'acpi_hibernation_begin': {}, 164 'acpi_hibernation_begin': {}, 196 'acpi_hibernation_enter': {}, 165 'acpi_hibernation_enter': {}, 197 'acpi_hibernation_leave': {}, 166 'acpi_hibernation_leave': {}, 198 'acpi_pm_freeze': {}, 167 'acpi_pm_freeze': {}, 199 'acpi_pm_thaw': {}, 168 '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' 169 'hibernate_preallocate_memory': {}, 210 'create_basic_memory_bitmaps': 170 'create_basic_memory_bitmaps': {}, 211 'swsusp_write': {}, 171 'swsusp_write': {}, 212 'suspend_console': {}, 172 'suspend_console': {}, 213 'acpi_pm_prepare': {}, 173 'acpi_pm_prepare': {}, 214 'syscore_suspend': {}, 174 'syscore_suspend': {}, 215 'arch_enable_nonboot_cpus_end' 175 'arch_enable_nonboot_cpus_end': {}, 216 'syscore_resume': {}, 176 'syscore_resume': {}, 217 'acpi_pm_finish': {}, 177 'acpi_pm_finish': {}, 218 'resume_console': {}, 178 'resume_console': {}, 219 'acpi_pm_end': {}, 179 'acpi_pm_end': {}, 220 'pm_restore_gfp_mask': {}, 180 'pm_restore_gfp_mask': {}, 221 'thaw_processes': {}, 181 'thaw_processes': {}, 222 'pm_restore_console': {}, 182 'pm_restore_console': {}, 223 'CPU_OFF': { 183 'CPU_OFF': { 224 'func':'_cpu_down', 184 'func':'_cpu_down', 225 'args_x86_64': {'cpu': 185 'args_x86_64': {'cpu':'%di:s32'}, 226 'format': 'CPU_OFF[{cp 186 'format': 'CPU_OFF[{cpu}]' 227 }, 187 }, 228 'CPU_ON': { 188 'CPU_ON': { 229 'func':'_cpu_up', 189 'func':'_cpu_up', 230 'args_x86_64': {'cpu': 190 'args_x86_64': {'cpu':'%di:s32'}, 231 'format': 'CPU_ON[{cpu 191 'format': 'CPU_ON[{cpu}]' 232 }, 192 }, 233 } 193 } 234 dev_tracefuncs = { 194 dev_tracefuncs = { 235 # general wait/delay/sleep 195 # general wait/delay/sleep 236 'msleep': { 'args_x86_64': {'t 196 'msleep': { 'args_x86_64': {'time':'%di:s32'}, 'ub': 1 }, 237 'schedule_timeout': { 'args_x8 197 'schedule_timeout': { 'args_x86_64': {'timeout':'%di:s32'}, 'ub': 1 }, 238 'udelay': { 'func':'__const_ud 198 'udelay': { 'func':'__const_udelay', 'args_x86_64': {'loops':'%di:s32'}, 'ub': 1 }, 239 'usleep_range': { 'args_x86_64 199 'usleep_range': { 'args_x86_64': {'min':'%di:s32', 'max':'%si:s32'}, 'ub': 1 }, 240 'mutex_lock_slowpath': { 'func 200 'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 }, 241 'acpi_os_stall': {'ub': 1}, 201 'acpi_os_stall': {'ub': 1}, 242 'rt_mutex_slowlock': {'ub': 1} << 243 # ACPI 202 # ACPI 244 'acpi_resume_power_resources': 203 'acpi_resume_power_resources': {}, 245 'acpi_ps_execute_method': { 'a !! 204 'acpi_ps_parse_aml': {}, 246 'fullpath':'+0(+40(%di << 247 }}, << 248 # mei_me << 249 'mei_reset': {}, << 250 # filesystem 205 # filesystem 251 'ext4_sync_fs': {}, 206 'ext4_sync_fs': {}, 252 # 80211 207 # 80211 253 'ath10k_bmi_read_memory': { 'a 208 'ath10k_bmi_read_memory': { 'args_x86_64': {'length':'%cx:s32'} }, 254 'ath10k_bmi_write_memory': { ' 209 'ath10k_bmi_write_memory': { 'args_x86_64': {'length':'%cx:s32'} }, 255 'ath10k_bmi_fast_download': { 210 'ath10k_bmi_fast_download': { 'args_x86_64': {'length':'%cx:s32'} }, 256 'iwlagn_mac_start': {}, 211 'iwlagn_mac_start': {}, 257 'iwlagn_alloc_bcast_station': 212 'iwlagn_alloc_bcast_station': {}, 258 'iwl_trans_pcie_start_hw': {}, 213 'iwl_trans_pcie_start_hw': {}, 259 'iwl_trans_pcie_start_fw': {}, 214 'iwl_trans_pcie_start_fw': {}, 260 'iwl_run_init_ucode': {}, 215 'iwl_run_init_ucode': {}, 261 'iwl_load_ucode_wait_alive': { 216 'iwl_load_ucode_wait_alive': {}, 262 'iwl_alive_start': {}, 217 'iwl_alive_start': {}, 263 'iwlagn_mac_stop': {}, 218 'iwlagn_mac_stop': {}, 264 'iwlagn_mac_suspend': {}, 219 'iwlagn_mac_suspend': {}, 265 'iwlagn_mac_resume': {}, 220 'iwlagn_mac_resume': {}, 266 'iwlagn_mac_add_interface': {} 221 'iwlagn_mac_add_interface': {}, 267 'iwlagn_mac_remove_interface': 222 'iwlagn_mac_remove_interface': {}, 268 'iwlagn_mac_change_interface': 223 'iwlagn_mac_change_interface': {}, 269 'iwlagn_mac_config': {}, 224 'iwlagn_mac_config': {}, 270 'iwlagn_configure_filter': {}, 225 'iwlagn_configure_filter': {}, 271 'iwlagn_mac_hw_scan': {}, 226 'iwlagn_mac_hw_scan': {}, 272 'iwlagn_bss_info_changed': {}, 227 'iwlagn_bss_info_changed': {}, 273 'iwlagn_mac_channel_switch': { 228 'iwlagn_mac_channel_switch': {}, 274 'iwlagn_mac_flush': {}, 229 'iwlagn_mac_flush': {}, 275 # ATA 230 # ATA 276 'ata_eh_recover': { 'args_x86_ 231 'ata_eh_recover': { 'args_x86_64': {'port':'+36(%di):s32'} }, 277 # i915 232 # i915 278 'i915_gem_resume': {}, 233 'i915_gem_resume': {}, 279 'i915_restore_state': {}, 234 'i915_restore_state': {}, 280 'intel_opregion_setup': {}, 235 'intel_opregion_setup': {}, 281 'g4x_pre_enable_dp': {}, 236 'g4x_pre_enable_dp': {}, 282 'vlv_pre_enable_dp': {}, 237 'vlv_pre_enable_dp': {}, 283 'chv_pre_enable_dp': {}, 238 'chv_pre_enable_dp': {}, 284 'g4x_enable_dp': {}, 239 'g4x_enable_dp': {}, 285 'vlv_enable_dp': {}, 240 'vlv_enable_dp': {}, 286 'intel_hpd_init': {}, 241 'intel_hpd_init': {}, 287 'intel_opregion_register': {}, 242 'intel_opregion_register': {}, 288 'intel_dp_detect': {}, 243 'intel_dp_detect': {}, 289 'intel_hdmi_detect': {}, 244 'intel_hdmi_detect': {}, 290 'intel_opregion_init': {}, 245 'intel_opregion_init': {}, 291 'intel_fbdev_set_suspend': {}, 246 'intel_fbdev_set_suspend': {}, 292 } 247 } 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 = [] 248 cgblacklist = [] 314 kprobes = dict() 249 kprobes = dict() 315 timeformat = '%.3f' 250 timeformat = '%.3f' 316 cmdline = '%s %s' % \ 251 cmdline = '%s %s' % \ 317 (os.path.basename(sys. 252 (os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:])) 318 sudouser = '' 253 sudouser = '' 319 def __init__(self): 254 def __init__(self): 320 self.archargs = 'args_'+platfo 255 self.archargs = 'args_'+platform.machine() 321 self.hostname = platform.node( 256 self.hostname = platform.node() 322 if(self.hostname == ''): 257 if(self.hostname == ''): 323 self.hostname = 'local 258 self.hostname = 'localhost' 324 rtc = "rtc0" 259 rtc = "rtc0" 325 if os.path.exists('/dev/rtc'): 260 if os.path.exists('/dev/rtc'): 326 rtc = os.readlink('/de 261 rtc = os.readlink('/dev/rtc') 327 rtc = '/sys/class/rtc/'+rtc 262 rtc = '/sys/class/rtc/'+rtc 328 if os.path.exists(rtc) and os. 263 if os.path.exists(rtc) and os.path.exists(rtc+'/date') and \ 329 os.path.exists(rtc+'/t 264 os.path.exists(rtc+'/time') and os.path.exists(rtc+'/wakealarm'): 330 self.rtcpath = rtc 265 self.rtcpath = rtc 331 if (hasattr(sys.stdout, 'isatt 266 if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 332 self.ansi = True 267 self.ansi = True 333 self.testdir = datetime.now(). 268 self.testdir = datetime.now().strftime('suspend-%y%m%d-%H%M%S') 334 if os.getuid() == 0 and 'SUDO_ 269 if os.getuid() == 0 and 'SUDO_USER' in os.environ and \ 335 os.environ['SUDO_USER' 270 os.environ['SUDO_USER']: 336 self.sudouser = os.env 271 self.sudouser = os.environ['SUDO_USER'] 337 def resetlog(self): << 338 self.logmsg = '' << 339 self.platinfo = [] << 340 def vprint(self, msg): 272 def vprint(self, msg): 341 self.logmsg += msg+'\n' 273 self.logmsg += msg+'\n' 342 if self.verbose or msg.startsw 274 if self.verbose or msg.startswith('WARNING:'): 343 pprint(msg) 275 pprint(msg) 344 def signalHandler(self, signum, frame) 276 def signalHandler(self, signum, frame): 345 if not self.result: 277 if not self.result: 346 return 278 return 347 signame = self.signames[signum 279 signame = self.signames[signum] if signum in self.signames else 'UNKNOWN' 348 msg = 'Signal %s caused a tool 280 msg = 'Signal %s caused a tool exit, line %d' % (signame, frame.f_lineno) 349 self.outputResult({'error':msg !! 281 sysvals.outputResult({'error':msg}) 350 sys.exit(3) 282 sys.exit(3) 351 def signalHandlerInit(self): 283 def signalHandlerInit(self): 352 capture = ['BUS', 'SYS', 'XCPU 284 capture = ['BUS', 'SYS', 'XCPU', 'XFSZ', 'PWR', 'HUP', 'INT', 'QUIT', 353 'ILL', 'ABRT', 'FPE', !! 285 'ILL', 'ABRT', 'FPE', 'SEGV', 'TERM', 'TSTP'] 354 self.signames = dict() 286 self.signames = dict() 355 for i in capture: 287 for i in capture: 356 s = 'SIG'+i 288 s = 'SIG'+i 357 try: 289 try: 358 signum = getat 290 signum = getattr(signal, s) 359 signal.signal( 291 signal.signal(signum, self.signalHandler) 360 except: 292 except: 361 continue 293 continue 362 self.signames[signum] 294 self.signames[signum] = s 363 def rootCheck(self, fatal=True): 295 def rootCheck(self, fatal=True): 364 if(os.access(self.powerfile, o 296 if(os.access(self.powerfile, os.W_OK)): 365 return True 297 return True 366 if fatal: 298 if fatal: 367 msg = 'This command re 299 msg = 'This command requires sysfs mount and root access' 368 pprint('ERROR: %s\n' % 300 pprint('ERROR: %s\n' % msg) 369 self.outputResult({'er 301 self.outputResult({'error':msg}) 370 sys.exit(1) 302 sys.exit(1) 371 return False 303 return False 372 def rootUser(self, fatal=False): 304 def rootUser(self, fatal=False): 373 if 'USER' in os.environ and os 305 if 'USER' in os.environ and os.environ['USER'] == 'root': 374 return True 306 return True 375 if fatal: 307 if fatal: 376 msg = 'This command mu 308 msg = 'This command must be run as root' 377 pprint('ERROR: %s\n' % 309 pprint('ERROR: %s\n' % msg) 378 self.outputResult({'er 310 self.outputResult({'error':msg}) 379 sys.exit(1) 311 sys.exit(1) 380 return False 312 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): 313 def getExec(self, cmd): 395 try: !! 314 dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin', 396 fp = Popen(['which', c !! 315 '/usr/local/sbin', '/usr/local/bin'] 397 out = ascii(fp.read()) !! 316 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 317 cmdfull = os.path.join(path, cmd) 406 if os.path.exists(cmdf 318 if os.path.exists(cmdfull): 407 return cmdfull 319 return cmdfull 408 return out !! 320 return '' 409 def setPrecision(self, num): 321 def setPrecision(self, num): 410 if num < 0 or num > 6: 322 if num < 0 or num > 6: 411 return 323 return 412 self.timeformat = '%.{0}f'.for 324 self.timeformat = '%.{0}f'.format(num) 413 def setOutputFolder(self, value): 325 def setOutputFolder(self, value): 414 args = dict() 326 args = dict() 415 n = datetime.now() 327 n = datetime.now() 416 args['date'] = n.strftime('%y% 328 args['date'] = n.strftime('%y%m%d') 417 args['time'] = n.strftime('%H% 329 args['time'] = n.strftime('%H%M%S') 418 args['hostname'] = args['host' 330 args['hostname'] = args['host'] = self.hostname 419 args['mode'] = self.suspendmod << 420 return value.format(**args) 331 return value.format(**args) 421 def setOutputFile(self): 332 def setOutputFile(self): 422 if self.dmesgfile != '': 333 if self.dmesgfile != '': 423 m = re.match(r'(?P<nam !! 334 m = re.match('(?P<name>.*)_dmesg\.txt.*', self.dmesgfile) 424 if(m): 335 if(m): 425 self.htmlfile 336 self.htmlfile = m.group('name')+'.html' 426 if self.ftracefile != '': 337 if self.ftracefile != '': 427 m = re.match(r'(?P<nam !! 338 m = re.match('(?P<name>.*)_ftrace\.txt.*', self.ftracefile) 428 if(m): 339 if(m): 429 self.htmlfile 340 self.htmlfile = m.group('name')+'.html' 430 def systemInfo(self, info): 341 def systemInfo(self, info): 431 p = m = '' !! 342 p = c = m = b = '' 432 if 'baseboard-manufacturer' in 343 if 'baseboard-manufacturer' in info: 433 m = info['baseboard-ma 344 m = info['baseboard-manufacturer'] 434 elif 'system-manufacturer' in 345 elif 'system-manufacturer' in info: 435 m = info['system-manuf 346 m = info['system-manufacturer'] 436 if 'system-product-name' in in !! 347 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 348 p = info['baseboard-product-name'] 442 c = info['processor-version'] !! 349 elif 'system-product-name' in info: 443 b = info['bios-version'] if 'b !! 350 p = info['system-product-name'] 444 r = info['bios-release-date'] !! 351 if 'processor-version' in info: 445 self.sysstamp = '# sysinfo | m !! 352 c = info['processor-version'] 446 (m, p, c, b, r, self.c !! 353 if 'bios-version' in info: 447 if self.osversion: !! 354 b = info['bios-version'] 448 self.sysstamp += ' | o !! 355 self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d | memfr:%d' % \ >> 356 (m, p, c, b, self.cpucount, self.memtotal, self.memfree) 449 def printSystemInfo(self, fatal=False) 357 def printSystemInfo(self, fatal=False): 450 self.rootCheck(True) 358 self.rootCheck(True) 451 out = dmidecode(self.mempath, 359 out = dmidecode(self.mempath, fatal) 452 if len(out) < 1: 360 if len(out) < 1: 453 return 361 return 454 fmt = '%-24s: %s' 362 fmt = '%-24s: %s' 455 if self.osversion: << 456 print(fmt % ('os-versi << 457 for name in sorted(out): 363 for name in sorted(out): 458 print(fmt % (name, out !! 364 print fmt % (name, out[name]) 459 print(fmt % ('cpucount', ('%d' !! 365 print fmt % ('cpucount', ('%d' % self.cpucount)) 460 print(fmt % ('memtotal', ('%d !! 366 print fmt % ('memtotal', ('%d kB' % self.memtotal)) 461 print(fmt % ('memfree', ('%d k !! 367 print fmt % ('memfree', ('%d kB' % self.memfree)) 462 def cpuInfo(self): 368 def cpuInfo(self): 463 self.cpucount = 0 369 self.cpucount = 0 464 if os.path.exists('/proc/cpuin !! 370 fp = open('/proc/cpuinfo', 'r') 465 with open('/proc/cpuin !! 371 for line in fp: 466 for line in fp !! 372 if re.match('^processor[ \t]*:[ \t]*[0-9]*', line): 467 if re. !! 373 self.cpucount += 1 468 !! 374 fp.close() 469 if os.path.exists('/proc/memin !! 375 fp = open('/proc/meminfo', 'r') 470 with open('/proc/memin !! 376 for line in fp: 471 for line in fp !! 377 m = re.match('^MemTotal:[ \t]*(?P<sz>[0-9]*) *kB', line) 472 m = re !! 378 if m: 473 if m: !! 379 self.memtotal = int(m.group('sz')) 474 !! 380 m = re.match('^MemFree:[ \t]*(?P<sz>[0-9]*) *kB', line) 475 m = re !! 381 if m: 476 if m: !! 382 self.memfree = int(m.group('sz')) 477 !! 383 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): 384 def initTestOutput(self, name): 484 self.prefix = self.hostname 385 self.prefix = self.hostname 485 v = open('/proc/version', 'r') 386 v = open('/proc/version', 'r').read().strip() 486 kver = v.split()[2] !! 387 kver = string.split(v)[2] 487 fmt = name+'-%m%d%y-%H%M%S' 388 fmt = name+'-%m%d%y-%H%M%S' 488 testtime = datetime.now().strf 389 testtime = datetime.now().strftime(fmt) 489 self.teststamp = \ 390 self.teststamp = \ 490 '# '+testtime+' '+self 391 '# '+testtime+' '+self.prefix+' '+self.suspendmode+' '+kver 491 ext = '' 392 ext = '' 492 if self.gzip: 393 if self.gzip: 493 ext = '.gz' 394 ext = '.gz' 494 self.dmesgfile = \ 395 self.dmesgfile = \ 495 self.testdir+'/'+self. 396 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_dmesg.txt'+ext 496 self.ftracefile = \ 397 self.ftracefile = \ 497 self.testdir+'/'+self. 398 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'_ftrace.txt'+ext 498 self.htmlfile = \ 399 self.htmlfile = \ 499 self.testdir+'/'+self. 400 self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html' 500 if not os.path.isdir(self.test 401 if not os.path.isdir(self.testdir): 501 os.makedirs(self.testd !! 402 os.mkdir(self.testdir) 502 self.sudoUserchown(self.testdi << 503 def getValueList(self, value): 403 def getValueList(self, value): 504 out = [] 404 out = [] 505 for i in value.split(','): 405 for i in value.split(','): 506 if i.strip(): 406 if i.strip(): 507 out.append(i.s 407 out.append(i.strip()) 508 return out 408 return out 509 def setDeviceFilter(self, value): 409 def setDeviceFilter(self, value): 510 self.devicefilter = self.getVa 410 self.devicefilter = self.getValueList(value) 511 def setCallgraphFilter(self, value): 411 def setCallgraphFilter(self, value): 512 self.cgfilter = self.getValueL 412 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): 413 def setCallgraphBlacklist(self, file): 520 self.cgblacklist = self.listFr 414 self.cgblacklist = self.listFromFile(file) 521 def rtcWakeAlarmOn(self): 415 def rtcWakeAlarmOn(self): 522 call('echo 0 > '+self.rtcpath+ 416 call('echo 0 > '+self.rtcpath+'/wakealarm', shell=True) 523 nowtime = open(self.rtcpath+'/ 417 nowtime = open(self.rtcpath+'/since_epoch', 'r').read().strip() 524 if nowtime: 418 if nowtime: 525 nowtime = int(nowtime) 419 nowtime = int(nowtime) 526 else: 420 else: 527 # if hardware time fai 421 # if hardware time fails, use the software time 528 nowtime = int(datetime 422 nowtime = int(datetime.now().strftime('%s')) 529 alarm = nowtime + self.rtcwake 423 alarm = nowtime + self.rtcwaketime 530 call('echo %d > %s/wakealarm' 424 call('echo %d > %s/wakealarm' % (alarm, self.rtcpath), shell=True) 531 def rtcWakeAlarmOff(self): 425 def rtcWakeAlarmOff(self): 532 call('echo 0 > %s/wakealarm' % 426 call('echo 0 > %s/wakealarm' % self.rtcpath, shell=True) 533 def initdmesg(self): 427 def initdmesg(self): 534 # get the latest time stamp fr 428 # get the latest time stamp from the dmesg log 535 lines = Popen('dmesg', stdout= !! 429 fp = Popen('dmesg', stdout=PIPE).stdout 536 ktime = '0' 430 ktime = '0' 537 for line in reversed(lines): !! 431 for line in fp: 538 line = ascii(line).rep !! 432 line = line.replace('\r\n', '') 539 idx = line.find('[') 433 idx = line.find('[') 540 if idx > 1: 434 if idx > 1: 541 line = line[id 435 line = line[idx:] 542 m = re.match(r'[ \t]*( !! 436 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 543 if(m): 437 if(m): 544 ktime = m.grou 438 ktime = m.group('ktime') 545 break !! 439 fp.close() 546 self.dmesgstart = float(ktime) 440 self.dmesgstart = float(ktime) 547 def getdmesg(self, testdata): 441 def getdmesg(self, testdata): 548 op = self.writeDatafileHeader( !! 442 op = self.writeDatafileHeader(sysvals.dmesgfile, testdata) 549 # store all new dmesg lines si 443 # store all new dmesg lines since initdmesg was called 550 fp = Popen('dmesg', stdout=PIP 444 fp = Popen('dmesg', stdout=PIPE).stdout 551 for line in fp: 445 for line in fp: 552 line = ascii(line).rep !! 446 line = line.replace('\r\n', '') 553 idx = line.find('[') 447 idx = line.find('[') 554 if idx > 1: 448 if idx > 1: 555 line = line[id 449 line = line[idx:] 556 m = re.match(r'[ \t]*( !! 450 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 557 if(not m): 451 if(not m): 558 continue 452 continue 559 ktime = float(m.group( 453 ktime = float(m.group('ktime')) 560 if ktime > self.dmesgs 454 if ktime > self.dmesgstart: 561 op.write(line) 455 op.write(line) 562 fp.close() 456 fp.close() 563 op.close() 457 op.close() 564 def listFromFile(self, file): 458 def listFromFile(self, file): 565 list = [] 459 list = [] 566 fp = open(file) 460 fp = open(file) 567 for i in fp.read().split('\n') 461 for i in fp.read().split('\n'): 568 i = i.strip() 462 i = i.strip() 569 if i and i[0] != '#': 463 if i and i[0] != '#': 570 list.append(i) 464 list.append(i) 571 fp.close() 465 fp.close() 572 return list 466 return list 573 def addFtraceFilterFunctions(self, fil 467 def addFtraceFilterFunctions(self, file): 574 for i in self.listFromFile(fil 468 for i in self.listFromFile(file): 575 if len(i) < 2: 469 if len(i) < 2: 576 continue 470 continue 577 self.tracefuncs[i] = d 471 self.tracefuncs[i] = dict() 578 def getFtraceFilterFunctions(self, cur 472 def getFtraceFilterFunctions(self, current): 579 self.rootCheck(True) 473 self.rootCheck(True) 580 if not current: 474 if not current: 581 call('cat '+self.tpath 475 call('cat '+self.tpath+'available_filter_functions', shell=True) 582 return 476 return 583 master = self.listFromFile(sel 477 master = self.listFromFile(self.tpath+'available_filter_functions') 584 for i in sorted(self.tracefunc !! 478 for i in self.tracefuncs: 585 if 'func' in self.trac 479 if 'func' in self.tracefuncs[i]: 586 i = self.trace 480 i = self.tracefuncs[i]['func'] 587 if i in master: 481 if i in master: 588 print(i) !! 482 print i 589 else: 483 else: 590 print(self.col !! 484 print self.colorText(i) 591 def setFtraceFilterFunctions(self, lis 485 def setFtraceFilterFunctions(self, list): 592 master = self.listFromFile(sel 486 master = self.listFromFile(self.tpath+'available_filter_functions') 593 flist = '' 487 flist = '' 594 for i in list: 488 for i in list: 595 if i not in master: 489 if i not in master: 596 continue 490 continue 597 if ' [' in i: 491 if ' [' in i: 598 flist += i.spl 492 flist += i.split(' ')[0]+'\n' 599 else: 493 else: 600 flist += i+'\n 494 flist += i+'\n' 601 fp = open(self.tpath+'set_grap 495 fp = open(self.tpath+'set_graph_function', 'w') 602 fp.write(flist) 496 fp.write(flist) 603 fp.close() 497 fp.close() 604 def basicKprobe(self, name): 498 def basicKprobe(self, name): 605 self.kprobes[name] = {'name': 499 self.kprobes[name] = {'name': name,'func': name,'args': dict(),'format': name} 606 def defaultKprobe(self, name, kdata): 500 def defaultKprobe(self, name, kdata): 607 k = kdata 501 k = kdata 608 for field in ['name', 'format' 502 for field in ['name', 'format', 'func']: 609 if field not in k: 503 if field not in k: 610 k[field] = nam 504 k[field] = name 611 if self.archargs in k: 505 if self.archargs in k: 612 k['args'] = k[self.arc 506 k['args'] = k[self.archargs] 613 else: 507 else: 614 k['args'] = dict() 508 k['args'] = dict() 615 k['format'] = name 509 k['format'] = name 616 self.kprobes[name] = k 510 self.kprobes[name] = k 617 def kprobeColor(self, name): 511 def kprobeColor(self, name): 618 if name not in self.kprobes or 512 if name not in self.kprobes or 'color' not in self.kprobes[name]: 619 return '' 513 return '' 620 return self.kprobes[name]['col 514 return self.kprobes[name]['color'] 621 def kprobeDisplayName(self, name, data 515 def kprobeDisplayName(self, name, dataraw): 622 if name not in self.kprobes: 516 if name not in self.kprobes: 623 self.basicKprobe(name) 517 self.basicKprobe(name) 624 data = '' 518 data = '' 625 quote=0 519 quote=0 626 # first remvoe any spaces insi 520 # first remvoe any spaces inside quotes, and the quotes 627 for c in dataraw: 521 for c in dataraw: 628 if c == '"': 522 if c == '"': 629 quote = (quote 523 quote = (quote + 1) % 2 630 if quote and c == ' ': 524 if quote and c == ' ': 631 data += '_' 525 data += '_' 632 elif c != '"': 526 elif c != '"': 633 data += c 527 data += c 634 fmt, args = self.kprobes[name] 528 fmt, args = self.kprobes[name]['format'], self.kprobes[name]['args'] 635 arglist = dict() 529 arglist = dict() 636 # now process the args 530 # now process the args 637 for arg in sorted(args): 531 for arg in sorted(args): 638 arglist[arg] = '' 532 arglist[arg] = '' 639 m = re.match(r'.* '+ar !! 533 m = re.match('.* '+arg+'=(?P<arg>.*) ', data); 640 if m: 534 if m: 641 arglist[arg] = 535 arglist[arg] = m.group('arg') 642 else: 536 else: 643 m = re.match(r !! 537 m = re.match('.* '+arg+'=(?P<arg>.*)', data); 644 if m: 538 if m: 645 arglis 539 arglist[arg] = m.group('arg') 646 out = fmt.format(**arglist) 540 out = fmt.format(**arglist) 647 out = out.replace(' ', '_').re 541 out = out.replace(' ', '_').replace('"', '') 648 return out 542 return out 649 def kprobeText(self, kname, kprobe): 543 def kprobeText(self, kname, kprobe): 650 name = fmt = func = kname 544 name = fmt = func = kname 651 args = dict() 545 args = dict() 652 if 'name' in kprobe: 546 if 'name' in kprobe: 653 name = kprobe['name'] 547 name = kprobe['name'] 654 if 'format' in kprobe: 548 if 'format' in kprobe: 655 fmt = kprobe['format'] 549 fmt = kprobe['format'] 656 if 'func' in kprobe: 550 if 'func' in kprobe: 657 func = kprobe['func'] 551 func = kprobe['func'] 658 if self.archargs in kprobe: 552 if self.archargs in kprobe: 659 args = kprobe[self.arc 553 args = kprobe[self.archargs] 660 if 'args' in kprobe: 554 if 'args' in kprobe: 661 args = kprobe['args'] 555 args = kprobe['args'] 662 if re.findall('{(?P<n>[a-z,A-Z 556 if re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', func): 663 doError('Kprobe "%s" h 557 doError('Kprobe "%s" has format info in the function name "%s"' % (name, func)) 664 for arg in re.findall('{(?P<n> 558 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', fmt): 665 if arg not in args: 559 if arg not in args: 666 doError('Kprob 560 doError('Kprobe "%s" is missing argument "%s"' % (name, arg)) 667 val = 'p:%s_cal %s' % (name, f 561 val = 'p:%s_cal %s' % (name, func) 668 for i in sorted(args): 562 for i in sorted(args): 669 val += ' %s=%s' % (i, 563 val += ' %s=%s' % (i, args[i]) 670 val += '\nr:%s_ret %s $retval\ 564 val += '\nr:%s_ret %s $retval\n' % (name, func) 671 return val 565 return val 672 def addKprobes(self, output=False): 566 def addKprobes(self, output=False): 673 if len(self.kprobes) < 1: 567 if len(self.kprobes) < 1: 674 return 568 return 675 if output: 569 if output: 676 pprint(' kprobe fun 570 pprint(' kprobe functions in this kernel:') 677 # first test each kprobe 571 # first test each kprobe 678 rejects = [] 572 rejects = [] 679 # sort kprobes: trace, ub-dev, 573 # sort kprobes: trace, ub-dev, custom, dev 680 kpl = [[], [], [], []] 574 kpl = [[], [], [], []] 681 linesout = len(self.kprobes) 575 linesout = len(self.kprobes) 682 for name in sorted(self.kprobe 576 for name in sorted(self.kprobes): 683 res = self.colorText(' 577 res = self.colorText('YES', 32) 684 if not self.testKprobe 578 if not self.testKprobe(name, self.kprobes[name]): 685 res = self.col 579 res = self.colorText('NO') 686 rejects.append 580 rejects.append(name) 687 else: 581 else: 688 if name in sel 582 if name in self.tracefuncs: 689 kpl[0] 583 kpl[0].append(name) 690 elif name in s 584 elif name in self.dev_tracefuncs: 691 if 'ub 585 if 'ub' in self.dev_tracefuncs[name]: 692 586 kpl[1].append(name) 693 else: 587 else: 694 588 kpl[3].append(name) 695 else: 589 else: 696 kpl[2] 590 kpl[2].append(name) 697 if output: 591 if output: 698 pprint(' 592 pprint(' %s: %s' % (name, res)) 699 kplist = kpl[0] + kpl[1] + kpl 593 kplist = kpl[0] + kpl[1] + kpl[2] + kpl[3] 700 # remove all failed ones from 594 # remove all failed ones from the list 701 for name in rejects: 595 for name in rejects: 702 self.kprobes.pop(name) 596 self.kprobes.pop(name) 703 # set the kprobes all at once 597 # set the kprobes all at once 704 self.fsetVal('', 'kprobe_event 598 self.fsetVal('', 'kprobe_events') 705 kprobeevents = '' 599 kprobeevents = '' 706 for kp in kplist: 600 for kp in kplist: 707 kprobeevents += self.k 601 kprobeevents += self.kprobeText(kp, self.kprobes[kp]) 708 self.fsetVal(kprobeevents, 'kp 602 self.fsetVal(kprobeevents, 'kprobe_events') 709 if output: 603 if output: 710 check = self.fgetVal(' 604 check = self.fgetVal('kprobe_events') 711 linesack = (len(check. !! 605 linesack = (len(check.split('\n')) - 1) / 2 712 pprint(' kprobe fun 606 pprint(' kprobe functions enabled: %d/%d' % (linesack, linesout)) 713 self.fsetVal('1', 'events/kpro 607 self.fsetVal('1', 'events/kprobes/enable') 714 def testKprobe(self, kname, kprobe): 608 def testKprobe(self, kname, kprobe): 715 self.fsetVal('0', 'events/kpro 609 self.fsetVal('0', 'events/kprobes/enable') 716 kprobeevents = self.kprobeText 610 kprobeevents = self.kprobeText(kname, kprobe) 717 if not kprobeevents: 611 if not kprobeevents: 718 return False 612 return False 719 try: 613 try: 720 self.fsetVal(kprobeeve 614 self.fsetVal(kprobeevents, 'kprobe_events') 721 check = self.fgetVal(' 615 check = self.fgetVal('kprobe_events') 722 except: 616 except: 723 return False 617 return False 724 linesout = len(kprobeevents.sp 618 linesout = len(kprobeevents.split('\n')) 725 linesack = len(check.split('\n 619 linesack = len(check.split('\n')) 726 if linesack < linesout: 620 if linesack < linesout: 727 return False 621 return False 728 return True 622 return True 729 def setVal(self, val, file): !! 623 def setVal(self, val, file, mode='w'): 730 if not os.path.exists(file): 624 if not os.path.exists(file): 731 return False 625 return False 732 try: 626 try: 733 fp = open(file, 'wb', !! 627 fp = open(file, mode, 0) 734 fp.write(val.encode()) !! 628 fp.write(val) 735 fp.flush() 629 fp.flush() 736 fp.close() 630 fp.close() 737 except: 631 except: 738 return False 632 return False 739 return True 633 return True 740 def fsetVal(self, val, path): !! 634 def fsetVal(self, val, path, mode='w'): 741 if not self.useftrace: !! 635 return self.setVal(val, self.tpath+path, mode) 742 return False << 743 return self.setVal(val, self.t << 744 def getVal(self, file): 636 def getVal(self, file): 745 res = '' 637 res = '' 746 if not os.path.exists(file): 638 if not os.path.exists(file): 747 return res 639 return res 748 try: 640 try: 749 fp = open(file, 'r') 641 fp = open(file, 'r') 750 res = fp.read() 642 res = fp.read() 751 fp.close() 643 fp.close() 752 except: 644 except: 753 pass 645 pass 754 return res 646 return res 755 def fgetVal(self, path): 647 def fgetVal(self, path): 756 if not self.useftrace: << 757 return '' << 758 return self.getVal(self.tpath+ 648 return self.getVal(self.tpath+path) 759 def cleanupFtrace(self): 649 def cleanupFtrace(self): 760 if self.useftrace: !! 650 if(self.usecallgraph or self.usetraceevents or self.usedevsrc): 761 self.fsetVal('0', 'eve 651 self.fsetVal('0', 'events/kprobes/enable') 762 self.fsetVal('', 'kpro 652 self.fsetVal('', 'kprobe_events') 763 self.fsetVal('1024', ' 653 self.fsetVal('1024', 'buffer_size_kb') >> 654 if self.pmdebug: >> 655 self.setVal(self.pmdebug, self.pmdpath) 764 def setupAllKprobes(self): 656 def setupAllKprobes(self): 765 for name in self.tracefuncs: 657 for name in self.tracefuncs: 766 self.defaultKprobe(nam 658 self.defaultKprobe(name, self.tracefuncs[name]) 767 for name in self.dev_tracefunc 659 for name in self.dev_tracefuncs: 768 self.defaultKprobe(nam 660 self.defaultKprobe(name, self.dev_tracefuncs[name]) 769 def isCallgraphFunc(self, name): 661 def isCallgraphFunc(self, name): 770 if len(self.tracefuncs) < 1 an 662 if len(self.tracefuncs) < 1 and self.suspendmode == 'command': 771 return True 663 return True 772 for i in self.tracefuncs: 664 for i in self.tracefuncs: 773 if 'func' in self.trac 665 if 'func' in self.tracefuncs[i]: 774 f = self.trace 666 f = self.tracefuncs[i]['func'] 775 else: 667 else: 776 f = i 668 f = i 777 if name == f: 669 if name == f: 778 return True 670 return True 779 return False 671 return False 780 def initFtrace(self, quiet=False): !! 672 def initFtrace(self): 781 if not self.useftrace: !! 673 self.printSystemInfo(False) 782 return !! 674 pprint('INITIALIZING FTRACE...') 783 if not quiet: << 784 sysvals.printSystemInf << 785 pprint('INITIALIZING F << 786 # turn trace off 675 # turn trace off 787 self.fsetVal('0', 'tracing_on' 676 self.fsetVal('0', 'tracing_on') 788 self.cleanupFtrace() 677 self.cleanupFtrace() >> 678 # pm debug messages >> 679 pv = self.getVal(self.pmdpath) >> 680 if pv != '1': >> 681 self.setVal('1', self.pmdpath) >> 682 self.pmdebug = pv 789 # set the trace clock to globa 683 # set the trace clock to global 790 self.fsetVal('global', 'trace_ 684 self.fsetVal('global', 'trace_clock') 791 self.fsetVal('nop', 'current_t 685 self.fsetVal('nop', 'current_tracer') 792 # set trace buffer to an appro 686 # set trace buffer to an appropriate value 793 cpus = max(1, self.cpucount) 687 cpus = max(1, self.cpucount) 794 if self.bufsize > 0: 688 if self.bufsize > 0: 795 tgtsize = self.bufsize 689 tgtsize = self.bufsize 796 elif self.usecallgraph or self 690 elif self.usecallgraph or self.usedevsrc: 797 bmax = (1*1024*1024) i !! 691 bmax = (1*1024*1024) if self.suspendmode == 'disk' else (3*1024*1024) 798 else (3*1024*1 << 799 tgtsize = min(self.mem 692 tgtsize = min(self.memfree, bmax) 800 else: 693 else: 801 tgtsize = 65536 694 tgtsize = 65536 802 while not self.fsetVal('%d' % !! 695 while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'): 803 # if the size failed t 696 # if the size failed to set, lower it and keep trying 804 tgtsize -= 65536 697 tgtsize -= 65536 805 if tgtsize < 65536: 698 if tgtsize < 65536: 806 tgtsize = int( 699 tgtsize = int(self.fgetVal('buffer_size_kb')) * cpus 807 break 700 break 808 self.vprint('Setting trace buf !! 701 pprint('Setting trace buffers to %d kB (%d kB per cpu)' % (tgtsize, tgtsize/cpus)) 809 # initialize the callgraph tra 702 # initialize the callgraph trace 810 if(self.usecallgraph): 703 if(self.usecallgraph): 811 # set trace type 704 # set trace type 812 self.fsetVal('function 705 self.fsetVal('function_graph', 'current_tracer') 813 self.fsetVal('', 'set_ 706 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 707 # set trace format options 819 self.fsetVal('print-pa 708 self.fsetVal('print-parent', 'trace_options') 820 self.fsetVal('funcgrap 709 self.fsetVal('funcgraph-abstime', 'trace_options') 821 self.fsetVal('funcgrap 710 self.fsetVal('funcgraph-cpu', 'trace_options') 822 self.fsetVal('funcgrap 711 self.fsetVal('funcgraph-duration', 'trace_options') 823 self.fsetVal('funcgrap 712 self.fsetVal('funcgraph-proc', 'trace_options') 824 self.fsetVal('funcgrap 713 self.fsetVal('funcgraph-tail', 'trace_options') 825 self.fsetVal('nofuncgr 714 self.fsetVal('nofuncgraph-overhead', 'trace_options') 826 self.fsetVal('context- 715 self.fsetVal('context-info', 'trace_options') 827 self.fsetVal('graph-ti 716 self.fsetVal('graph-time', 'trace_options') 828 self.fsetVal('%d' % se 717 self.fsetVal('%d' % self.max_graph_depth, 'max_graph_depth') 829 cf = ['dpm_run_callbac 718 cf = ['dpm_run_callback'] 830 if(self.usetraceevents 719 if(self.usetraceevents): 831 cf += ['dpm_pr 720 cf += ['dpm_prepare', 'dpm_complete'] 832 for fn in self.tracefu 721 for fn in self.tracefuncs: 833 if 'func' in s 722 if 'func' in self.tracefuncs[fn]: 834 cf.app 723 cf.append(self.tracefuncs[fn]['func']) 835 else: 724 else: 836 cf.app 725 cf.append(fn) 837 if self.ftop: !! 726 self.setFtraceFilterFunctions(cf) 838 self.setFtrace << 839 else: << 840 self.setFtrace << 841 # initialize the kprobe trace 727 # initialize the kprobe trace 842 elif self.usekprobes: 728 elif self.usekprobes: 843 for name in self.trace 729 for name in self.tracefuncs: 844 self.defaultKp 730 self.defaultKprobe(name, self.tracefuncs[name]) 845 if self.usedevsrc: 731 if self.usedevsrc: 846 for name in se 732 for name in self.dev_tracefuncs: 847 self.d 733 self.defaultKprobe(name, self.dev_tracefuncs[name]) 848 if not quiet: !! 734 pprint('INITIALIZING KPROBES...') 849 pprint('INITIA << 850 self.addKprobes(self.v 735 self.addKprobes(self.verbose) 851 if(self.usetraceevents): 736 if(self.usetraceevents): 852 # turn trace events on 737 # turn trace events on 853 events = iter(self.tra 738 events = iter(self.traceevents) 854 for e in events: 739 for e in events: 855 self.fsetVal(' 740 self.fsetVal('1', 'events/power/'+e+'/enable') 856 # clear the trace buffer 741 # clear the trace buffer 857 self.fsetVal('', 'trace') 742 self.fsetVal('', 'trace') 858 def verifyFtrace(self): 743 def verifyFtrace(self): 859 # files needed for any trace d 744 # files needed for any trace data 860 files = ['buffer_size_kb', 'cu 745 files = ['buffer_size_kb', 'current_tracer', 'trace', 'trace_clock', 861 'trace_marker 746 'trace_marker', 'trace_options', 'tracing_on'] 862 # files needed for callgraph t 747 # files needed for callgraph trace data 863 tp = self.tpath 748 tp = self.tpath 864 if(self.usecallgraph): 749 if(self.usecallgraph): 865 files += [ 750 files += [ 866 'available_fil 751 'available_filter_functions', 867 'set_ftrace_fi 752 'set_ftrace_filter', 868 'set_graph_fun 753 'set_graph_function' 869 ] 754 ] 870 for f in files: 755 for f in files: 871 if(os.path.exists(tp+f 756 if(os.path.exists(tp+f) == False): 872 return False 757 return False 873 return True 758 return True 874 def verifyKprobes(self): 759 def verifyKprobes(self): 875 # files needed for kprobes to 760 # files needed for kprobes to work 876 files = ['kprobe_events', 'eve 761 files = ['kprobe_events', 'events'] 877 tp = self.tpath 762 tp = self.tpath 878 for f in files: 763 for f in files: 879 if(os.path.exists(tp+f 764 if(os.path.exists(tp+f) == False): 880 return False 765 return False 881 return True 766 return True 882 def colorText(self, str, color=31): 767 def colorText(self, str, color=31): 883 if not self.ansi: 768 if not self.ansi: 884 return str 769 return str 885 return '\x1B[%d;40m%s\x1B[m' % 770 return '\x1B[%d;40m%s\x1B[m' % (color, str) 886 def writeDatafileHeader(self, filename 771 def writeDatafileHeader(self, filename, testdata): 887 fp = self.openlog(filename, 'w 772 fp = self.openlog(filename, 'w') 888 fp.write('%s\n%s\n# command | 773 fp.write('%s\n%s\n# command | %s\n' % (self.teststamp, self.sysstamp, self.cmdline)) 889 for test in testdata: 774 for test in testdata: 890 if 'fw' in test: 775 if 'fw' in test: 891 fw = test['fw' 776 fw = test['fw'] 892 if(fw): 777 if(fw): 893 fp.wri 778 fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1])) 894 if 'turbo' in test: !! 779 if 'bat' in test: 895 fp.write('# tu !! 780 (a1, c1), (a2, c2) = test['bat'] 896 if 'wifi' in test: !! 781 fp.write('# battery %s %d %s %d\n' % (a1, c1, a2, c2)) 897 fp.write('# wi << 898 if 'netfix' in test: << 899 fp.write('# ne << 900 if test['error'] or le 782 if test['error'] or len(testdata) > 1: 901 fp.write('# en 783 fp.write('# enter_sleep_error %s\n' % test['error']) 902 return fp 784 return fp 903 def sudoUserchown(self, dir): 785 def sudoUserchown(self, dir): 904 if os.path.exists(dir) and sel 786 if os.path.exists(dir) and self.sudouser: 905 cmd = 'chown -R {0}:{0 787 cmd = 'chown -R {0}:{0} {1} > /dev/null 2>&1' 906 call(cmd.format(self.s 788 call(cmd.format(self.sudouser, dir), shell=True) 907 def outputResult(self, testdata, num=0 789 def outputResult(self, testdata, num=0): 908 if not self.result: 790 if not self.result: 909 return 791 return 910 n = '' 792 n = '' 911 if num > 0: 793 if num > 0: 912 n = '%d' % num 794 n = '%d' % num 913 fp = open(self.result, 'a') 795 fp = open(self.result, 'a') 914 if 'error' in testdata: 796 if 'error' in testdata: 915 fp.write('result%s: fa 797 fp.write('result%s: fail\n' % n) 916 fp.write('error%s: %s\ 798 fp.write('error%s: %s\n' % (n, testdata['error'])) 917 else: 799 else: 918 fp.write('result%s: pa 800 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', 801 for v in ['suspend', 'resume', 'boot', 'lastinit']: 922 if v in testdata: 802 if v in testdata: 923 fp.write('%s%s 803 fp.write('%s%s: %.3f\n' % (v, n, testdata[v])) 924 for v in ['fwsuspend', 'fwresu 804 for v in ['fwsuspend', 'fwresume']: 925 if v in testdata: 805 if v in testdata: 926 fp.write('%s%s 806 fp.write('%s%s: %.3f\n' % (v, n, testdata[v] / 1000000.0)) 927 if 'bugurl' in testdata: 807 if 'bugurl' in testdata: 928 fp.write('url%s: %s\n' 808 fp.write('url%s: %s\n' % (n, testdata['bugurl'])) 929 fp.close() 809 fp.close() 930 self.sudoUserchown(self.result 810 self.sudoUserchown(self.result) 931 def configFile(self, file): 811 def configFile(self, file): 932 dir = os.path.dirname(os.path. 812 dir = os.path.dirname(os.path.realpath(__file__)) 933 if os.path.exists(file): 813 if os.path.exists(file): 934 return file 814 return file 935 elif os.path.exists(dir+'/'+fi 815 elif os.path.exists(dir+'/'+file): 936 return dir+'/'+file 816 return dir+'/'+file 937 elif os.path.exists(dir+'/conf 817 elif os.path.exists(dir+'/config/'+file): 938 return dir+'/config/'+ 818 return dir+'/config/'+file 939 return '' 819 return '' 940 def openlog(self, filename, mode): 820 def openlog(self, filename, mode): 941 isgz = self.gzip 821 isgz = self.gzip 942 if mode == 'r': 822 if mode == 'r': 943 try: 823 try: 944 with gzip.open !! 824 with gzip.open(filename, mode+'b') as fp: 945 test = 825 test = fp.read(64) 946 isgz = True 826 isgz = True 947 except: 827 except: 948 isgz = False 828 isgz = False 949 if isgz: 829 if isgz: 950 return gzip.open(filen !! 830 return gzip.open(filename, mode+'b') 951 return open(filename, mode) 831 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 832 1384 sysvals = SystemValues() 833 sysvals = SystemValues() 1385 switchvalues = ['enable', 'disable', 'on', 'o 834 switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0'] 1386 switchoff = ['disable', 'off', 'false', '0'] 835 switchoff = ['disable', 'off', 'false', '0'] 1387 suspendmodename = { 836 suspendmodename = { 1388 'standby': 'standby (S1)', !! 837 'freeze': 'Freeze (S0)', 1389 'freeze': 'freeze (S2idle)', !! 838 'standby': 'Standby (S1)', 1390 'mem': 'suspend (S3)', !! 839 'mem': 'Suspend (S3)', 1391 'disk': 'hibernate (S4)' !! 840 'disk': 'Hibernate (S4)' 1392 } 841 } 1393 842 1394 # Class: DevProps 843 # Class: DevProps 1395 # Description: 844 # Description: 1396 # Simple class which holds property va 845 # Simple class which holds property values collected 1397 # for all the devices used in the time 846 # for all the devices used in the timeline. 1398 class DevProps: 847 class DevProps: 1399 def __init__(self): 848 def __init__(self): 1400 self.syspath = '' 849 self.syspath = '' 1401 self.altname = '' 850 self.altname = '' 1402 self.isasync = True !! 851 self.async = True 1403 self.xtraclass = '' 852 self.xtraclass = '' 1404 self.xtrainfo = '' 853 self.xtrainfo = '' 1405 def out(self, dev): 854 def out(self, dev): 1406 return '%s,%s,%d;' % (dev, se !! 855 return '%s,%s,%d;' % (dev, self.altname, self.async) 1407 def debug(self, dev): 856 def debug(self, dev): 1408 pprint('%s:\n\taltname = %s\n !! 857 pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async)) 1409 def altName(self, dev): 858 def altName(self, dev): 1410 if not self.altname or self.a 859 if not self.altname or self.altname == dev: 1411 return dev 860 return dev 1412 return '%s [%s]' % (self.altn 861 return '%s [%s]' % (self.altname, dev) 1413 def xtraClass(self): 862 def xtraClass(self): 1414 if self.xtraclass: 863 if self.xtraclass: 1415 return ' '+self.xtrac 864 return ' '+self.xtraclass 1416 if not self.isasync: !! 865 if not self.async: 1417 return ' sync' 866 return ' sync' 1418 return '' 867 return '' 1419 def xtraInfo(self): 868 def xtraInfo(self): 1420 if self.xtraclass: 869 if self.xtraclass: 1421 return ' '+self.xtrac 870 return ' '+self.xtraclass 1422 if self.isasync: !! 871 if self.async: 1423 return ' (async)' !! 872 return ' async_device' 1424 return ' (sync)' !! 873 return ' sync_device' 1425 874 1426 # Class: DeviceNode 875 # Class: DeviceNode 1427 # Description: 876 # Description: 1428 # A container used to create a device 877 # A container used to create a device hierachy, with a single root node 1429 # and a tree of child nodes. Used by D 878 # and a tree of child nodes. Used by Data.deviceTopology() 1430 class DeviceNode: 879 class DeviceNode: 1431 def __init__(self, nodename, nodedept 880 def __init__(self, nodename, nodedepth): 1432 self.name = nodename 881 self.name = nodename 1433 self.children = [] 882 self.children = [] 1434 self.depth = nodedepth 883 self.depth = nodedepth 1435 884 1436 # Class: Data 885 # Class: Data 1437 # Description: 886 # Description: 1438 # The primary container for suspend/re 887 # The primary container for suspend/resume test data. There is one for 1439 # each test run. The data is organized 888 # each test run. The data is organized into a cronological hierarchy: 1440 # Data.dmesg { 889 # Data.dmesg { 1441 # phases { 890 # phases { 1442 # 10 sequential, non-ov 891 # 10 sequential, non-overlapping phases of S/R 1443 # contents: times for p 892 # contents: times for phase start/end, order/color data for html 1444 # devlist { 893 # devlist { 1445 # device callba 894 # device callback or action list for this phase 1446 # device { 895 # device { 1447 # a sin 896 # a single device callback or generic action 1448 # conte 897 # contents: start/stop times, pid/cpu/driver info 1449 # 898 # parents/children, html id for timeline/callgraph 1450 # 899 # optionally includes an ftrace callgraph 1451 # 900 # optionally includes dev/ps data 1452 # } 901 # } 1453 # } 902 # } 1454 # } 903 # } 1455 # } 904 # } 1456 # 905 # 1457 class Data: 906 class Data: 1458 phasedef = { 907 phasedef = { 1459 'suspend_prepare': {'order': 908 'suspend_prepare': {'order': 0, 'color': '#CCFFCC'}, 1460 'suspend': {'order': 909 'suspend': {'order': 1, 'color': '#88FF88'}, 1461 'suspend_late': {'order': 910 'suspend_late': {'order': 2, 'color': '#00AA00'}, 1462 'suspend_noirq': {'order': 911 'suspend_noirq': {'order': 3, 'color': '#008888'}, 1463 'suspend_machine': {'order': 912 'suspend_machine': {'order': 4, 'color': '#0000FF'}, 1464 'resume_machine': {'order': 913 'resume_machine': {'order': 5, 'color': '#FF0000'}, 1465 'resume_noirq': {'order': 914 'resume_noirq': {'order': 6, 'color': '#FF9900'}, 1466 'resume_early': {'order': 915 'resume_early': {'order': 7, 'color': '#FFCC00'}, 1467 'resume': {'order': 916 'resume': {'order': 8, 'color': '#FFFF88'}, 1468 'resume_complete': {'order': 917 'resume_complete': {'order': 9, 'color': '#FFFFCC'}, 1469 } 918 } 1470 errlist = { 919 errlist = { 1471 'HWERROR' : r'.*\[ *Hardware !! 920 'HWERROR' : '.*\[ *Hardware Error *\].*', 1472 'FWBUG' : r'.*\[ *Firmware !! 921 'FWBUG' : '.*\[ *Firmware Bug *\].*', 1473 'TASKFAIL': r'.*Freezing .*af !! 922 'BUG' : '.*BUG.*', 1474 'BUG' : r'(?i).*\bBUG\b.* !! 923 'ERROR' : '.*ERROR.*', 1475 'ERROR' : r'(?i).*\bERROR\b !! 924 'WARNING' : '.*WARNING.*', 1476 'WARNING' : r'(?i).*\bWARNING !! 925 'IRQ' : '.*genirq: .*', 1477 'FAULT' : r'(?i).*\bFAULT\b !! 926 'TASKFAIL': '.*Freezing of tasks failed.*', 1478 'FAIL' : r'(?i).*\bFAILED\ << 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 } 927 } 1491 def __init__(self, num): 928 def __init__(self, num): 1492 idchar = 'abcdefghij' 929 idchar = 'abcdefghij' 1493 self.start = 0.0 # test start 930 self.start = 0.0 # test start 1494 self.end = 0.0 # test end 931 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 932 self.tSuspended = 0.0 # low-level suspend start 1498 self.tResumed = 0.0 # low-l 933 self.tResumed = 0.0 # low-level resume start 1499 self.tKernSus = 0.0 # kerne 934 self.tKernSus = 0.0 # kernel level suspend start 1500 self.tKernRes = 0.0 # kerne 935 self.tKernRes = 0.0 # kernel level resume end 1501 self.fwValid = False # is fi 936 self.fwValid = False # is firmware data available 1502 self.fwSuspend = 0 # time 937 self.fwSuspend = 0 # time spent in firmware suspend 1503 self.fwResume = 0 # time 938 self.fwResume = 0 # time spent in firmware resume 1504 self.html_device_id = 0 939 self.html_device_id = 0 1505 self.stamp = 0 940 self.stamp = 0 1506 self.outfile = '' 941 self.outfile = '' 1507 self.kerror = False 942 self.kerror = False 1508 self.wifi = dict() !! 943 self.battery = 0 1509 self.turbostat = 0 << 1510 self.enterfail = '' 944 self.enterfail = '' 1511 self.currphase = '' 945 self.currphase = '' 1512 self.pstl = dict() # proce 946 self.pstl = dict() # process timeline 1513 self.testnumber = num 947 self.testnumber = num 1514 self.idstr = idchar[num] 948 self.idstr = idchar[num] 1515 self.dmesgtext = [] # dmesg 949 self.dmesgtext = [] # dmesg text file in memory 1516 self.dmesg = dict() # root 950 self.dmesg = dict() # root data structure 1517 self.errorinfo = {'suspend':[ 951 self.errorinfo = {'suspend':[],'resume':[]} 1518 self.tLow = [] # time 952 self.tLow = [] # time spent in low-level suspends (standby/freeze) 1519 self.devpids = [] 953 self.devpids = [] 1520 self.devicegroups = 0 954 self.devicegroups = 0 1521 def sortedPhases(self): 955 def sortedPhases(self): 1522 return sorted(self.dmesg, key 956 return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order']) 1523 def initDevicegroups(self): 957 def initDevicegroups(self): 1524 # called when phases are all 958 # called when phases are all finished being added 1525 for phase in sorted(self.dmes !! 959 for phase in self.dmesg.keys(): 1526 if '*' in phase: 960 if '*' in phase: 1527 p = phase.spl 961 p = phase.split('*') 1528 pnew = '%s%d' 962 pnew = '%s%d' % (p[0], len(p)) 1529 self.dmesg[pn 963 self.dmesg[pnew] = self.dmesg.pop(phase) 1530 self.devicegroups = [] 964 self.devicegroups = [] 1531 for phase in self.sortedPhase 965 for phase in self.sortedPhases(): 1532 self.devicegroups.app 966 self.devicegroups.append([phase]) 1533 def nextPhase(self, phase, offset): 967 def nextPhase(self, phase, offset): 1534 order = self.dmesg[phase]['or 968 order = self.dmesg[phase]['order'] + offset 1535 for p in self.dmesg: 969 for p in self.dmesg: 1536 if self.dmesg[p]['ord 970 if self.dmesg[p]['order'] == order: 1537 return p 971 return p 1538 return '' 972 return '' 1539 def lastPhase(self, depth=1): !! 973 def lastPhase(self): 1540 plist = self.sortedPhases() 974 plist = self.sortedPhases() 1541 if len(plist) < depth: !! 975 if len(plist) < 1: 1542 return '' 976 return '' 1543 return plist[-1*depth] !! 977 return plist[-1] 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): 978 def extractErrorInfo(self): 1559 lf = self.dmesgtext !! 979 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 1560 if len(self.dmesgtext) < 1 an << 1561 lf = sysvals.openlog( << 1562 i = 0 980 i = 0 1563 tp = TestProps() << 1564 list = [] 981 list = [] 1565 for line in lf: 982 for line in lf: 1566 i += 1 983 i += 1 1567 if tp.stampInfo(line, !! 984 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 1568 continue << 1569 m = re.match(r'[ \t]* << 1570 if not m: 985 if not m: 1571 continue 986 continue 1572 t = float(m.group('kt 987 t = float(m.group('ktime')) 1573 if t < self.start or 988 if t < self.start or t > self.end: 1574 continue 989 continue 1575 dir = 'suspend' if t 990 dir = 'suspend' if t < self.tSuspended else 'resume' 1576 msg = m.group('msg') 991 msg = m.group('msg') 1577 if re.match(r'capabil << 1578 continue << 1579 for err in self.errli 992 for err in self.errlist: 1580 if re.match(s 993 if re.match(self.errlist[err], msg): 1581 list. !! 994 list.append((err, dir, t, i, i)) 1582 self. 995 self.kerror = True 1583 break 996 break 1584 tp.msglist = [] !! 997 for e in list: 1585 for msg, type, dir, t, idx1, !! 998 type, dir, t, idx1, idx2 = e 1586 tp.msglist.append(msg !! 999 sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t)) 1587 self.errorinfo[dir].a 1000 self.errorinfo[dir].append((type, t, idx1, idx2)) 1588 if self.kerror: 1001 if self.kerror: 1589 sysvals.dmesglog = Tr 1002 sysvals.dmesglog = True 1590 if len(self.dmesgtext) < 1 an !! 1003 lf.close() 1591 lf.close() !! 1004 def setStart(self, time): 1592 return tp << 1593 def setStart(self, time, msg=''): << 1594 self.start = time 1005 self.start = time 1595 if msg: !! 1006 def setEnd(self, time): 1596 try: << 1597 self.hwstart << 1598 except: << 1599 self.hwstart << 1600 def setEnd(self, time, msg=''): << 1601 self.end = time 1007 self.end = time 1602 if msg: << 1603 try: << 1604 self.hwend = << 1605 except: << 1606 self.hwend = << 1607 def isTraceEventOutsideDeviceCalls(se 1008 def isTraceEventOutsideDeviceCalls(self, pid, time): 1608 for phase in self.sortedPhase 1009 for phase in self.sortedPhases(): 1609 list = self.dmesg[pha 1010 list = self.dmesg[phase]['list'] 1610 for dev in list: 1011 for dev in list: 1611 d = list[dev] 1012 d = list[dev] 1612 if(d['pid'] = 1013 if(d['pid'] == pid and time >= d['start'] and 1613 time 1014 time < d['end']): 1614 retur 1015 return False 1615 return True 1016 return True 1616 def sourcePhase(self, start): 1017 def sourcePhase(self, start): 1617 for phase in self.sortedPhase 1018 for phase in self.sortedPhases(): 1618 if 'machine' in phase 1019 if 'machine' in phase: 1619 continue 1020 continue 1620 pend = self.dmesg[pha 1021 pend = self.dmesg[phase]['end'] 1621 if start <= pend: 1022 if start <= pend: 1622 return phase 1023 return phase 1623 return 'resume_complete' if ' !! 1024 return 'resume_complete' 1624 def sourceDevice(self, phaselist, sta 1025 def sourceDevice(self, phaselist, start, end, pid, type): 1625 tgtdev = '' 1026 tgtdev = '' 1626 for phase in phaselist: 1027 for phase in phaselist: 1627 list = self.dmesg[pha 1028 list = self.dmesg[phase]['list'] 1628 for devname in list: 1029 for devname in list: 1629 dev = list[de 1030 dev = list[devname] 1630 # pid must ma 1031 # pid must match 1631 if dev['pid'] 1032 if dev['pid'] != pid: 1632 conti 1033 continue 1633 devS = dev['s 1034 devS = dev['start'] 1634 devE = dev['e 1035 devE = dev['end'] 1635 if type == 'd 1036 if type == 'device': 1636 # dev 1037 # device target event is entirely inside the source boundary 1637 if(st 1038 if(start < devS or start >= devE or end <= devS or end > devE): 1638 1039 continue 1639 elif type == 1040 elif type == 'thread': 1640 # thr 1041 # thread target event will expand the source boundary 1641 if st 1042 if start < devS: 1642 1043 dev['start'] = start 1643 if en 1044 if end > devE: 1644 1045 dev['end'] = end 1645 tgtdev = dev 1046 tgtdev = dev 1646 break 1047 break 1647 return tgtdev 1048 return tgtdev 1648 def addDeviceFunctionCall(self, displ 1049 def addDeviceFunctionCall(self, displayname, kprobename, proc, pid, start, end, cdata, rdata): 1649 # try to place the call in a 1050 # try to place the call in a device 1650 phases = self.sortedPhases() 1051 phases = self.sortedPhases() 1651 tgtdev = self.sourceDevice(ph 1052 tgtdev = self.sourceDevice(phases, start, end, pid, 'device') 1652 # calls with device pids that 1053 # calls with device pids that occur outside device bounds are dropped 1653 # TODO: include these somehow 1054 # TODO: include these somehow 1654 if not tgtdev and pid in self 1055 if not tgtdev and pid in self.devpids: 1655 return False 1056 return False 1656 # try to place the call in a 1057 # try to place the call in a thread 1657 if not tgtdev: 1058 if not tgtdev: 1658 tgtdev = self.sourceD 1059 tgtdev = self.sourceDevice(phases, start, end, pid, 'thread') 1659 # create new thread blocks, e 1060 # create new thread blocks, expand as new calls are found 1660 if not tgtdev: 1061 if not tgtdev: 1661 if proc == '<...>': 1062 if proc == '<...>': 1662 threadname = 1063 threadname = 'kthread-%d' % (pid) 1663 else: 1064 else: 1664 threadname = 1065 threadname = '%s-%d' % (proc, pid) 1665 tgtphase = self.sourc 1066 tgtphase = self.sourcePhase(start) 1666 if not tgtphase: << 1667 return False << 1668 self.newAction(tgtpha 1067 self.newAction(tgtphase, threadname, pid, '', start, end, '', ' kth', '') 1669 return self.addDevice 1068 return self.addDeviceFunctionCall(displayname, kprobename, proc, pid, start, end, cdata, rdata) 1670 # this should not happen 1069 # this should not happen 1671 if not tgtdev: 1070 if not tgtdev: 1672 sysvals.vprint('[%f - 1071 sysvals.vprint('[%f - %f] %s-%d %s %s %s' % \ 1673 (start, end, 1072 (start, end, proc, pid, kprobename, cdata, rdata)) 1674 return False 1073 return False 1675 # place the call data inside 1074 # place the call data inside the src element of the tgtdev 1676 if('src' not in tgtdev): 1075 if('src' not in tgtdev): 1677 tgtdev['src'] = [] 1076 tgtdev['src'] = [] 1678 dtf = sysvals.dev_tracefuncs 1077 dtf = sysvals.dev_tracefuncs 1679 ubiquitous = False 1078 ubiquitous = False 1680 if kprobename in dtf and 'ub' 1079 if kprobename in dtf and 'ub' in dtf[kprobename]: 1681 ubiquitous = True 1080 ubiquitous = True 1682 mc = re.match(r'\(.*\) *(?P<a !! 1081 title = cdata+' '+rdata 1683 mr = re.match(r'\((?P<caller> !! 1082 mstr = '\(.*\) *(?P<args>.*) *\((?P<caller>.*)\+.* arg1=(?P<ret>.*)' 1684 if mc and mr: !! 1083 m = re.match(mstr, title) 1685 c = mr.group('caller' !! 1084 if m: 1686 a = mc.group('args'). !! 1085 c = m.group('caller') 1687 r = mr.group('ret') !! 1086 a = m.group('args').strip() >> 1087 r = m.group('ret') 1688 if len(r) > 6: 1088 if len(r) > 6: 1689 r = '' 1089 r = '' 1690 else: 1090 else: 1691 r = 'ret=%s ' 1091 r = 'ret=%s ' % r 1692 if ubiquitous and c i 1092 if ubiquitous and c in dtf and 'ub' in dtf[c]: 1693 return False 1093 return False 1694 else: << 1695 return False << 1696 color = sysvals.kprobeColor(k 1094 color = sysvals.kprobeColor(kprobename) 1697 e = DevFunction(displayname, 1095 e = DevFunction(displayname, a, c, r, start, end, ubiquitous, proc, pid, color) 1698 tgtdev['src'].append(e) 1096 tgtdev['src'].append(e) 1699 return True 1097 return True 1700 def overflowDevices(self): 1098 def overflowDevices(self): 1701 # get a list of devices that 1099 # get a list of devices that extend beyond the end of this test run 1702 devlist = [] 1100 devlist = [] 1703 for phase in self.sortedPhase 1101 for phase in self.sortedPhases(): 1704 list = self.dmesg[pha 1102 list = self.dmesg[phase]['list'] 1705 for devname in list: 1103 for devname in list: 1706 dev = list[de 1104 dev = list[devname] 1707 if dev['end'] 1105 if dev['end'] > self.end: 1708 devli 1106 devlist.append(dev) 1709 return devlist 1107 return devlist 1710 def mergeOverlapDevices(self, devlist 1108 def mergeOverlapDevices(self, devlist): 1711 # merge any devices that over 1109 # merge any devices that overlap devlist 1712 for dev in devlist: 1110 for dev in devlist: 1713 devname = dev['name'] 1111 devname = dev['name'] 1714 for phase in self.sor 1112 for phase in self.sortedPhases(): 1715 list = self.d 1113 list = self.dmesg[phase]['list'] 1716 if devname no 1114 if devname not in list: 1717 conti 1115 continue 1718 tdev = list[d 1116 tdev = list[devname] 1719 o = min(dev[' 1117 o = min(dev['end'], tdev['end']) - max(dev['start'], tdev['start']) 1720 if o <= 0: 1118 if o <= 0: 1721 conti 1119 continue 1722 dev['end'] = 1120 dev['end'] = tdev['end'] 1723 if 'src' not 1121 if 'src' not in dev or 'src' not in tdev: 1724 conti 1122 continue 1725 dev['src'] += 1123 dev['src'] += tdev['src'] 1726 del list[devn 1124 del list[devname] 1727 def usurpTouchingThread(self, name, d 1125 def usurpTouchingThread(self, name, dev): 1728 # the caller test has priorit 1126 # the caller test has priority of this thread, give it to him 1729 for phase in self.sortedPhase 1127 for phase in self.sortedPhases(): 1730 list = self.dmesg[pha 1128 list = self.dmesg[phase]['list'] 1731 if name in list: 1129 if name in list: 1732 tdev = list[n 1130 tdev = list[name] 1733 if tdev['star 1131 if tdev['start'] - dev['end'] < 0.1: 1734 dev[' 1132 dev['end'] = tdev['end'] 1735 if 's 1133 if 'src' not in dev: 1736 1134 dev['src'] = [] 1737 if 's 1135 if 'src' in tdev: 1738 1136 dev['src'] += tdev['src'] 1739 del l 1137 del list[name] 1740 break 1138 break 1741 def stitchTouchingThreads(self, testl 1139 def stitchTouchingThreads(self, testlist): 1742 # merge any threads between t 1140 # merge any threads between tests that touch 1743 for phase in self.sortedPhase 1141 for phase in self.sortedPhases(): 1744 list = self.dmesg[pha 1142 list = self.dmesg[phase]['list'] 1745 for devname in list: 1143 for devname in list: 1746 dev = list[de 1144 dev = list[devname] 1747 if 'htmlclass 1145 if 'htmlclass' not in dev or 'kth' not in dev['htmlclass']: 1748 conti 1146 continue 1749 for data in t 1147 for data in testlist: 1750 data. 1148 data.usurpTouchingThread(devname, dev) 1751 def optimizeDevSrc(self): 1149 def optimizeDevSrc(self): 1752 # merge any src call loops to 1150 # merge any src call loops to reduce timeline size 1753 for phase in self.sortedPhase 1151 for phase in self.sortedPhases(): 1754 list = self.dmesg[pha 1152 list = self.dmesg[phase]['list'] 1755 for dev in list: 1153 for dev in list: 1756 if 'src' not 1154 if 'src' not in list[dev]: 1757 conti 1155 continue 1758 src = list[de 1156 src = list[dev]['src'] 1759 p = 0 1157 p = 0 1760 for e in sort 1158 for e in sorted(src, key=lambda event: event.time): 1761 if no 1159 if not p or not e.repeat(p): 1762 1160 p = e 1763 1161 continue 1764 # e i 1162 # e is another iteration of p, move it into p 1765 p.end 1163 p.end = e.end 1766 p.len 1164 p.length = p.end - p.time 1767 p.cou 1165 p.count += 1 1768 src.r 1166 src.remove(e) 1769 def trimTimeVal(self, t, t0, dT, left 1167 def trimTimeVal(self, t, t0, dT, left): 1770 if left: 1168 if left: 1771 if(t > t0): 1169 if(t > t0): 1772 if(t - dT < t 1170 if(t - dT < t0): 1773 retur 1171 return t0 1774 return t - dT 1172 return t - dT 1775 else: 1173 else: 1776 return t 1174 return t 1777 else: 1175 else: 1778 if(t < t0 + dT): 1176 if(t < t0 + dT): 1779 if(t > t0): 1177 if(t > t0): 1780 retur 1178 return t0 + dT 1781 return t + dT 1179 return t + dT 1782 else: 1180 else: 1783 return t 1181 return t 1784 def trimTime(self, t0, dT, left): 1182 def trimTime(self, t0, dT, left): 1785 self.tSuspended = self.trimTi 1183 self.tSuspended = self.trimTimeVal(self.tSuspended, t0, dT, left) 1786 self.tResumed = self.trimTime 1184 self.tResumed = self.trimTimeVal(self.tResumed, t0, dT, left) 1787 self.start = self.trimTimeVal 1185 self.start = self.trimTimeVal(self.start, t0, dT, left) 1788 self.tKernSus = self.trimTime 1186 self.tKernSus = self.trimTimeVal(self.tKernSus, t0, dT, left) 1789 self.tKernRes = self.trimTime 1187 self.tKernRes = self.trimTimeVal(self.tKernRes, t0, dT, left) 1790 self.end = self.trimTimeVal(s 1188 self.end = self.trimTimeVal(self.end, t0, dT, left) 1791 for phase in self.sortedPhase 1189 for phase in self.sortedPhases(): 1792 p = self.dmesg[phase] 1190 p = self.dmesg[phase] 1793 p['start'] = self.tri 1191 p['start'] = self.trimTimeVal(p['start'], t0, dT, left) 1794 p['end'] = self.trimT 1192 p['end'] = self.trimTimeVal(p['end'], t0, dT, left) 1795 list = p['list'] 1193 list = p['list'] 1796 for name in list: 1194 for name in list: 1797 d = list[name 1195 d = list[name] 1798 d['start'] = 1196 d['start'] = self.trimTimeVal(d['start'], t0, dT, left) 1799 d['end'] = se 1197 d['end'] = self.trimTimeVal(d['end'], t0, dT, left) 1800 d['length'] = 1198 d['length'] = d['end'] - d['start'] 1801 if('ftrace' i 1199 if('ftrace' in d): 1802 cg = 1200 cg = d['ftrace'] 1803 cg.st 1201 cg.start = self.trimTimeVal(cg.start, t0, dT, left) 1804 cg.en 1202 cg.end = self.trimTimeVal(cg.end, t0, dT, left) 1805 for l 1203 for line in cg.list: 1806 1204 line.time = self.trimTimeVal(line.time, t0, dT, left) 1807 if('src' in d 1205 if('src' in d): 1808 for e 1206 for e in d['src']: 1809 1207 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 1208 for dir in ['suspend', 'resume']: 1821 list = [] 1209 list = [] 1822 for e in self.errorin 1210 for e in self.errorinfo[dir]: 1823 type, tm, idx 1211 type, tm, idx1, idx2 = e 1824 tm = self.tri 1212 tm = self.trimTimeVal(tm, t0, dT, left) 1825 list.append(( 1213 list.append((type, tm, idx1, idx2)) 1826 self.errorinfo[dir] = 1214 self.errorinfo[dir] = list 1827 def trimFreezeTime(self, tZero): 1215 def trimFreezeTime(self, tZero): 1828 # trim out any standby or fre 1216 # trim out any standby or freeze clock time 1829 lp = '' 1217 lp = '' 1830 for phase in self.sortedPhase 1218 for phase in self.sortedPhases(): 1831 if 'resume_machine' i 1219 if 'resume_machine' in phase and 'suspend_machine' in lp: 1832 tS, tR = self 1220 tS, tR = self.dmesg[lp]['end'], self.dmesg[phase]['start'] 1833 tL = tR - tS 1221 tL = tR - tS 1834 if tL <= 0: !! 1222 if tL > 0: 1835 conti !! 1223 left = True if tR > tZero else False 1836 left = True i !! 1224 self.trimTime(tS, tL, left) 1837 self.trimTime !! 1225 self.tLow.append('%.0f'%(tL*1000)) 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 1226 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): 1227 def getTimeValues(self): 1858 s = (self.tSuspended - self.t !! 1228 sktime = (self.tSuspended - self.tKernSus) * 1000 1859 r = (self.tKernRes - self.tRe !! 1229 rktime = (self.tKernRes - self.tResumed) * 1000 1860 return (max(s, 0), max(r, 0)) !! 1230 return (sktime, rktime) 1861 def setPhase(self, phase, ktime, isbe 1231 def setPhase(self, phase, ktime, isbegin, order=-1): 1862 if(isbegin): 1232 if(isbegin): 1863 # phase start over cu 1233 # phase start over current phase 1864 if self.currphase: 1234 if self.currphase: 1865 if 'resume_ma 1235 if 'resume_machine' not in self.currphase: 1866 sysva 1236 sysvals.vprint('WARNING: phase %s failed to end' % self.currphase) 1867 self.dmesg[se 1237 self.dmesg[self.currphase]['end'] = ktime 1868 phases = self.dmesg.k 1238 phases = self.dmesg.keys() 1869 color = self.phasedef 1239 color = self.phasedef[phase]['color'] 1870 count = len(phases) i 1240 count = len(phases) if order < 0 else order 1871 # create unique name 1241 # create unique name for every new phase 1872 while phase in phases 1242 while phase in phases: 1873 phase += '*' 1243 phase += '*' 1874 self.dmesg[phase] = { 1244 self.dmesg[phase] = {'list': dict(), 'start': -1.0, 'end': -1.0, 1875 'row': 0, 'co 1245 'row': 0, 'color': color, 'order': count} 1876 self.dmesg[phase]['st 1246 self.dmesg[phase]['start'] = ktime 1877 self.currphase = phas 1247 self.currphase = phase 1878 else: 1248 else: 1879 # phase end without a 1249 # phase end without a start 1880 if phase not in self. 1250 if phase not in self.currphase: 1881 if self.currp 1251 if self.currphase: 1882 sysva 1252 sysvals.vprint('WARNING: %s ended instead of %s, ftrace corruption?' % (phase, self.currphase)) 1883 else: 1253 else: 1884 sysva 1254 sysvals.vprint('WARNING: %s ended without a start, ftrace corruption?' % phase) 1885 retur 1255 return phase 1886 phase = self.currphas 1256 phase = self.currphase 1887 self.dmesg[phase]['en 1257 self.dmesg[phase]['end'] = ktime 1888 self.currphase = '' 1258 self.currphase = '' 1889 return phase 1259 return phase 1890 def sortedDevices(self, phase): 1260 def sortedDevices(self, phase): 1891 list = self.dmesg[phase]['lis 1261 list = self.dmesg[phase]['list'] 1892 return sorted(list, key=lambd !! 1262 slist = [] >> 1263 tmp = dict() >> 1264 for devname in list: >> 1265 dev = list[devname] >> 1266 if dev['length'] == 0: >> 1267 continue >> 1268 tmp[dev['start']] = devname >> 1269 for t in sorted(tmp): >> 1270 slist.append(tmp[t]) >> 1271 return slist 1893 def fixupInitcalls(self, phase): 1272 def fixupInitcalls(self, phase): 1894 # if any calls never returned 1273 # if any calls never returned, clip them at system resume end 1895 phaselist = self.dmesg[phase] 1274 phaselist = self.dmesg[phase]['list'] 1896 for devname in phaselist: 1275 for devname in phaselist: 1897 dev = phaselist[devna 1276 dev = phaselist[devname] 1898 if(dev['end'] < 0): 1277 if(dev['end'] < 0): 1899 for p in self 1278 for p in self.sortedPhases(): 1900 if se 1279 if self.dmesg[p]['end'] > dev['start']: 1901 1280 dev['end'] = self.dmesg[p]['end'] 1902 1281 break 1903 sysvals.vprin 1282 sysvals.vprint('%s (%s): callback didnt return' % (devname, phase)) 1904 def deviceFilter(self, devicefilter): 1283 def deviceFilter(self, devicefilter): 1905 for phase in self.sortedPhase 1284 for phase in self.sortedPhases(): 1906 list = self.dmesg[pha 1285 list = self.dmesg[phase]['list'] 1907 rmlist = [] 1286 rmlist = [] 1908 for name in list: 1287 for name in list: 1909 keep = False 1288 keep = False 1910 for filter in 1289 for filter in devicefilter: 1911 if fi 1290 if filter in name or \ 1912 1291 ('drv' in list[name] and filter in list[name]['drv']): 1913 1292 keep = True 1914 if not keep: 1293 if not keep: 1915 rmlis 1294 rmlist.append(name) 1916 for name in rmlist: 1295 for name in rmlist: 1917 del list[name 1296 del list[name] 1918 def fixupInitcallsThatDidntReturn(sel 1297 def fixupInitcallsThatDidntReturn(self): 1919 # if any calls never returned 1298 # if any calls never returned, clip them at system resume end 1920 for phase in self.sortedPhase 1299 for phase in self.sortedPhases(): 1921 self.fixupInitcalls(p 1300 self.fixupInitcalls(phase) 1922 def phaseOverlap(self, phases): 1301 def phaseOverlap(self, phases): 1923 rmgroups = [] 1302 rmgroups = [] 1924 newgroup = [] 1303 newgroup = [] 1925 for group in self.devicegroup 1304 for group in self.devicegroups: 1926 for phase in phases: 1305 for phase in phases: 1927 if phase not 1306 if phase not in group: 1928 conti 1307 continue 1929 for p in grou 1308 for p in group: 1930 if p 1309 if p not in newgroup: 1931 1310 newgroup.append(p) 1932 if group not 1311 if group not in rmgroups: 1933 rmgro 1312 rmgroups.append(group) 1934 for group in rmgroups: 1313 for group in rmgroups: 1935 self.devicegroups.rem 1314 self.devicegroups.remove(group) 1936 self.devicegroups.append(newg 1315 self.devicegroups.append(newgroup) 1937 def newActionGlobal(self, name, start 1316 def newActionGlobal(self, name, start, end, pid=-1, color=''): 1938 # which phase is this device 1317 # which phase is this device callback or action in 1939 phases = self.sortedPhases() 1318 phases = self.sortedPhases() 1940 targetphase = 'none' 1319 targetphase = 'none' 1941 htmlclass = '' 1320 htmlclass = '' 1942 overlap = 0.0 1321 overlap = 0.0 1943 myphases = [] 1322 myphases = [] 1944 for phase in phases: 1323 for phase in phases: 1945 pstart = self.dmesg[p 1324 pstart = self.dmesg[phase]['start'] 1946 pend = self.dmesg[pha 1325 pend = self.dmesg[phase]['end'] 1947 # see if the action o 1326 # see if the action overlaps this phase 1948 o = max(0, min(end, p 1327 o = max(0, min(end, pend) - max(start, pstart)) 1949 if o > 0: 1328 if o > 0: 1950 myphases.appe 1329 myphases.append(phase) 1951 # set the target phas 1330 # set the target phase to the one that overlaps most 1952 if o > overlap: 1331 if o > overlap: 1953 if overlap > 1332 if overlap > 0 and phase == 'post_resume': 1954 conti 1333 continue 1955 targetphase = 1334 targetphase = phase 1956 overlap = o 1335 overlap = o 1957 # if no target phase was foun 1336 # if no target phase was found, pin it to the edge 1958 if targetphase == 'none': 1337 if targetphase == 'none': 1959 p0start = self.dmesg[ 1338 p0start = self.dmesg[phases[0]]['start'] 1960 if start <= p0start: 1339 if start <= p0start: 1961 targetphase = 1340 targetphase = phases[0] 1962 else: 1341 else: 1963 targetphase = 1342 targetphase = phases[-1] 1964 if pid == -2: 1343 if pid == -2: 1965 htmlclass = ' bg' 1344 htmlclass = ' bg' 1966 elif pid == -3: 1345 elif pid == -3: 1967 htmlclass = ' ps' 1346 htmlclass = ' ps' 1968 if len(myphases) > 1: 1347 if len(myphases) > 1: 1969 htmlclass = ' bg' 1348 htmlclass = ' bg' 1970 self.phaseOverlap(myp 1349 self.phaseOverlap(myphases) 1971 if targetphase in phases: 1350 if targetphase in phases: 1972 newname = self.newAct 1351 newname = self.newAction(targetphase, name, pid, '', start, end, '', htmlclass, color) 1973 return (targetphase, 1352 return (targetphase, newname) 1974 return False 1353 return False 1975 def newAction(self, phase, name, pid, 1354 def newAction(self, phase, name, pid, parent, start, end, drv, htmlclass='', color=''): 1976 # new device callback for a s 1355 # new device callback for a specific phase 1977 self.html_device_id += 1 1356 self.html_device_id += 1 1978 devid = '%s%d' % (self.idstr, 1357 devid = '%s%d' % (self.idstr, self.html_device_id) 1979 list = self.dmesg[phase]['lis 1358 list = self.dmesg[phase]['list'] 1980 length = -1.0 1359 length = -1.0 1981 if(start >= 0 and end >= 0): 1360 if(start >= 0 and end >= 0): 1982 length = end - start 1361 length = end - start 1983 if pid == -2 or name not in s !! 1362 if pid == -2: 1984 i = 2 1363 i = 2 1985 origname = name 1364 origname = name 1986 while(name in list): 1365 while(name in list): 1987 name = '%s[%d 1366 name = '%s[%d]' % (origname, i) 1988 i += 1 1367 i += 1 1989 list[name] = {'name': name, ' 1368 list[name] = {'name': name, 'start': start, 'end': end, 'pid': pid, 1990 'par': parent, 'lengt 1369 'par': parent, 'length': length, 'row': 0, 'id': devid, 'drv': drv } 1991 if htmlclass: 1370 if htmlclass: 1992 list[name]['htmlclass 1371 list[name]['htmlclass'] = htmlclass 1993 if color: 1372 if color: 1994 list[name]['color'] = 1373 list[name]['color'] = color 1995 return name 1374 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 1375 def deviceChildren(self, devname, phase): 2006 devlist = [] 1376 devlist = [] 2007 list = self.dmesg[phase]['lis 1377 list = self.dmesg[phase]['list'] 2008 for child in list: 1378 for child in list: 2009 if(list[child]['par'] 1379 if(list[child]['par'] == devname): 2010 devlist.appen 1380 devlist.append(child) 2011 return devlist 1381 return devlist 2012 def maxDeviceNameSize(self, phase): 1382 def maxDeviceNameSize(self, phase): 2013 size = 0 1383 size = 0 2014 for name in self.dmesg[phase] 1384 for name in self.dmesg[phase]['list']: 2015 if len(name) > size: 1385 if len(name) > size: 2016 size = len(na 1386 size = len(name) 2017 return size 1387 return size 2018 def printDetails(self): 1388 def printDetails(self): 2019 sysvals.vprint('Timeline Deta 1389 sysvals.vprint('Timeline Details:') 2020 sysvals.vprint(' tes 1390 sysvals.vprint(' test start: %f' % self.start) 2021 sysvals.vprint('kernel suspen 1391 sysvals.vprint('kernel suspend start: %f' % self.tKernSus) 2022 tS = tR = False 1392 tS = tR = False 2023 for phase in self.sortedPhase 1393 for phase in self.sortedPhases(): 2024 devlist = self.dmesg[ 1394 devlist = self.dmesg[phase]['list'] 2025 dc, ps, pe = len(devl 1395 dc, ps, pe = len(devlist), self.dmesg[phase]['start'], self.dmesg[phase]['end'] 2026 if not tS and ps >= s 1396 if not tS and ps >= self.tSuspended: 2027 sysvals.vprin 1397 sysvals.vprint(' machine suspended: %f' % self.tSuspended) 2028 tS = True 1398 tS = True 2029 if not tR and ps >= s 1399 if not tR and ps >= self.tResumed: 2030 sysvals.vprin 1400 sysvals.vprint(' machine resumed: %f' % self.tResumed) 2031 tR = True 1401 tR = True 2032 sysvals.vprint('%20s: 1402 sysvals.vprint('%20s: %f - %f (%d devices)' % (phase, ps, pe, dc)) 2033 if sysvals.devdump: 1403 if sysvals.devdump: 2034 sysvals.vprin 1404 sysvals.vprint(''.join('-' for i in range(80))) 2035 maxname = '%d 1405 maxname = '%d' % self.maxDeviceNameSize(phase) 2036 fmt = '%3d) % 1406 fmt = '%3d) %'+maxname+'s - %f - %f' 2037 c = 1 1407 c = 1 2038 for name in s !! 1408 for name in devlist: 2039 s = d 1409 s = devlist[name]['start'] 2040 e = d 1410 e = devlist[name]['end'] 2041 sysva 1411 sysvals.vprint(fmt % (c, name, s, e)) 2042 c += 1412 c += 1 2043 sysvals.vprin 1413 sysvals.vprint(''.join('-' for i in range(80))) 2044 sysvals.vprint(' kernel res 1414 sysvals.vprint(' kernel resume end: %f' % self.tKernRes) 2045 sysvals.vprint(' t 1415 sysvals.vprint(' test end: %f' % self.end) 2046 def deviceChildrenAllPhases(self, dev 1416 def deviceChildrenAllPhases(self, devname): 2047 devlist = [] 1417 devlist = [] 2048 for phase in self.sortedPhase 1418 for phase in self.sortedPhases(): 2049 list = self.deviceChi 1419 list = self.deviceChildren(devname, phase) 2050 for dev in sorted(lis !! 1420 for dev in list: 2051 if dev not in 1421 if dev not in devlist: 2052 devli 1422 devlist.append(dev) 2053 return devlist 1423 return devlist 2054 def masterTopology(self, name, list, 1424 def masterTopology(self, name, list, depth): 2055 node = DeviceNode(name, depth 1425 node = DeviceNode(name, depth) 2056 for cname in list: 1426 for cname in list: 2057 # avoid recursions 1427 # avoid recursions 2058 if name == cname: 1428 if name == cname: 2059 continue 1429 continue 2060 clist = self.deviceCh 1430 clist = self.deviceChildrenAllPhases(cname) 2061 cnode = self.masterTo 1431 cnode = self.masterTopology(cname, clist, depth+1) 2062 node.children.append( 1432 node.children.append(cnode) 2063 return node 1433 return node 2064 def printTopology(self, node): 1434 def printTopology(self, node): 2065 html = '' 1435 html = '' 2066 if node.name: 1436 if node.name: 2067 info = '' 1437 info = '' 2068 drv = '' 1438 drv = '' 2069 for phase in self.sor 1439 for phase in self.sortedPhases(): 2070 list = self.d 1440 list = self.dmesg[phase]['list'] 2071 if node.name 1441 if node.name in list: 2072 s = l 1442 s = list[node.name]['start'] 2073 e = l 1443 e = list[node.name]['end'] 2074 if li 1444 if list[node.name]['drv']: 2075 1445 drv = ' {'+list[node.name]['drv']+'}' 2076 info 1446 info += ('<li>%s: %.3fms</li>' % (phase, (e-s)*1000)) 2077 html += '<li><b>'+nod 1447 html += '<li><b>'+node.name+drv+'</b>' 2078 if info: 1448 if info: 2079 html += '<ul> 1449 html += '<ul>'+info+'</ul>' 2080 html += '</li>' 1450 html += '</li>' 2081 if len(node.children) > 0: 1451 if len(node.children) > 0: 2082 html += '<ul>' 1452 html += '<ul>' 2083 for cnode in node.chi 1453 for cnode in node.children: 2084 html += self. 1454 html += self.printTopology(cnode) 2085 html += '</ul>' 1455 html += '</ul>' 2086 return html 1456 return html 2087 def rootDeviceList(self): 1457 def rootDeviceList(self): 2088 # list of devices graphed 1458 # list of devices graphed 2089 real = [] 1459 real = [] 2090 for phase in self.sortedPhase !! 1460 for phase in self.dmesg: 2091 list = self.dmesg[pha 1461 list = self.dmesg[phase]['list'] 2092 for dev in sorted(lis !! 1462 for dev in list: 2093 if list[dev][ 1463 if list[dev]['pid'] >= 0 and dev not in real: 2094 real. 1464 real.append(dev) 2095 # list of top-most root devic 1465 # list of top-most root devices 2096 rootlist = [] 1466 rootlist = [] 2097 for phase in self.sortedPhase !! 1467 for phase in self.dmesg: 2098 list = self.dmesg[pha 1468 list = self.dmesg[phase]['list'] 2099 for dev in sorted(lis !! 1469 for dev in list: 2100 pdev = list[d 1470 pdev = list[dev]['par'] 2101 pid = list[de 1471 pid = list[dev]['pid'] 2102 if(pid < 0 or !! 1472 if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)): 2103 conti 1473 continue 2104 if pdev and p 1474 if pdev and pdev not in real and pdev not in rootlist: 2105 rootl 1475 rootlist.append(pdev) 2106 return rootlist 1476 return rootlist 2107 def deviceTopology(self): 1477 def deviceTopology(self): 2108 rootlist = self.rootDeviceLis 1478 rootlist = self.rootDeviceList() 2109 master = self.masterTopology( 1479 master = self.masterTopology('', rootlist, 0) 2110 return self.printTopology(mas 1480 return self.printTopology(master) 2111 def selectTimelineDevices(self, widfm 1481 def selectTimelineDevices(self, widfmt, tTotal, mindevlen): 2112 # only select devices that wi 1482 # only select devices that will actually show up in html 2113 self.tdevlist = dict() 1483 self.tdevlist = dict() 2114 for phase in self.dmesg: 1484 for phase in self.dmesg: 2115 devlist = [] 1485 devlist = [] 2116 list = self.dmesg[pha 1486 list = self.dmesg[phase]['list'] 2117 for dev in list: 1487 for dev in list: 2118 length = (lis 1488 length = (list[dev]['end'] - list[dev]['start']) * 1000 2119 width = widfm 1489 width = widfmt % (((list[dev]['end']-list[dev]['start'])*100)/tTotal) 2120 if length >= !! 1490 if width != '0.000000' and length >= mindevlen: 2121 devli 1491 devlist.append(dev) 2122 self.tdevlist[phase] 1492 self.tdevlist[phase] = devlist 2123 def addHorizontalDivider(self, devnam 1493 def addHorizontalDivider(self, devname, devend): 2124 phase = 'suspend_prepare' 1494 phase = 'suspend_prepare' 2125 self.newAction(phase, devname 1495 self.newAction(phase, devname, -2, '', \ 2126 self.start, devend, ' 1496 self.start, devend, '', ' sec', '') 2127 if phase not in self.tdevlist 1497 if phase not in self.tdevlist: 2128 self.tdevlist[phase] 1498 self.tdevlist[phase] = [] 2129 self.tdevlist[phase].append(d 1499 self.tdevlist[phase].append(devname) 2130 d = DevItem(0, phase, self.dm 1500 d = DevItem(0, phase, self.dmesg[phase]['list'][devname]) 2131 return d 1501 return d 2132 def addProcessUsageEvent(self, name, 1502 def addProcessUsageEvent(self, name, times): 2133 # get the start and end times 1503 # get the start and end times for this process 2134 cpuexec = dict() !! 1504 maxC = 0 2135 tlast = start = end = -1 !! 1505 tlast = 0 >> 1506 start = -1 >> 1507 end = -1 2136 for t in sorted(times): 1508 for t in sorted(times): 2137 if tlast < 0: !! 1509 if tlast == 0: 2138 tlast = t 1510 tlast = t 2139 continue 1511 continue 2140 if name in self.pstl[ !! 1512 if name in self.pstl[t]: 2141 if start < 0: !! 1513 if start == -1 or tlast < start: 2142 start 1514 start = tlast 2143 end, key = t, !! 1515 if end == -1 or t > end: 2144 maxj = (t - t !! 1516 end = t 2145 cpuexec[key] << 2146 tlast = t 1517 tlast = t 2147 if start < 0 or end < 0: !! 1518 if start == -1 or end == -1: 2148 return !! 1519 return 0 2149 # add a new action for this p 1520 # add a new action for this process and get the object 2150 out = self.newActionGlobal(na 1521 out = self.newActionGlobal(name, start, end, -3) 2151 if out: !! 1522 if not out: 2152 phase, devname = out !! 1523 return 0 2153 dev = self.dmesg[phas !! 1524 phase, devname = out 2154 dev['cpuexec'] = cpue !! 1525 dev = self.dmesg[phase]['list'][devname] >> 1526 # get the cpu exec data >> 1527 tlast = 0 >> 1528 clast = 0 >> 1529 cpuexec = dict() >> 1530 for t in sorted(times): >> 1531 if tlast == 0 or t <= start or t > end: >> 1532 tlast = t >> 1533 continue >> 1534 list = self.pstl[t] >> 1535 c = 0 >> 1536 if name in list: >> 1537 c = list[name] >> 1538 if c > maxC: >> 1539 maxC = c >> 1540 if c != clast: >> 1541 key = (tlast, t) >> 1542 cpuexec[key] = c >> 1543 tlast = t >> 1544 clast = c >> 1545 dev['cpuexec'] = cpuexec >> 1546 return maxC 2155 def createProcessUsageEvents(self): 1547 def createProcessUsageEvents(self): 2156 # get an array of process nam !! 1548 # get an array of process names 2157 proclist = {'sus': dict(), 'r !! 1549 proclist = [] 2158 tdata = {'sus': [], 'res': [] !! 1550 for t in self.pstl: >> 1551 pslist = self.pstl[t] >> 1552 for ps in pslist: >> 1553 if ps not in proclist: >> 1554 proclist.append(ps) >> 1555 # get a list of data points for suspend and resume >> 1556 tsus = [] >> 1557 tres = [] 2159 for t in sorted(self.pstl): 1558 for t in sorted(self.pstl): 2160 dir = 'sus' if t < se !! 1559 if t < self.tSuspended: 2161 for ps in sorted(self !! 1560 tsus.append(t) 2162 if ps not in !! 1561 else: 2163 procl !! 1562 tres.append(t) 2164 tdata[dir].append(t) << 2165 # process the events for susp 1563 # process the events for suspend and resume 2166 if len(proclist['sus']) > 0 o !! 1564 if len(proclist) > 0: 2167 sysvals.vprint('Proce 1565 sysvals.vprint('Process Execution:') 2168 for dir in ['sus', 'res']: !! 1566 for ps in proclist: 2169 for ps in sorted(proc !! 1567 c = self.addProcessUsageEvent(ps, tsus) 2170 self.addProce !! 1568 if c > 0: 2171 def handleEndMarker(self, time, msg=' !! 1569 sysvals.vprint('%25s (sus): %d' % (ps, c)) >> 1570 c = self.addProcessUsageEvent(ps, tres) >> 1571 if c > 0: >> 1572 sysvals.vprint('%25s (res): %d' % (ps, c)) >> 1573 def handleEndMarker(self, time): 2172 dm = self.dmesg 1574 dm = self.dmesg 2173 self.setEnd(time, msg) !! 1575 self.setEnd(time) 2174 self.initDevicegroups() 1576 self.initDevicegroups() 2175 # give suspend_prepare an end 1577 # give suspend_prepare an end if needed 2176 if 'suspend_prepare' in dm an 1578 if 'suspend_prepare' in dm and dm['suspend_prepare']['end'] < 0: 2177 dm['suspend_prepare'] 1579 dm['suspend_prepare']['end'] = time 2178 # assume resume machine ends 1580 # assume resume machine ends at next phase start 2179 if 'resume_machine' in dm and 1581 if 'resume_machine' in dm and dm['resume_machine']['end'] < 0: 2180 np = self.nextPhase(' 1582 np = self.nextPhase('resume_machine', 1) 2181 if np: 1583 if np: 2182 dm['resume_ma 1584 dm['resume_machine']['end'] = dm[np]['start'] 2183 # if kernel resume end not fo 1585 # if kernel resume end not found, assume its the end marker 2184 if self.tKernRes == 0.0: 1586 if self.tKernRes == 0.0: 2185 self.tKernRes = time 1587 self.tKernRes = time 2186 # if kernel suspend start not 1588 # if kernel suspend start not found, assume its the end marker 2187 if self.tKernSus == 0.0: 1589 if self.tKernSus == 0.0: 2188 self.tKernSus = time 1590 self.tKernSus = time 2189 # set resume complete to end 1591 # set resume complete to end at end marker 2190 if 'resume_complete' in dm: 1592 if 'resume_complete' in dm: 2191 dm['resume_complete'] 1593 dm['resume_complete']['end'] = time 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): 1594 def debugPrint(self): 2217 for p in self.sortedPhases(): 1595 for p in self.sortedPhases(): 2218 list = self.dmesg[p][ 1596 list = self.dmesg[p]['list'] 2219 for devname in sorted !! 1597 for devname in list: 2220 dev = list[de 1598 dev = list[devname] 2221 if 'ftrace' i 1599 if 'ftrace' in dev: 2222 dev[' 1600 dev['ftrace'].debugPrint(' [%s]' % devname) 2223 1601 2224 # Class: DevFunction 1602 # Class: DevFunction 2225 # Description: 1603 # Description: 2226 # A container for kprobe function data 1604 # A container for kprobe function data we want in the dev timeline 2227 class DevFunction: 1605 class DevFunction: 2228 def __init__(self, name, args, caller 1606 def __init__(self, name, args, caller, ret, start, end, u, proc, pid, color): 2229 self.row = 0 1607 self.row = 0 2230 self.count = 1 1608 self.count = 1 2231 self.name = name 1609 self.name = name 2232 self.args = args 1610 self.args = args 2233 self.caller = caller 1611 self.caller = caller 2234 self.ret = ret 1612 self.ret = ret 2235 self.time = start 1613 self.time = start 2236 self.length = end - start 1614 self.length = end - start 2237 self.end = end 1615 self.end = end 2238 self.ubiquitous = u 1616 self.ubiquitous = u 2239 self.proc = proc 1617 self.proc = proc 2240 self.pid = pid 1618 self.pid = pid 2241 self.color = color 1619 self.color = color 2242 def title(self): 1620 def title(self): 2243 cnt = '' 1621 cnt = '' 2244 if self.count > 1: 1622 if self.count > 1: 2245 cnt = '(x%d)' % self. 1623 cnt = '(x%d)' % self.count 2246 l = '%0.3fms' % (self.length 1624 l = '%0.3fms' % (self.length * 1000) 2247 if self.ubiquitous: 1625 if self.ubiquitous: 2248 title = '%s(%s)%s <- 1626 title = '%s(%s)%s <- %s, %s(%s)' % \ 2249 (self.name, s 1627 (self.name, self.args, cnt, self.caller, self.ret, l) 2250 else: 1628 else: 2251 title = '%s(%s) %s%s( 1629 title = '%s(%s) %s%s(%s)' % (self.name, self.args, self.ret, cnt, l) 2252 return title.replace('"', '') 1630 return title.replace('"', '') 2253 def text(self): 1631 def text(self): 2254 if self.count > 1: 1632 if self.count > 1: 2255 text = '%s(x%d)' % (s 1633 text = '%s(x%d)' % (self.name, self.count) 2256 else: 1634 else: 2257 text = self.name 1635 text = self.name 2258 return text 1636 return text 2259 def repeat(self, tgt): 1637 def repeat(self, tgt): 2260 # is the tgt call just a repe 1638 # is the tgt call just a repeat of this call (e.g. are we in a loop) 2261 dt = self.time - tgt.end 1639 dt = self.time - tgt.end 2262 # only combine calls if -all- 1640 # only combine calls if -all- attributes are identical 2263 if tgt.caller == self.caller 1641 if tgt.caller == self.caller and \ 2264 tgt.name == self.name 1642 tgt.name == self.name and tgt.args == self.args and \ 2265 tgt.proc == self.proc 1643 tgt.proc == self.proc and tgt.pid == self.pid and \ 2266 tgt.ret == self.ret a 1644 tgt.ret == self.ret and dt >= 0 and \ 2267 dt <= sysvals.callloo 1645 dt <= sysvals.callloopmaxgap and \ 2268 self.length < sysvals 1646 self.length < sysvals.callloopmaxlen: 2269 return True 1647 return True 2270 return False 1648 return False 2271 1649 2272 # Class: FTraceLine 1650 # Class: FTraceLine 2273 # Description: 1651 # Description: 2274 # A container for a single line of ftr 1652 # A container for a single line of ftrace data. There are six basic types: 2275 # callgraph line: 1653 # callgraph line: 2276 # call: " dpm_run_ca 1654 # call: " dpm_run_callback() {" 2277 # return: " }" 1655 # return: " }" 2278 # leaf: " dpm_run_cal 1656 # leaf: " dpm_run_callback();" 2279 # trace event: 1657 # trace event: 2280 # tracing_mark_write: 1658 # tracing_mark_write: SUSPEND START or RESUME COMPLETE 2281 # suspend_resume: phas 1659 # suspend_resume: phase or custom exec block data 2282 # device_pm_callback: 1660 # device_pm_callback: device callback info 2283 class FTraceLine: 1661 class FTraceLine: 2284 def __init__(self, t, m='', d=''): 1662 def __init__(self, t, m='', d=''): 2285 self.length = 0.0 1663 self.length = 0.0 2286 self.fcall = False 1664 self.fcall = False 2287 self.freturn = False 1665 self.freturn = False 2288 self.fevent = False 1666 self.fevent = False 2289 self.fkprobe = False 1667 self.fkprobe = False 2290 self.depth = 0 1668 self.depth = 0 2291 self.name = '' 1669 self.name = '' 2292 self.type = '' 1670 self.type = '' 2293 self.time = float(t) 1671 self.time = float(t) 2294 if not m and not d: 1672 if not m and not d: 2295 return 1673 return 2296 # is this a trace event 1674 # is this a trace event 2297 if(d == 'traceevent' or re.ma !! 1675 if(d == 'traceevent' or re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m)): 2298 if(d == 'traceevent') 1676 if(d == 'traceevent'): 2299 # nop format 1677 # nop format trace event 2300 msg = m 1678 msg = m 2301 else: 1679 else: 2302 # function_gr 1680 # function_graph format trace event 2303 em = re.match !! 1681 em = re.match('^ *\/\* *(?P<msg>.*) \*\/ *$', m) 2304 msg = em.grou 1682 msg = em.group('msg') 2305 1683 2306 emm = re.match(r'^(?P !! 1684 emm = re.match('^(?P<call>.*?): (?P<msg>.*)', msg) 2307 if(emm): 1685 if(emm): 2308 self.name = e 1686 self.name = emm.group('msg') 2309 self.type = e 1687 self.type = emm.group('call') 2310 else: 1688 else: 2311 self.name = m 1689 self.name = msg 2312 km = re.match(r'^(?P< !! 1690 km = re.match('^(?P<n>.*)_cal$', self.type) 2313 if km: 1691 if km: 2314 self.fcall = 1692 self.fcall = True 2315 self.fkprobe 1693 self.fkprobe = True 2316 self.type = k 1694 self.type = km.group('n') 2317 return 1695 return 2318 km = re.match(r'^(?P< !! 1696 km = re.match('^(?P<n>.*)_ret$', self.type) 2319 if km: 1697 if km: 2320 self.freturn 1698 self.freturn = True 2321 self.fkprobe 1699 self.fkprobe = True 2322 self.type = k 1700 self.type = km.group('n') 2323 return 1701 return 2324 self.fevent = True 1702 self.fevent = True 2325 return 1703 return 2326 # convert the duration to sec 1704 # convert the duration to seconds 2327 if(d): 1705 if(d): 2328 self.length = float(d 1706 self.length = float(d)/1000000 2329 # the indentation determines 1707 # the indentation determines the depth 2330 match = re.match(r'^(?P<d> *) !! 1708 match = re.match('^(?P<d> *)(?P<o>.*)$', m) 2331 if(not match): 1709 if(not match): 2332 return 1710 return 2333 self.depth = self.getDepth(ma 1711 self.depth = self.getDepth(match.group('d')) 2334 m = match.group('o') 1712 m = match.group('o') 2335 # function return 1713 # function return 2336 if(m[0] == '}'): 1714 if(m[0] == '}'): 2337 self.freturn = True 1715 self.freturn = True 2338 if(len(m) > 1): 1716 if(len(m) > 1): 2339 # includes co 1717 # includes comment with function name 2340 match = re.ma !! 1718 match = re.match('^} *\/\* *(?P<n>.*) *\*\/$', m) 2341 if(match): 1719 if(match): 2342 self. 1720 self.name = match.group('n').strip() 2343 # function call 1721 # function call 2344 else: 1722 else: 2345 self.fcall = True 1723 self.fcall = True 2346 # function call with 1724 # function call with children 2347 if(m[-1] == '{'): 1725 if(m[-1] == '{'): 2348 match = re.ma !! 1726 match = re.match('^(?P<n>.*) *\(.*', m) 2349 if(match): 1727 if(match): 2350 self. 1728 self.name = match.group('n').strip() 2351 # function call with 1729 # function call with no children (leaf) 2352 elif(m[-1] == ';'): 1730 elif(m[-1] == ';'): 2353 self.freturn 1731 self.freturn = True 2354 match = re.ma !! 1732 match = re.match('^(?P<n>.*) *\(.*', m) 2355 if(match): 1733 if(match): 2356 self. 1734 self.name = match.group('n').strip() 2357 # something else (pos 1735 # something else (possibly a trace marker) 2358 else: 1736 else: 2359 self.name = m 1737 self.name = m 2360 def isCall(self): 1738 def isCall(self): 2361 return self.fcall and not sel 1739 return self.fcall and not self.freturn 2362 def isReturn(self): 1740 def isReturn(self): 2363 return self.freturn and not s 1741 return self.freturn and not self.fcall 2364 def isLeaf(self): 1742 def isLeaf(self): 2365 return self.fcall and self.fr 1743 return self.fcall and self.freturn 2366 def getDepth(self, str): 1744 def getDepth(self, str): 2367 return len(str)/2 1745 return len(str)/2 2368 def debugPrint(self, info=''): 1746 def debugPrint(self, info=''): 2369 if self.isLeaf(): 1747 if self.isLeaf(): 2370 pprint(' -- %12.6f (d 1748 pprint(' -- %12.6f (depth=%02d): %s(); (%.3f us) %s' % (self.time, \ 2371 self.depth, s 1749 self.depth, self.name, self.length*1000000, info)) 2372 elif self.freturn: 1750 elif self.freturn: 2373 pprint(' -- %12.6f (d 1751 pprint(' -- %12.6f (depth=%02d): %s} (%.3f us) %s' % (self.time, \ 2374 self.depth, s 1752 self.depth, self.name, self.length*1000000, info)) 2375 else: 1753 else: 2376 pprint(' -- %12.6f (d 1754 pprint(' -- %12.6f (depth=%02d): %s() { (%.3f us) %s' % (self.time, \ 2377 self.depth, s 1755 self.depth, self.name, self.length*1000000, info)) 2378 def startMarker(self): 1756 def startMarker(self): 2379 # Is this the starting line o 1757 # Is this the starting line of a suspend? 2380 if not self.fevent: 1758 if not self.fevent: 2381 return False 1759 return False 2382 if sysvals.usetracemarkers: 1760 if sysvals.usetracemarkers: 2383 if(self.name.startswi !! 1761 if(self.name == 'SUSPEND START'): 2384 return True 1762 return True 2385 return False 1763 return False 2386 else: 1764 else: 2387 if(self.type == 'susp 1765 if(self.type == 'suspend_resume' and 2388 re.match(r'su !! 1766 re.match('suspend_enter\[.*\] begin', self.name)): 2389 return True 1767 return True 2390 return False 1768 return False 2391 def endMarker(self): 1769 def endMarker(self): 2392 # Is this the ending line of 1770 # Is this the ending line of a resume? 2393 if not self.fevent: 1771 if not self.fevent: 2394 return False 1772 return False 2395 if sysvals.usetracemarkers: 1773 if sysvals.usetracemarkers: 2396 if(self.name.startswi !! 1774 if(self.name == 'RESUME COMPLETE'): 2397 return True 1775 return True 2398 return False 1776 return False 2399 else: 1777 else: 2400 if(self.type == 'susp 1778 if(self.type == 'suspend_resume' and 2401 re.match(r'th !! 1779 re.match('thaw_processes\[.*\] end', self.name)): 2402 return True 1780 return True 2403 return False 1781 return False 2404 1782 2405 # Class: FTraceCallGraph 1783 # Class: FTraceCallGraph 2406 # Description: 1784 # Description: 2407 # A container for the ftrace callgraph 1785 # A container for the ftrace callgraph of a single recursive function. 2408 # This can be a dpm_run_callback, dpm_ 1786 # This can be a dpm_run_callback, dpm_prepare, or dpm_complete callgraph 2409 # Each instance is tied to a single de 1787 # Each instance is tied to a single device in a single phase, and is 2410 # comprised of an ordered list of FTra 1788 # comprised of an ordered list of FTraceLine objects 2411 class FTraceCallGraph: 1789 class FTraceCallGraph: 2412 vfname = 'missing_function_name' 1790 vfname = 'missing_function_name' 2413 def __init__(self, pid, sv): 1791 def __init__(self, pid, sv): 2414 self.id = '' 1792 self.id = '' 2415 self.invalid = False 1793 self.invalid = False 2416 self.name = '' 1794 self.name = '' 2417 self.partial = False 1795 self.partial = False 2418 self.ignore = False 1796 self.ignore = False 2419 self.start = -1.0 1797 self.start = -1.0 2420 self.end = -1.0 1798 self.end = -1.0 2421 self.list = [] 1799 self.list = [] 2422 self.depth = 0 1800 self.depth = 0 2423 self.pid = pid 1801 self.pid = pid 2424 self.sv = sv 1802 self.sv = sv 2425 def addLine(self, line): 1803 def addLine(self, line): 2426 # if this is already invalid, 1804 # if this is already invalid, just leave 2427 if(self.invalid): 1805 if(self.invalid): 2428 if(line.depth == 0 an 1806 if(line.depth == 0 and line.freturn): 2429 return 1 1807 return 1 2430 return 0 1808 return 0 2431 # invalidate on bad depth 1809 # invalidate on bad depth 2432 if(self.depth < 0): 1810 if(self.depth < 0): 2433 self.invalidate(line) 1811 self.invalidate(line) 2434 return 0 1812 return 0 2435 # ignore data til we return t 1813 # ignore data til we return to the current depth 2436 if self.ignore: 1814 if self.ignore: 2437 if line.depth > self. 1815 if line.depth > self.depth: 2438 return 0 1816 return 0 2439 else: 1817 else: 2440 self.list[-1] 1818 self.list[-1].freturn = True 2441 self.list[-1] 1819 self.list[-1].length = line.time - self.list[-1].time 2442 self.ignore = 1820 self.ignore = False 2443 # if this is 1821 # if this is a return at self.depth, no more work is needed 2444 if line.depth 1822 if line.depth == self.depth and line.isReturn(): 2445 if li 1823 if line.depth == 0: 2446 1824 self.end = line.time 2447 1825 return 1 2448 retur 1826 return 0 2449 # compare current depth with 1827 # compare current depth with this lines pre-call depth 2450 prelinedep = line.depth 1828 prelinedep = line.depth 2451 if line.isReturn(): 1829 if line.isReturn(): 2452 prelinedep += 1 1830 prelinedep += 1 2453 last = 0 1831 last = 0 2454 lasttime = line.time 1832 lasttime = line.time 2455 if len(self.list) > 0: 1833 if len(self.list) > 0: 2456 last = self.list[-1] 1834 last = self.list[-1] 2457 lasttime = last.time 1835 lasttime = last.time 2458 if last.isLeaf(): 1836 if last.isLeaf(): 2459 lasttime += l 1837 lasttime += last.length 2460 # handle low misalignments by 1838 # handle low misalignments by inserting returns 2461 mismatch = prelinedep - self. 1839 mismatch = prelinedep - self.depth 2462 warning = self.sv.verbose and 1840 warning = self.sv.verbose and abs(mismatch) > 1 2463 info = [] 1841 info = [] 2464 if mismatch < 0: 1842 if mismatch < 0: 2465 idx = 0 1843 idx = 0 2466 # add return calls to 1844 # add return calls to get the depth down 2467 while prelinedep < se 1845 while prelinedep < self.depth: 2468 self.depth -= 1846 self.depth -= 1 2469 if idx == 0 a 1847 if idx == 0 and last and last.isCall(): 2470 # spe 1848 # special case, turn last call into a leaf 2471 last. 1849 last.depth = self.depth 2472 last. 1850 last.freturn = True 2473 last. 1851 last.length = line.time - last.time 2474 if wa 1852 if warning: 2475 1853 info.append(('[make leaf]', last)) 2476 else: 1854 else: 2477 vline 1855 vline = FTraceLine(lasttime) 2478 vline 1856 vline.depth = self.depth 2479 vline 1857 vline.name = self.vfname 2480 vline 1858 vline.freturn = True 2481 self. 1859 self.list.append(vline) 2482 if wa 1860 if warning: 2483 1861 if idx == 0: 2484 1862 info.append(('', last)) 2485 1863 info.append(('[add return]', vline)) 2486 idx += 1 1864 idx += 1 2487 if warning: 1865 if warning: 2488 info.append(( 1866 info.append(('', line)) 2489 # handle high misalignments b 1867 # handle high misalignments by inserting calls 2490 elif mismatch > 0: 1868 elif mismatch > 0: 2491 idx = 0 1869 idx = 0 2492 if warning: 1870 if warning: 2493 info.append(( 1871 info.append(('', last)) 2494 # add calls to get th 1872 # add calls to get the depth up 2495 while prelinedep > se 1873 while prelinedep > self.depth: 2496 if idx == 0 a 1874 if idx == 0 and line.isReturn(): 2497 # spe 1875 # special case, turn this return into a leaf 2498 line. 1876 line.fcall = True 2499 preli 1877 prelinedep -= 1 2500 if wa 1878 if warning: 2501 1879 info.append(('[make leaf]', line)) 2502 else: 1880 else: 2503 vline 1881 vline = FTraceLine(lasttime) 2504 vline 1882 vline.depth = self.depth 2505 vline 1883 vline.name = self.vfname 2506 vline 1884 vline.fcall = True 2507 self. 1885 self.list.append(vline) 2508 self. 1886 self.depth += 1 2509 if no 1887 if not last: 2510 1888 self.start = vline.time 2511 if wa 1889 if warning: 2512 1890 info.append(('[add call]', vline)) 2513 idx += 1 1891 idx += 1 2514 if warning and ('[mak 1892 if warning and ('[make leaf]', line) not in info: 2515 info.append(( 1893 info.append(('', line)) 2516 if warning: 1894 if warning: 2517 pprint('WARNING: ftra 1895 pprint('WARNING: ftrace data missing, corrections made:') 2518 for i in info: 1896 for i in info: 2519 t, obj = i 1897 t, obj = i 2520 if obj: 1898 if obj: 2521 obj.d 1899 obj.debugPrint(t) 2522 # process the call and set th 1900 # process the call and set the new depth 2523 skipadd = False 1901 skipadd = False 2524 md = self.sv.max_graph_depth 1902 md = self.sv.max_graph_depth 2525 if line.isCall(): 1903 if line.isCall(): 2526 # ignore blacklisted/ 1904 # ignore blacklisted/overdepth funcs 2527 if (md and self.depth 1905 if (md and self.depth >= md - 1) or (line.name in self.sv.cgblacklist): 2528 self.ignore = 1906 self.ignore = True 2529 else: 1907 else: 2530 self.depth += 1908 self.depth += 1 2531 elif line.isReturn(): 1909 elif line.isReturn(): 2532 self.depth -= 1 1910 self.depth -= 1 2533 # remove blacklisted/ 1911 # remove blacklisted/overdepth/empty funcs that slipped through 2534 if (last and last.isC 1912 if (last and last.isCall() and last.depth == line.depth) or \ 2535 (md and last 1913 (md and last and last.depth >= md) or \ 2536 (line.name in 1914 (line.name in self.sv.cgblacklist): 2537 while len(sel 1915 while len(self.list) > 0 and self.list[-1].depth > line.depth: 2538 self. 1916 self.list.pop(-1) 2539 if len(self.l 1917 if len(self.list) == 0: 2540 self. 1918 self.invalid = True 2541 retur 1919 return 1 2542 self.list[-1] 1920 self.list[-1].freturn = True 2543 self.list[-1] 1921 self.list[-1].length = line.time - self.list[-1].time 2544 self.list[-1] 1922 self.list[-1].name = line.name 2545 skipadd = Tru 1923 skipadd = True 2546 if len(self.list) < 1: 1924 if len(self.list) < 1: 2547 self.start = line.tim 1925 self.start = line.time 2548 # check for a mismatch that r 1926 # check for a mismatch that returned all the way to callgraph end 2549 res = 1 1927 res = 1 2550 if mismatch < 0 and self.list 1928 if mismatch < 0 and self.list[-1].depth == 0 and self.list[-1].freturn: 2551 line = self.list[-1] 1929 line = self.list[-1] 2552 skipadd = True 1930 skipadd = True 2553 res = -1 1931 res = -1 2554 if not skipadd: 1932 if not skipadd: 2555 self.list.append(line 1933 self.list.append(line) 2556 if(line.depth == 0 and line.f 1934 if(line.depth == 0 and line.freturn): 2557 if(self.start < 0): 1935 if(self.start < 0): 2558 self.start = 1936 self.start = line.time 2559 self.end = line.time 1937 self.end = line.time 2560 if line.fcall: 1938 if line.fcall: 2561 self.end += l 1939 self.end += line.length 2562 if self.list[0].name 1940 if self.list[0].name == self.vfname: 2563 self.invalid 1941 self.invalid = True 2564 if res == -1: 1942 if res == -1: 2565 self.partial 1943 self.partial = True 2566 return res 1944 return res 2567 return 0 1945 return 0 2568 def invalidate(self, line): 1946 def invalidate(self, line): 2569 if(len(self.list) > 0): 1947 if(len(self.list) > 0): 2570 first = self.list[0] 1948 first = self.list[0] 2571 self.list = [] 1949 self.list = [] 2572 self.list.append(firs 1950 self.list.append(first) 2573 self.invalid = True 1951 self.invalid = True 2574 id = 'task %s' % (self.pid) 1952 id = 'task %s' % (self.pid) 2575 window = '(%f - %f)' % (self. 1953 window = '(%f - %f)' % (self.start, line.time) 2576 if(self.depth < 0): 1954 if(self.depth < 0): 2577 pprint('Data misalign 1955 pprint('Data misalignment for '+id+\ 2578 ' (buffer ove 1956 ' (buffer overflow), ignoring this callback') 2579 else: 1957 else: 2580 pprint('Too much data 1958 pprint('Too much data for '+id+\ 2581 ' '+window+', 1959 ' '+window+', ignoring this callback') 2582 def slice(self, dev): 1960 def slice(self, dev): 2583 minicg = FTraceCallGraph(dev[ 1961 minicg = FTraceCallGraph(dev['pid'], self.sv) 2584 minicg.name = self.name 1962 minicg.name = self.name 2585 mydepth = -1 1963 mydepth = -1 2586 good = False 1964 good = False 2587 for l in self.list: 1965 for l in self.list: 2588 if(l.time < dev['star 1966 if(l.time < dev['start'] or l.time > dev['end']): 2589 continue 1967 continue 2590 if mydepth < 0: 1968 if mydepth < 0: 2591 if l.name == 1969 if l.name == 'mutex_lock' and l.freturn: 2592 mydep 1970 mydepth = l.depth 2593 continue 1971 continue 2594 elif l.depth == mydep 1972 elif l.depth == mydepth and l.name == 'mutex_unlock' and l.fcall: 2595 good = True 1973 good = True 2596 break 1974 break 2597 l.depth -= mydepth 1975 l.depth -= mydepth 2598 minicg.addLine(l) 1976 minicg.addLine(l) 2599 if not good or len(minicg.lis 1977 if not good or len(minicg.list) < 1: 2600 return 0 1978 return 0 2601 return minicg 1979 return minicg 2602 def repair(self, enddepth): 1980 def repair(self, enddepth): 2603 # bring the depth back to 0 w 1981 # bring the depth back to 0 with additional returns 2604 fixed = False 1982 fixed = False 2605 last = self.list[-1] 1983 last = self.list[-1] 2606 for i in reversed(range(endde 1984 for i in reversed(range(enddepth)): 2607 t = FTraceLine(last.t 1985 t = FTraceLine(last.time) 2608 t.depth = i 1986 t.depth = i 2609 t.freturn = True 1987 t.freturn = True 2610 fixed = self.addLine( 1988 fixed = self.addLine(t) 2611 if fixed != 0: 1989 if fixed != 0: 2612 self.end = la 1990 self.end = last.time 2613 return True 1991 return True 2614 return False 1992 return False 2615 def postProcess(self): 1993 def postProcess(self): 2616 if len(self.list) > 0: 1994 if len(self.list) > 0: 2617 self.name = self.list 1995 self.name = self.list[0].name 2618 stack = dict() 1996 stack = dict() 2619 cnt = 0 1997 cnt = 0 2620 last = 0 1998 last = 0 2621 for l in self.list: 1999 for l in self.list: 2622 # ftrace bug: reporte 2000 # ftrace bug: reported duration is not reliable 2623 # check each leaf and 2001 # check each leaf and clip it at max possible length 2624 if last and last.isLe 2002 if last and last.isLeaf(): 2625 if last.lengt 2003 if last.length > l.time - last.time: 2626 last. 2004 last.length = l.time - last.time 2627 if l.isCall(): 2005 if l.isCall(): 2628 stack[l.depth 2006 stack[l.depth] = l 2629 cnt += 1 2007 cnt += 1 2630 elif l.isReturn(): 2008 elif l.isReturn(): 2631 if(l.depth no 2009 if(l.depth not in stack): 2632 if se 2010 if self.sv.verbose: 2633 2011 pprint('Post Process Error: Depth missing') 2634 2012 l.debugPrint() 2635 retur 2013 return False 2636 # calculate c 2014 # calculate call length from call/return lines 2637 cl = stack[l. 2015 cl = stack[l.depth] 2638 cl.length = l 2016 cl.length = l.time - cl.time 2639 if cl.name == 2017 if cl.name == self.vfname: 2640 cl.na 2018 cl.name = l.name 2641 stack.pop(l.d 2019 stack.pop(l.depth) 2642 l.length = 0 2020 l.length = 0 2643 cnt -= 1 2021 cnt -= 1 2644 last = l 2022 last = l 2645 if(cnt == 0): 2023 if(cnt == 0): 2646 # trace caught the wh 2024 # trace caught the whole call tree 2647 return True 2025 return True 2648 elif(cnt < 0): 2026 elif(cnt < 0): 2649 if self.sv.verbose: 2027 if self.sv.verbose: 2650 pprint('Post 2028 pprint('Post Process Error: Depth is less than 0') 2651 return False 2029 return False 2652 # trace ended before call tre 2030 # trace ended before call tree finished 2653 return self.repair(cnt) 2031 return self.repair(cnt) 2654 def deviceMatch(self, pid, data): 2032 def deviceMatch(self, pid, data): 2655 found = '' 2033 found = '' 2656 # add the callgraph data to t 2034 # add the callgraph data to the device hierarchy 2657 borderphase = { 2035 borderphase = { 2658 'dpm_prepare': 'suspe 2036 'dpm_prepare': 'suspend_prepare', 2659 'dpm_complete': 'resu 2037 'dpm_complete': 'resume_complete' 2660 } 2038 } 2661 if(self.name in borderphase): 2039 if(self.name in borderphase): 2662 p = borderphase[self. 2040 p = borderphase[self.name] 2663 list = data.dmesg[p][ 2041 list = data.dmesg[p]['list'] 2664 for devname in list: 2042 for devname in list: 2665 dev = list[de 2043 dev = list[devname] 2666 if(pid == dev 2044 if(pid == dev['pid'] and 2667 self. 2045 self.start <= dev['start'] and 2668 self. 2046 self.end >= dev['end']): 2669 cg = 2047 cg = self.slice(dev) 2670 if cg 2048 if cg: 2671 2049 dev['ftrace'] = cg 2672 found 2050 found = devname 2673 return found 2051 return found 2674 for p in data.sortedPhases(): 2052 for p in data.sortedPhases(): 2675 if(data.dmesg[p]['sta 2053 if(data.dmesg[p]['start'] <= self.start and 2676 self.start <= 2054 self.start <= data.dmesg[p]['end']): 2677 list = data.d 2055 list = data.dmesg[p]['list'] 2678 for devname i !! 2056 for devname in list: 2679 dev = 2057 dev = list[devname] 2680 if(pi 2058 if(pid == dev['pid'] and 2681 2059 self.start <= dev['start'] and 2682 2060 self.end >= dev['end']): 2683 2061 dev['ftrace'] = self 2684 2062 found = devname 2685 2063 break 2686 break 2064 break 2687 return found 2065 return found 2688 def newActionFromFunction(self, data) 2066 def newActionFromFunction(self, data): 2689 name = self.name 2067 name = self.name 2690 if name in ['dpm_run_callback 2068 if name in ['dpm_run_callback', 'dpm_prepare', 'dpm_complete']: 2691 return 2069 return 2692 fs = self.start 2070 fs = self.start 2693 fe = self.end 2071 fe = self.end 2694 if fs < data.start or fe > da 2072 if fs < data.start or fe > data.end: 2695 return 2073 return 2696 phase = '' 2074 phase = '' 2697 for p in data.sortedPhases(): 2075 for p in data.sortedPhases(): 2698 if(data.dmesg[p]['sta 2076 if(data.dmesg[p]['start'] <= self.start and 2699 self.start < 2077 self.start < data.dmesg[p]['end']): 2700 phase = p 2078 phase = p 2701 break 2079 break 2702 if not phase: 2080 if not phase: 2703 return 2081 return 2704 out = data.newActionGlobal(na 2082 out = data.newActionGlobal(name, fs, fe, -2) 2705 if out: 2083 if out: 2706 phase, myname = out 2084 phase, myname = out 2707 data.dmesg[phase]['li 2085 data.dmesg[phase]['list'][myname]['ftrace'] = self 2708 def debugPrint(self, info=''): 2086 def debugPrint(self, info=''): 2709 pprint('%s pid=%d [%f - %f] % 2087 pprint('%s pid=%d [%f - %f] %.3f us' % \ 2710 (self.name, self.pid, 2088 (self.name, self.pid, self.start, self.end, 2711 (self.end - self.star 2089 (self.end - self.start)*1000000)) 2712 for l in self.list: 2090 for l in self.list: 2713 if l.isLeaf(): 2091 if l.isLeaf(): 2714 pprint('%f (% 2092 pprint('%f (%02d): %s(); (%.3f us)%s' % (l.time, \ 2715 l.dep 2093 l.depth, l.name, l.length*1000000, info)) 2716 elif l.freturn: 2094 elif l.freturn: 2717 pprint('%f (% 2095 pprint('%f (%02d): %s} (%.3f us)%s' % (l.time, \ 2718 l.dep 2096 l.depth, l.name, l.length*1000000, info)) 2719 else: 2097 else: 2720 pprint('%f (% 2098 pprint('%f (%02d): %s() { (%.3f us)%s' % (l.time, \ 2721 l.dep 2099 l.depth, l.name, l.length*1000000, info)) 2722 pprint(' ') 2100 pprint(' ') 2723 2101 2724 class DevItem: 2102 class DevItem: 2725 def __init__(self, test, phase, dev): 2103 def __init__(self, test, phase, dev): 2726 self.test = test 2104 self.test = test 2727 self.phase = phase 2105 self.phase = phase 2728 self.dev = dev 2106 self.dev = dev 2729 def isa(self, cls): 2107 def isa(self, cls): 2730 if 'htmlclass' in self.dev an 2108 if 'htmlclass' in self.dev and cls in self.dev['htmlclass']: 2731 return True 2109 return True 2732 return False 2110 return False 2733 2111 2734 # Class: Timeline 2112 # Class: Timeline 2735 # Description: 2113 # Description: 2736 # A container for a device timeline wh 2114 # A container for a device timeline which calculates 2737 # all the html properties to display i 2115 # all the html properties to display it correctly 2738 class Timeline: 2116 class Timeline: 2739 html_tblock = '<div id="block{0}" cla 2117 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="{ 2118 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 2119 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= 2120 html_phaselet = '<div id="{0}" class="phaselet" style="left:{1}%;width:{2}%;background:{3}"></div>\n' 2743 html_legend = '<div id="p{3}" class=" 2121 html_legend = '<div id="p{3}" class="square" style="left:{0}%;background:{1}"> {2}</div>\n' 2744 def __init__(self, rowheight, scalehe 2122 def __init__(self, rowheight, scaleheight): 2745 self.html = '' 2123 self.html = '' 2746 self.height = 0 # total time 2124 self.height = 0 # total timeline height 2747 self.scaleH = scaleheight # t 2125 self.scaleH = scaleheight # timescale (top) row height 2748 self.rowH = rowheight # d 2126 self.rowH = rowheight # device row height 2749 self.bodyH = 0 # body heigh 2127 self.bodyH = 0 # body height 2750 self.rows = 0 # total time 2128 self.rows = 0 # total timeline rows 2751 self.rowlines = dict() 2129 self.rowlines = dict() 2752 self.rowheight = dict() 2130 self.rowheight = dict() 2753 def createHeader(self, sv, stamp): 2131 def createHeader(self, sv, stamp): 2754 if(not stamp['time']): 2132 if(not stamp['time']): 2755 return 2133 return 2756 self.html += '<div class="ver !! 2134 self.html += '<div class="version"><a href="https://01.org/suspendresume">%s v%s</a></div>' \ 2757 % (sv.title, sv.versi 2135 % (sv.title, sv.version) 2758 if sv.logmsg and sv.testlog: 2136 if sv.logmsg and sv.testlog: 2759 self.html += '<button 2137 self.html += '<button id="showtest" class="logbtn btnfmt">log</button>' 2760 if sv.dmesglog: 2138 if sv.dmesglog: 2761 self.html += '<button 2139 self.html += '<button id="showdmesg" class="logbtn btnfmt">dmesg</button>' 2762 if sv.ftracelog: 2140 if sv.ftracelog: 2763 self.html += '<button 2141 self.html += '<button id="showftrace" class="logbtn btnfmt">ftrace</button>' 2764 headline_stamp = '<div class= 2142 headline_stamp = '<div class="stamp">{0} {1} {2} {3}</div>\n' 2765 self.html += headline_stamp.f 2143 self.html += headline_stamp.format(stamp['host'], stamp['kernel'], 2766 stamp['mode'], stamp[ 2144 stamp['mode'], stamp['time']) 2767 if 'man' in stamp and 'plat' 2145 if 'man' in stamp and 'plat' in stamp and 'cpu' in stamp and \ 2768 stamp['man'] and stam 2146 stamp['man'] and stamp['plat'] and stamp['cpu']: 2769 headline_sysinfo = '< 2147 headline_sysinfo = '<div class="stamp sysinfo">{0} {1} <i>with</i> {2}</div>\n' 2770 self.html += headline 2148 self.html += headline_sysinfo.format(stamp['man'], stamp['plat'], stamp['cpu']) 2771 2149 2772 # Function: getDeviceRows 2150 # Function: getDeviceRows 2773 # Description: 2151 # Description: 2774 # determine how may rows the devic 2152 # determine how may rows the device funcs will take 2775 # Arguments: 2153 # Arguments: 2776 # rawlist: the list of devices 2154 # rawlist: the list of devices/actions for a single phase 2777 # Output: 2155 # Output: 2778 # The total number of rows nee 2156 # The total number of rows needed to display this phase of the timeline 2779 def getDeviceRows(self, rawlist): 2157 def getDeviceRows(self, rawlist): 2780 # clear all rows and set them 2158 # clear all rows and set them to undefined 2781 sortdict = dict() 2159 sortdict = dict() 2782 for item in rawlist: 2160 for item in rawlist: 2783 item.row = -1 2161 item.row = -1 2784 sortdict[item] = item 2162 sortdict[item] = item.length 2785 sortlist = sorted(sortdict, k 2163 sortlist = sorted(sortdict, key=sortdict.get, reverse=True) 2786 remaining = len(sortlist) 2164 remaining = len(sortlist) 2787 rowdata = dict() 2165 rowdata = dict() 2788 row = 1 2166 row = 1 2789 # try to pack each row with a 2167 # try to pack each row with as many ranges as possible 2790 while(remaining > 0): 2168 while(remaining > 0): 2791 if(row not in rowdata 2169 if(row not in rowdata): 2792 rowdata[row] 2170 rowdata[row] = [] 2793 for i in sortlist: 2171 for i in sortlist: 2794 if(i.row >= 0 2172 if(i.row >= 0): 2795 conti 2173 continue 2796 s = i.time 2174 s = i.time 2797 e = i.time + 2175 e = i.time + i.length 2798 valid = True 2176 valid = True 2799 for ritem in 2177 for ritem in rowdata[row]: 2800 rs = 2178 rs = ritem.time 2801 re = 2179 re = ritem.time + ritem.length 2802 if(no 2180 if(not (((s <= rs) and (e <= rs)) or 2803 2181 ((s >= re) and (e >= re)))): 2804 2182 valid = False 2805 2183 break 2806 if(valid): 2184 if(valid): 2807 rowda 2185 rowdata[row].append(i) 2808 i.row 2186 i.row = row 2809 remai 2187 remaining -= 1 2810 row += 1 2188 row += 1 2811 return row 2189 return row 2812 # Function: getPhaseRows 2190 # Function: getPhaseRows 2813 # Description: 2191 # Description: 2814 # Organize the timeline entrie 2192 # Organize the timeline entries into the smallest 2815 # number of rows possible, wit 2193 # number of rows possible, with no entry overlapping 2816 # Arguments: 2194 # Arguments: 2817 # devlist: the list of devices 2195 # devlist: the list of devices/actions in a group of contiguous phases 2818 # Output: 2196 # Output: 2819 # The total number of rows nee 2197 # The total number of rows needed to display this phase of the timeline 2820 def getPhaseRows(self, devlist, row=0 2198 def getPhaseRows(self, devlist, row=0, sortby='length'): 2821 # clear all rows and set them 2199 # clear all rows and set them to undefined 2822 remaining = len(devlist) 2200 remaining = len(devlist) 2823 rowdata = dict() 2201 rowdata = dict() 2824 sortdict = dict() 2202 sortdict = dict() 2825 myphases = [] 2203 myphases = [] 2826 # initialize all device rows 2204 # initialize all device rows to -1 and calculate devrows 2827 for item in devlist: 2205 for item in devlist: 2828 dev = item.dev 2206 dev = item.dev 2829 tp = (item.test, item 2207 tp = (item.test, item.phase) 2830 if tp not in myphases 2208 if tp not in myphases: 2831 myphases.appe 2209 myphases.append(tp) 2832 dev['row'] = -1 2210 dev['row'] = -1 2833 if sortby == 'start': 2211 if sortby == 'start': 2834 # sort by sta 2212 # sort by start 1st, then length 2nd 2835 sortdict[item 2213 sortdict[item] = (-1*float(dev['start']), float(dev['end']) - float(dev['start'])) 2836 else: 2214 else: 2837 # sort by len 2215 # sort by length 1st, then name 2nd 2838 sortdict[item 2216 sortdict[item] = (float(dev['end']) - float(dev['start']), item.dev['name']) 2839 if 'src' in dev: 2217 if 'src' in dev: 2840 dev['devrows' 2218 dev['devrows'] = self.getDeviceRows(dev['src']) 2841 # sort the devlist by length 2219 # sort the devlist by length so that large items graph on top 2842 sortlist = sorted(sortdict, k 2220 sortlist = sorted(sortdict, key=sortdict.get, reverse=True) 2843 orderedlist = [] 2221 orderedlist = [] 2844 for item in sortlist: 2222 for item in sortlist: 2845 if item.dev['pid'] == 2223 if item.dev['pid'] == -2: 2846 orderedlist.a 2224 orderedlist.append(item) 2847 for item in sortlist: 2225 for item in sortlist: 2848 if item not in ordere 2226 if item not in orderedlist: 2849 orderedlist.a 2227 orderedlist.append(item) 2850 # try to pack each row with a 2228 # try to pack each row with as many devices as possible 2851 while(remaining > 0): 2229 while(remaining > 0): 2852 rowheight = 1 2230 rowheight = 1 2853 if(row not in rowdata 2231 if(row not in rowdata): 2854 rowdata[row] 2232 rowdata[row] = [] 2855 for item in orderedli 2233 for item in orderedlist: 2856 dev = item.de 2234 dev = item.dev 2857 if(dev['row'] 2235 if(dev['row'] < 0): 2858 s = d 2236 s = dev['start'] 2859 e = d 2237 e = dev['end'] 2860 valid 2238 valid = True 2861 for r 2239 for ritem in rowdata[row]: 2862 2240 rs = ritem.dev['start'] 2863 2241 re = ritem.dev['end'] 2864 2242 if(not (((s <= rs) and (e <= rs)) or 2865 2243 ((s >= re) and (e >= re)))): 2866 2244 valid = False 2867 2245 break 2868 if(va 2246 if(valid): 2869 2247 rowdata[row].append(item) 2870 2248 dev['row'] = row 2871 2249 remaining -= 1 2872 2250 if 'devrows' in dev and dev['devrows'] > rowheight: 2873 2251 rowheight = dev['devrows'] 2874 for t, p in myphases: 2252 for t, p in myphases: 2875 if t not in s 2253 if t not in self.rowlines or t not in self.rowheight: 2876 self. 2254 self.rowlines[t] = dict() 2877 self. 2255 self.rowheight[t] = dict() 2878 if p not in s 2256 if p not in self.rowlines[t] or p not in self.rowheight[t]: 2879 self. 2257 self.rowlines[t][p] = dict() 2880 self. 2258 self.rowheight[t][p] = dict() 2881 rh = self.row 2259 rh = self.rowH 2882 # section hea 2260 # section headers should use a different row height 2883 if len(rowdat 2261 if len(rowdata[row]) == 1 and \ 2884 'html 2262 'htmlclass' in rowdata[row][0].dev and \ 2885 'sec' 2263 'sec' in rowdata[row][0].dev['htmlclass']: 2886 rh = 2264 rh = 15 2887 self.rowlines 2265 self.rowlines[t][p][row] = rowheight 2888 self.rowheigh 2266 self.rowheight[t][p][row] = rowheight * rh 2889 row += 1 2267 row += 1 2890 if(row > self.rows): 2268 if(row > self.rows): 2891 self.rows = int(row) 2269 self.rows = int(row) 2892 return row 2270 return row 2893 def phaseRowHeight(self, test, phase, 2271 def phaseRowHeight(self, test, phase, row): 2894 return self.rowheight[test][p 2272 return self.rowheight[test][phase][row] 2895 def phaseRowTop(self, test, phase, ro 2273 def phaseRowTop(self, test, phase, row): 2896 top = 0 2274 top = 0 2897 for i in sorted(self.rowheigh 2275 for i in sorted(self.rowheight[test][phase]): 2898 if i >= row: 2276 if i >= row: 2899 break 2277 break 2900 top += self.rowheight 2278 top += self.rowheight[test][phase][i] 2901 return top 2279 return top 2902 def calcTotalRows(self): 2280 def calcTotalRows(self): 2903 # Calculate the heights and o 2281 # Calculate the heights and offsets for the header and rows 2904 maxrows = 0 2282 maxrows = 0 2905 standardphases = [] 2283 standardphases = [] 2906 for t in self.rowlines: 2284 for t in self.rowlines: 2907 for p in self.rowline 2285 for p in self.rowlines[t]: 2908 total = 0 2286 total = 0 2909 for i in sort 2287 for i in sorted(self.rowlines[t][p]): 2910 total 2288 total += self.rowlines[t][p][i] 2911 if total > ma 2289 if total > maxrows: 2912 maxro 2290 maxrows = total 2913 if total == l 2291 if total == len(self.rowlines[t][p]): 2914 stand 2292 standardphases.append((t, p)) 2915 self.height = self.scaleH + ( 2293 self.height = self.scaleH + (maxrows*self.rowH) 2916 self.bodyH = self.height - se 2294 self.bodyH = self.height - self.scaleH 2917 # if there is 1 line per row, 2295 # if there is 1 line per row, draw them the standard way 2918 for t, p in standardphases: 2296 for t, p in standardphases: 2919 for i in sorted(self. 2297 for i in sorted(self.rowheight[t][p]): 2920 self.rowheigh !! 2298 self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p]) 2921 def createZoomBox(self, mode='command 2299 def createZoomBox(self, mode='command', testcount=1): 2922 # Create bounding box, add bu 2300 # Create bounding box, add buttons 2923 html_zoombox = '<center><butt 2301 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 2302 html_timeline = '<div id="dmesgzoombox" class="zoombox">\n<div id="{0}" class="timeline" style="height:{1}px">\n' 2925 html_devlist1 = '<button id=" 2303 html_devlist1 = '<button id="devlist1" class="devlist" style="float:left;">Device Detail{0}</button>' 2926 html_devlist2 = '<button id=" 2304 html_devlist2 = '<button id="devlist2" class="devlist" style="float:right;">Device Detail2</button>\n' 2927 if mode != 'command': 2305 if mode != 'command': 2928 if testcount > 1: 2306 if testcount > 1: 2929 self.html += 2307 self.html += html_devlist2 2930 self.html += 2308 self.html += html_devlist1.format('1') 2931 else: 2309 else: 2932 self.html += 2310 self.html += html_devlist1.format('') 2933 self.html += html_zoombox 2311 self.html += html_zoombox 2934 self.html += html_timeline.fo 2312 self.html += html_timeline.format('dmesg', self.height) 2935 # Function: createTimeScale 2313 # Function: createTimeScale 2936 # Description: 2314 # Description: 2937 # Create the timescale for a t 2315 # Create the timescale for a timeline block 2938 # Arguments: 2316 # Arguments: 2939 # m0: start time (mode begin) 2317 # m0: start time (mode begin) 2940 # mMax: end time (mode end) 2318 # mMax: end time (mode end) 2941 # tTotal: total timeline time 2319 # tTotal: total timeline time 2942 # mode: suspend or resume 2320 # mode: suspend or resume 2943 # Output: 2321 # Output: 2944 # The html code needed to disp 2322 # The html code needed to display the time scale 2945 def createTimeScale(self, m0, mMax, t 2323 def createTimeScale(self, m0, mMax, tTotal, mode): 2946 timescale = '<div class="t" s 2324 timescale = '<div class="t" style="right:{0}%">{1}</div>\n' 2947 rline = '<div class="t" style 2325 rline = '<div class="t" style="left:0;border-left:1px solid black;border-right:0;">{0}</div>\n' 2948 output = '<div class="timesca 2326 output = '<div class="timescale">\n' 2949 # set scale for timeline 2327 # set scale for timeline 2950 mTotal = mMax - m0 2328 mTotal = mMax - m0 2951 tS = 0.1 2329 tS = 0.1 2952 if(tTotal <= 0): 2330 if(tTotal <= 0): 2953 return output+'</div> 2331 return output+'</div>\n' 2954 if(tTotal > 4): 2332 if(tTotal > 4): 2955 tS = 1 2333 tS = 1 2956 divTotal = int(mTotal/tS) + 1 2334 divTotal = int(mTotal/tS) + 1 2957 divEdge = (mTotal - tS*(divTo 2335 divEdge = (mTotal - tS*(divTotal-1))*100/mTotal 2958 for i in range(divTotal): 2336 for i in range(divTotal): 2959 htmlline = '' 2337 htmlline = '' 2960 if(mode == 'suspend') 2338 if(mode == 'suspend'): 2961 pos = '%0.3f' 2339 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal) - divEdge) 2962 val = '%0.fms 2340 val = '%0.fms' % (float(i-divTotal+1)*tS*1000) 2963 if(i == divTo 2341 if(i == divTotal - 1): 2964 val = 2342 val = mode 2965 htmlline = ti 2343 htmlline = timescale.format(pos, val) 2966 else: 2344 else: 2967 pos = '%0.3f' 2345 pos = '%0.3f' % (100 - ((float(i)*tS*100)/mTotal)) 2968 val = '%0.fms 2346 val = '%0.fms' % (float(i)*tS*1000) 2969 htmlline = ti 2347 htmlline = timescale.format(pos, val) 2970 if(i == 0): 2348 if(i == 0): 2971 htmll 2349 htmlline = rline.format(mode) 2972 output += htmlline 2350 output += htmlline 2973 self.html += output+'</div>\n 2351 self.html += output+'</div>\n' 2974 2352 2975 # Class: TestProps 2353 # Class: TestProps 2976 # Description: 2354 # Description: 2977 # A list of values describing the prop 2355 # A list of values describing the properties of these test runs 2978 class TestProps: 2356 class TestProps: 2979 stampfmt = r'# [a-z]*-(?P<m>[0-9]{2}) !! 2357 stampfmt = '# [a-z]*-(?P<m>[0-9]{2})(?P<d>[0-9]{2})(?P<y>[0-9]{2})-'+\ 2980 r'(?P<H>[0-9] !! 2358 '(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\ 2981 r' (?P<host>. !! 2359 ' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$' 2982 wififmt = r'^# wifi *(?P<d>\S*) *( !! 2360 batteryfmt = '^# battery (?P<a1>\w*) (?P<c1>\d*) (?P<a2>\w*) (?P<c2>\d*)' 2983 tstatfmt = r'^# turbostat (?P<t>\S* !! 2361 testerrfmt = '^# enter_sleep_error (?P<e>.*)' 2984 testerrfmt = r'^# enter_sleep_error ( !! 2362 sysinfofmt = '^# sysinfo .*' 2985 sysinfofmt = r'^# sysinfo .*' !! 2363 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2986 cmdlinefmt = r'^# command \| (?P<cmd> !! 2364 kparamsfmt = '^# kparams \| (?P<kp>.*)' 2987 kparamsfmt = r'^# kparams \| (?P<kp>. !! 2365 devpropfmt = '# Device Properties: .*' 2988 devpropfmt = r'# Device Properties: . !! 2366 tracertypefmt = '# tracer: (?P<t>.*)' 2989 pinfofmt = r'# platform-(?P<val>[a- !! 2367 firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$' 2990 tracertypefmt = r'# tracer: (?P<t>.*) !! 2368 procexecfmt = 'ps - (?P<ps>.*)$' 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 = \ 2369 ftrace_line_fmt_fg = \ 2995 r'^ *(?P<time>[0-9\.]*) *\| * !! 2370 '^ *(?P<time>[0-9\.]*) *\| *(?P<cpu>[0-9]*)\)'+\ 2996 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2371 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\|'+\ 2997 r'[ +!#\*@$]*(?P<dur>[0-9\.]* !! 2372 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)' 2998 ftrace_line_fmt_nop = \ 2373 ftrace_line_fmt_nop = \ 2999 r' *(?P<proc>.*)-(?P<pid>[0-9 !! 2374 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\ 3000 r'(?P<flags>\S*) *(?P<time>[0 !! 2375 '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\ 3001 r'(?P<msg>.*)' !! 2376 '(?P<msg>.*)' 3002 machinesuspend = r'machine_suspend\[. << 3003 multiproclist = dict() << 3004 multiproctime = 0.0 << 3005 multiproccnt = 0 << 3006 def __init__(self): 2377 def __init__(self): 3007 self.stamp = '' 2378 self.stamp = '' 3008 self.sysinfo = '' 2379 self.sysinfo = '' 3009 self.cmdline = '' 2380 self.cmdline = '' >> 2381 self.kparams = '' 3010 self.testerror = [] 2382 self.testerror = [] 3011 self.turbostat = [] !! 2383 self.battery = [] 3012 self.wifi = [] << 3013 self.fwdata = [] 2384 self.fwdata = [] 3014 self.ftrace_line_fmt = self.f 2385 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 3015 self.cgformat = False 2386 self.cgformat = False 3016 self.data = 0 2387 self.data = 0 3017 self.ktemp = dict() 2388 self.ktemp = dict() 3018 def setTracerType(self, tracer): 2389 def setTracerType(self, tracer): 3019 if(tracer == 'function_graph' 2390 if(tracer == 'function_graph'): 3020 self.cgformat = True 2391 self.cgformat = True 3021 self.ftrace_line_fmt 2392 self.ftrace_line_fmt = self.ftrace_line_fmt_fg 3022 elif(tracer == 'nop'): 2393 elif(tracer == 'nop'): 3023 self.ftrace_line_fmt 2394 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 3024 else: 2395 else: 3025 doError('Invalid trac 2396 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): 2397 def parseStamp(self, data, sv): 3061 # global test data 2398 # global test data 3062 m = re.match(self.stampfmt, s 2399 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 2400 data.stamp = {'time': '', 'host': '', 'mode': ''} 3066 dt = datetime(int(m.group('y' 2401 dt = datetime(int(m.group('y'))+2000, int(m.group('m')), 3067 int(m.group('d')), in 2402 int(m.group('d')), int(m.group('H')), int(m.group('M')), 3068 int(m.group('S'))) 2403 int(m.group('S'))) 3069 data.stamp['time'] = dt.strft 2404 data.stamp['time'] = dt.strftime('%B %d %Y, %I:%M:%S %p') 3070 data.stamp['host'] = m.group( 2405 data.stamp['host'] = m.group('host') 3071 data.stamp['mode'] = m.group( 2406 data.stamp['mode'] = m.group('mode') 3072 data.stamp['kernel'] = m.grou 2407 data.stamp['kernel'] = m.group('kernel') 3073 if re.match(self.sysinfofmt, 2408 if re.match(self.sysinfofmt, self.sysinfo): 3074 for f in self.sysinfo 2409 for f in self.sysinfo.split('|'): 3075 if '#' in f: 2410 if '#' in f: 3076 conti 2411 continue 3077 tmp = f.strip 2412 tmp = f.strip().split(':', 1) 3078 key = tmp[0] 2413 key = tmp[0] 3079 val = tmp[1] 2414 val = tmp[1] 3080 data.stamp[ke 2415 data.stamp[key] = val 3081 sv.hostname = data.stamp['hos 2416 sv.hostname = data.stamp['host'] 3082 sv.suspendmode = data.stamp[' 2417 sv.suspendmode = data.stamp['mode'] 3083 if sv.suspendmode == 'freeze' << 3084 self.machinesuspend = << 3085 else: << 3086 self.machinesuspend = << 3087 if sv.suspendmode == 'command 2418 if sv.suspendmode == 'command' and sv.ftracefile != '': 3088 modes = ['on', 'freez 2419 modes = ['on', 'freeze', 'standby', 'mem', 'disk'] 3089 fp = sv.openlog(sv.ft !! 2420 fp = sysvals.openlog(sv.ftracefile, 'r') 3090 for line in fp: 2421 for line in fp: 3091 m = re.match( !! 2422 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line) 3092 if m and m.gr 2423 if m and m.group('mode') in ['1', '2', '3', '4']: 3093 sv.su 2424 sv.suspendmode = modes[int(m.group('mode'))] 3094 data. 2425 data.stamp['mode'] = sv.suspendmode 3095 break 2426 break 3096 fp.close() 2427 fp.close() 3097 sv.cmdline = self.cmdline !! 2428 m = re.match(self.cmdlinefmt, self.cmdline) >> 2429 if m: >> 2430 sv.cmdline = m.group('cmd') >> 2431 if self.kparams: >> 2432 m = re.match(self.kparamsfmt, self.kparams) >> 2433 if m: >> 2434 sv.kparams = m.group('kp') 3098 if not sv.stamp: 2435 if not sv.stamp: 3099 sv.stamp = data.stamp 2436 sv.stamp = data.stamp 3100 # firmware data 2437 # firmware data 3101 if sv.suspendmode == 'mem' an 2438 if sv.suspendmode == 'mem' and len(self.fwdata) > data.testnumber: 3102 m = re.match(self.fir !! 2439 data.fwSuspend, data.fwResume = self.fwdata[data.testnumber] 3103 if m: !! 2440 if(data.fwSuspend > 0 or data.fwResume > 0): 3104 data.fwSuspen !! 2441 data.fwValid = True 3105 if(data.fwSus !! 2442 # battery data 3106 data. !! 2443 if len(self.battery) > data.testnumber: 3107 # turbostat data !! 2444 m = re.match(self.batteryfmt, self.battery[data.testnumber]) 3108 if len(self.turbostat) > data << 3109 m = re.match(self.tst << 3110 if m: 2445 if m: 3111 data.turbosta !! 2446 data.battery = m.groups() 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 2447 # sleep mode enter errors 3120 if len(self.testerror) > data 2448 if len(self.testerror) > data.testnumber: 3121 m = re.match(self.tes 2449 m = re.match(self.testerrfmt, self.testerror[data.testnumber]) 3122 if m: 2450 if m: 3123 data.enterfai 2451 data.enterfail = m.group('e') 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 2452 3165 # Class: TestRun 2453 # Class: TestRun 3166 # Description: 2454 # Description: 3167 # A container for a suspend/resume tes 2455 # A container for a suspend/resume test run. This is necessary as 3168 # there could be more than one, and th 2456 # there could be more than one, and they need to be separate. 3169 class TestRun: 2457 class TestRun: 3170 def __init__(self, dataobj): 2458 def __init__(self, dataobj): 3171 self.data = dataobj 2459 self.data = dataobj 3172 self.ftemp = dict() 2460 self.ftemp = dict() 3173 self.ttemp = dict() 2461 self.ttemp = dict() 3174 2462 3175 class ProcessMonitor: 2463 class ProcessMonitor: 3176 maxchars = 512 << 3177 def __init__(self): 2464 def __init__(self): 3178 self.proclist = dict() 2465 self.proclist = dict() 3179 self.running = False 2466 self.running = False 3180 def procstat(self): 2467 def procstat(self): 3181 c = ['cat /proc/[1-9]*/stat 2 2468 c = ['cat /proc/[1-9]*/stat 2>/dev/null'] 3182 process = Popen(c, shell=True 2469 process = Popen(c, shell=True, stdout=PIPE) 3183 running = dict() 2470 running = dict() 3184 for line in process.stdout: 2471 for line in process.stdout: 3185 data = ascii(line).sp !! 2472 data = line.split() 3186 pid = data[0] 2473 pid = data[0] 3187 name = re.sub('[()]', 2474 name = re.sub('[()]', '', data[1]) 3188 user = int(data[13]) 2475 user = int(data[13]) 3189 kern = int(data[14]) 2476 kern = int(data[14]) 3190 kjiff = ujiff = 0 2477 kjiff = ujiff = 0 3191 if pid not in self.pr 2478 if pid not in self.proclist: 3192 self.proclist 2479 self.proclist[pid] = {'name' : name, 'user' : user, 'kern' : kern} 3193 else: 2480 else: 3194 val = self.pr 2481 val = self.proclist[pid] 3195 ujiff = user 2482 ujiff = user - val['user'] 3196 kjiff = kern 2483 kjiff = kern - val['kern'] 3197 val['user'] = 2484 val['user'] = user 3198 val['kern'] = 2485 val['kern'] = kern 3199 if ujiff > 0 or kjiff 2486 if ujiff > 0 or kjiff > 0: 3200 running[pid] 2487 running[pid] = ujiff + kjiff 3201 process.wait() 2488 process.wait() 3202 out = [''] !! 2489 out = '' 3203 for pid in running: 2490 for pid in running: 3204 jiffies = running[pid 2491 jiffies = running[pid] 3205 val = self.proclist[p 2492 val = self.proclist[pid] 3206 if len(out[-1]) > sel !! 2493 if out: 3207 out.append('' !! 2494 out += ',' 3208 elif len(out[-1]) > 0 !! 2495 out += '%s-%s %d' % (val['name'], pid, jiffies) 3209 out[-1] += ', !! 2496 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): 2497 def processMonitor(self, tid): 3217 while self.running: 2498 while self.running: 3218 self.procstat() !! 2499 out = self.procstat() >> 2500 if out: >> 2501 sysvals.fsetVal(out, 'trace_marker') 3219 def start(self): 2502 def start(self): 3220 self.thread = Thread(target=s 2503 self.thread = Thread(target=self.processMonitor, args=(0,)) 3221 self.running = True 2504 self.running = True 3222 self.thread.start() 2505 self.thread.start() 3223 def stop(self): 2506 def stop(self): 3224 self.running = False 2507 self.running = False 3225 2508 3226 # ----------------- FUNCTIONS --------------- 2509 # ----------------- FUNCTIONS -------------------- 3227 2510 3228 # Function: doesTraceLogHaveTraceEvents 2511 # Function: doesTraceLogHaveTraceEvents 3229 # Description: 2512 # Description: 3230 # Quickly determine if the ftrace log 2513 # Quickly determine if the ftrace log has all of the trace events, 3231 # markers, and/or kprobes required for 2514 # markers, and/or kprobes required for primary parsing. 3232 def doesTraceLogHaveTraceEvents(): 2515 def doesTraceLogHaveTraceEvents(): 3233 kpcheck = ['_cal: (', '_ret: ('] !! 2516 kpcheck = ['_cal: (', '_cpu_down()'] 3234 techeck = ['suspend_resume', 'device_ !! 2517 techeck = ['suspend_resume', 'device_pm_callback'] 3235 tmcheck = ['SUSPEND START', 'RESUME C !! 2518 tmcheck = ['tracing_mark_write'] 3236 sysvals.usekprobes = False 2519 sysvals.usekprobes = False 3237 fp = sysvals.openlog(sysvals.ftracefi 2520 fp = sysvals.openlog(sysvals.ftracefile, 'r') 3238 for line in fp: 2521 for line in fp: 3239 # check for kprobes 2522 # check for kprobes 3240 if not sysvals.usekprobes: 2523 if not sysvals.usekprobes: 3241 for i in kpcheck: 2524 for i in kpcheck: 3242 if i in line: 2525 if i in line: 3243 sysva 2526 sysvals.usekprobes = True 3244 # check for all necessary tra 2527 # check for all necessary trace events 3245 check = techeck[:] 2528 check = techeck[:] 3246 for i in techeck: 2529 for i in techeck: 3247 if i in line: 2530 if i in line: 3248 check.remove( 2531 check.remove(i) 3249 techeck = check 2532 techeck = check 3250 # check for all necessary tra 2533 # check for all necessary trace markers 3251 check = tmcheck[:] 2534 check = tmcheck[:] 3252 for i in tmcheck: 2535 for i in tmcheck: 3253 if i in line: 2536 if i in line: 3254 check.remove( 2537 check.remove(i) 3255 tmcheck = check 2538 tmcheck = check 3256 fp.close() 2539 fp.close() 3257 sysvals.usetraceevents = True if len( !! 2540 sysvals.usetraceevents = True if len(techeck) < 2 else False 3258 sysvals.usetracemarkers = True if len 2541 sysvals.usetracemarkers = True if len(tmcheck) == 0 else False 3259 2542 3260 # Function: appendIncompleteTraceLog 2543 # Function: appendIncompleteTraceLog 3261 # Description: 2544 # Description: >> 2545 # [deprecated for kernel 3.15 or newer] 3262 # Adds callgraph data which lacks trac 2546 # Adds callgraph data which lacks trace event data. This is only 3263 # for timelines generated from 3.15 or 2547 # for timelines generated from 3.15 or older 3264 # Arguments: 2548 # Arguments: 3265 # testruns: the array of Data objects 2549 # testruns: the array of Data objects obtained from parseKernelLog 3266 def appendIncompleteTraceLog(testruns): 2550 def appendIncompleteTraceLog(testruns): 3267 # create TestRun vessels for ftrace p 2551 # create TestRun vessels for ftrace parsing 3268 testcnt = len(testruns) 2552 testcnt = len(testruns) 3269 testidx = 0 2553 testidx = 0 3270 testrun = [] 2554 testrun = [] 3271 for data in testruns: 2555 for data in testruns: 3272 testrun.append(TestRun(data)) 2556 testrun.append(TestRun(data)) 3273 2557 3274 # extract the callgraph and traceeven 2558 # extract the callgraph and traceevent data 3275 sysvals.vprint('Analyzing the ftrace 2559 sysvals.vprint('Analyzing the ftrace data (%s)...' % \ 3276 os.path.basename(sysvals.ftra 2560 os.path.basename(sysvals.ftracefile)) 3277 tp = TestProps() 2561 tp = TestProps() 3278 tf = sysvals.openlog(sysvals.ftracefi 2562 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3279 data = 0 2563 data = 0 3280 for line in tf: 2564 for line in tf: 3281 # remove any latent carriage 2565 # remove any latent carriage returns 3282 line = line.replace('\r\n', ' 2566 line = line.replace('\r\n', '') 3283 if tp.stampInfo(line, sysvals !! 2567 # grab the stamp and sysinfo >> 2568 if re.match(tp.stampfmt, line): >> 2569 tp.stamp = line >> 2570 continue >> 2571 elif re.match(tp.sysinfofmt, line): >> 2572 tp.sysinfo = line >> 2573 continue >> 2574 elif re.match(tp.cmdlinefmt, line): >> 2575 tp.cmdline = line >> 2576 continue >> 2577 elif re.match(tp.batteryfmt, line): >> 2578 tp.battery.append(line) >> 2579 continue >> 2580 elif re.match(tp.testerrfmt, line): >> 2581 tp.testerror.append(line) >> 2582 continue >> 2583 # determine the trace data type (required for further parsing) >> 2584 m = re.match(tp.tracertypefmt, line) >> 2585 if(m): >> 2586 tp.setTracerType(m.group('t')) >> 2587 continue >> 2588 # device properties line >> 2589 if(re.match(tp.devpropfmt, line)): >> 2590 devProps(line) 3284 continue 2591 continue 3285 # parse only valid lines, if 2592 # parse only valid lines, if this is not one move on 3286 m = re.match(tp.ftrace_line_f 2593 m = re.match(tp.ftrace_line_fmt, line) 3287 if(not m): 2594 if(not m): 3288 continue 2595 continue 3289 # gather the basic message da 2596 # gather the basic message data from the line 3290 m_time = m.group('time') 2597 m_time = m.group('time') 3291 m_pid = m.group('pid') 2598 m_pid = m.group('pid') 3292 m_msg = m.group('msg') 2599 m_msg = m.group('msg') 3293 if(tp.cgformat): 2600 if(tp.cgformat): 3294 m_param3 = m.group('d 2601 m_param3 = m.group('dur') 3295 else: 2602 else: 3296 m_param3 = 'traceeven 2603 m_param3 = 'traceevent' 3297 if(m_time and m_pid and m_msg 2604 if(m_time and m_pid and m_msg): 3298 t = FTraceLine(m_time 2605 t = FTraceLine(m_time, m_msg, m_param3) 3299 pid = int(m_pid) 2606 pid = int(m_pid) 3300 else: 2607 else: 3301 continue 2608 continue 3302 # the line should be a call, 2609 # the line should be a call, return, or event 3303 if(not t.fcall and not t.fret 2610 if(not t.fcall and not t.freturn and not t.fevent): 3304 continue 2611 continue 3305 # look for the suspend start 2612 # look for the suspend start marker 3306 if(t.startMarker()): 2613 if(t.startMarker()): 3307 data = testrun[testid 2614 data = testrun[testidx].data 3308 tp.parseStamp(data, s 2615 tp.parseStamp(data, sysvals) 3309 data.setStart(t.time, !! 2616 data.setStart(t.time) 3310 continue 2617 continue 3311 if(not data): 2618 if(not data): 3312 continue 2619 continue 3313 # find the end of resume 2620 # find the end of resume 3314 if(t.endMarker()): 2621 if(t.endMarker()): 3315 data.setEnd(t.time, t !! 2622 data.setEnd(t.time) 3316 testidx += 1 2623 testidx += 1 3317 if(testidx >= testcnt 2624 if(testidx >= testcnt): 3318 break 2625 break 3319 continue 2626 continue 3320 # trace event processing 2627 # trace event processing 3321 if(t.fevent): 2628 if(t.fevent): 3322 continue 2629 continue 3323 # call/return processing 2630 # call/return processing 3324 elif sysvals.usecallgraph: 2631 elif sysvals.usecallgraph: 3325 # create a callgraph 2632 # create a callgraph object for the data 3326 if(pid not in testrun 2633 if(pid not in testrun[testidx].ftemp): 3327 testrun[testi 2634 testrun[testidx].ftemp[pid] = [] 3328 testrun[testi 2635 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals)) 3329 # when the call is fi 2636 # when the call is finished, see which device matches it 3330 cg = testrun[testidx] 2637 cg = testrun[testidx].ftemp[pid][-1] 3331 res = cg.addLine(t) 2638 res = cg.addLine(t) 3332 if(res != 0): 2639 if(res != 0): 3333 testrun[testi 2640 testrun[testidx].ftemp[pid].append(FTraceCallGraph(pid, sysvals)) 3334 if(res == -1): 2641 if(res == -1): 3335 testrun[testi 2642 testrun[testidx].ftemp[pid][-1].addLine(t) 3336 tf.close() 2643 tf.close() 3337 2644 3338 for test in testrun: 2645 for test in testrun: 3339 # add the callgraph data to t 2646 # add the callgraph data to the device hierarchy 3340 for pid in test.ftemp: 2647 for pid in test.ftemp: 3341 for cg in test.ftemp[ 2648 for cg in test.ftemp[pid]: 3342 if len(cg.lis 2649 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3343 conti 2650 continue 3344 if(not cg.pos 2651 if(not cg.postProcess()): 3345 id = 2652 id = 'task %s cpu %s' % (pid, m.group('cpu')) 3346 sysva 2653 sysvals.vprint('Sanity check failed for '+\ 3347 2654 id+', ignoring this callback') 3348 conti 2655 continue 3349 callstart = c 2656 callstart = cg.start 3350 callend = cg. 2657 callend = cg.end 3351 for p in test 2658 for p in test.data.sortedPhases(): 3352 if(te 2659 if(test.data.dmesg[p]['start'] <= callstart and 3353 2660 callstart <= test.data.dmesg[p]['end']): 3354 2661 list = test.data.dmesg[p]['list'] 3355 2662 for devname in list: 3356 2663 dev = list[devname] 3357 2664 if(pid == dev['pid'] and 3358 2665 callstart <= dev['start'] and 3359 2666 callend >= dev['end']): 3360 2667 dev['ftrace'] = cg 3361 2668 break 3362 2669 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 2670 # Function: parseTraceLog 3419 # Description: 2671 # Description: 3420 # Analyze an ftrace log output file ge 2672 # Analyze an ftrace log output file generated from this app during 3421 # the execution phase. Used when the f 2673 # the execution phase. Used when the ftrace log is the primary data source 3422 # and includes the suspend_resume and 2674 # and includes the suspend_resume and device_pm_callback trace events 3423 # The ftrace filename is taken from sy 2675 # The ftrace filename is taken from sysvals 3424 # Output: 2676 # Output: 3425 # An array of Data objects 2677 # An array of Data objects 3426 def parseTraceLog(live=False): 2678 def parseTraceLog(live=False): 3427 sysvals.vprint('Analyzing the ftrace 2679 sysvals.vprint('Analyzing the ftrace data (%s)...' % \ 3428 os.path.basename(sysvals.ftra 2680 os.path.basename(sysvals.ftracefile)) 3429 if(os.path.exists(sysvals.ftracefile) 2681 if(os.path.exists(sysvals.ftracefile) == False): 3430 doError('%s does not exist' % 2682 doError('%s does not exist' % sysvals.ftracefile) 3431 if not live: 2683 if not live: 3432 sysvals.setupAllKprobes() 2684 sysvals.setupAllKprobes() 3433 ksuscalls = ['ksys_sync', 'pm_prepare !! 2685 ksuscalls = ['pm_prepare_console'] 3434 krescalls = ['pm_restore_console'] 2686 krescalls = ['pm_restore_console'] 3435 tracewatch = ['irq_wakeup'] !! 2687 tracewatch = [] 3436 if sysvals.usekprobes: 2688 if sysvals.usekprobes: 3437 tracewatch += ['sync_filesyst 2689 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 3438 'syscore_resume', 're 2690 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', 3439 'CPU_OFF', 'acpi_susp !! 2691 'CPU_OFF', 'timekeeping_freeze', 'acpi_suspend'] 3440 2692 3441 # extract the callgraph and traceeven 2693 # extract the callgraph and traceevent data 3442 s2idle_enter = hwsus = False !! 2694 tp = TestProps() 3443 testruns, testdata = [], [] !! 2695 testruns = [] 3444 testrun, data, limbo = 0, 0, True !! 2696 testdata = [] >> 2697 testrun = 0 >> 2698 data = 0 >> 2699 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3445 phase = 'suspend_prepare' 2700 phase = 'suspend_prepare' 3446 tp, tf = loadTraceLog() !! 2701 for line in tf: 3447 for m_time, m_proc, m_pid, m_msg, m_p !! 2702 # remove any latent carriage returns >> 2703 line = line.replace('\r\n', '') >> 2704 # stamp and sysinfo lines >> 2705 if re.match(tp.stampfmt, line): >> 2706 tp.stamp = line >> 2707 continue >> 2708 elif re.match(tp.sysinfofmt, line): >> 2709 tp.sysinfo = line >> 2710 continue >> 2711 elif re.match(tp.cmdlinefmt, line): >> 2712 tp.cmdline = line >> 2713 continue >> 2714 elif re.match(tp.batteryfmt, line): >> 2715 tp.battery.append(line) >> 2716 continue >> 2717 elif re.match(tp.testerrfmt, line): >> 2718 tp.testerror.append(line) >> 2719 continue >> 2720 # firmware line: pull out any firmware data >> 2721 m = re.match(tp.firmwarefmt, line) >> 2722 if(m): >> 2723 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) >> 2724 continue >> 2725 # tracer type line: determine the trace data type >> 2726 m = re.match(tp.tracertypefmt, line) >> 2727 if(m): >> 2728 tp.setTracerType(m.group('t')) >> 2729 continue >> 2730 # device properties line >> 2731 if(re.match(tp.devpropfmt, line)): >> 2732 devProps(line) >> 2733 continue >> 2734 # ignore all other commented lines >> 2735 if line[0] == '#': >> 2736 continue >> 2737 # ftrace line: parse only valid lines >> 2738 m = re.match(tp.ftrace_line_fmt, line) >> 2739 if(not m): >> 2740 continue 3448 # gather the basic message da 2741 # gather the basic message data from the line >> 2742 m_time = m.group('time') >> 2743 m_proc = m.group('proc') >> 2744 m_pid = m.group('pid') >> 2745 m_msg = m.group('msg') >> 2746 if(tp.cgformat): >> 2747 m_param3 = m.group('dur') >> 2748 else: >> 2749 m_param3 = 'traceevent' 3449 if(m_time and m_pid and m_msg 2750 if(m_time and m_pid and m_msg): 3450 t = FTraceLine(m_time 2751 t = FTraceLine(m_time, m_msg, m_param3) 3451 pid = int(m_pid) 2752 pid = int(m_pid) 3452 else: 2753 else: 3453 continue 2754 continue 3454 # the line should be a call, 2755 # the line should be a call, return, or event 3455 if(not t.fcall and not t.fret 2756 if(not t.fcall and not t.freturn and not t.fevent): 3456 continue 2757 continue 3457 # find the start of suspend 2758 # find the start of suspend 3458 if(t.startMarker()): 2759 if(t.startMarker()): 3459 data, limbo = Data(le !! 2760 data = Data(len(testdata)) 3460 testdata.append(data) 2761 testdata.append(data) 3461 testrun = TestRun(dat 2762 testrun = TestRun(data) 3462 testruns.append(testr 2763 testruns.append(testrun) 3463 tp.parseStamp(data, s 2764 tp.parseStamp(data, sysvals) 3464 data.setStart(t.time, !! 2765 data.setStart(t.time) 3465 data.first_suspend_pr 2766 data.first_suspend_prepare = True 3466 phase = data.setPhase 2767 phase = data.setPhase('suspend_prepare', t.time, True) 3467 continue 2768 continue 3468 if(not data or limbo): !! 2769 if(not data): 3469 continue 2770 continue 3470 # process cpu exec line 2771 # process cpu exec line 3471 if t.type == 'tracing_mark_wr 2772 if t.type == 'tracing_mark_write': 3472 if t.name == 'CMD COM << 3473 data.tKernRes << 3474 m = re.match(tp.proce 2773 m = re.match(tp.procexecfmt, t.name) 3475 if(m): 2774 if(m): 3476 parts, msg = !! 2775 proclist = dict() 3477 m = re.match( !! 2776 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 = 2777 val = ps.split() 3490 if no !! 2778 if not val: 3491 2779 continue 3492 name 2780 name = val[0].replace('--', '-') 3493 procl 2781 proclist[name] = int(val[1]) 3494 if parts == 1 !! 2782 data.pstl[t.time] = proclist 3495 data. << 3496 elif parts == << 3497 data. << 3498 tp.mu << 3499 continue 2783 continue 3500 # find the end of resume 2784 # find the end of resume 3501 if(t.endMarker()): 2785 if(t.endMarker()): 3502 if data.tKernRes == 0 !! 2786 data.handleEndMarker(t.time) 3503 data.tKernRes << 3504 data.handleEndMarker( << 3505 if(not sysvals.usetra 2787 if(not sysvals.usetracemarkers): 3506 # no trace ma 2788 # no trace markers? then quit and be sure to finish recording 3507 # the event w 2789 # the event we used to trigger resume end 3508 if('thaw_proc 2790 if('thaw_processes' in testrun.ttemp and len(testrun.ttemp['thaw_processes']) > 0): 3509 # if 2791 # if an entry exists, assume this is its end 3510 testr 2792 testrun.ttemp['thaw_processes'][-1]['end'] = t.time 3511 limbo = True !! 2793 break 3512 continue 2794 continue 3513 # trace event processing 2795 # trace event processing 3514 if(t.fevent): 2796 if(t.fevent): 3515 if(t.type == 'suspend 2797 if(t.type == 'suspend_resume'): 3516 # suspend_res 2798 # suspend_resume trace events have two types, begin and end 3517 if(re.match(r !! 2799 if(re.match('(?P<name>.*) begin$', t.name)): 3518 isbeg 2800 isbegin = True 3519 elif(re.match !! 2801 elif(re.match('(?P<name>.*) end$', t.name)): 3520 isbeg 2802 isbegin = False 3521 else: 2803 else: 3522 conti 2804 continue 3523 if '[' in t.n !! 2805 m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name) 3524 m = r !! 2806 if(m): >> 2807 val = m.group('val') >> 2808 if val == '0': >> 2809 name = m.group('name') >> 2810 else: >> 2811 name = m.group('name')+'['+val+']' 3525 else: 2812 else: 3526 m = r !! 2813 m = re.match('(?P<name>.*) .*', t.name) 3527 name = m.grou !! 2814 name = m.group('name') 3528 # ignore thes 2815 # ignore these events 3529 if(name.split 2816 if(name.split('[')[0] in tracewatch): 3530 conti 2817 continue 3531 # -- phase ch 2818 # -- phase changes -- 3532 # start of ke 2819 # start of kernel suspend 3533 if(re.match(r !! 2820 if(re.match('suspend_enter\[.*', t.name)): 3534 if(is !! 2821 if(isbegin): 3535 2822 data.tKernSus = t.time 3536 conti 2823 continue 3537 # suspend_pre 2824 # suspend_prepare start 3538 elif(re.match !! 2825 elif(re.match('dpm_prepare\[.*', t.name)): 3539 if is 2826 if isbegin and data.first_suspend_prepare: 3540 2827 data.first_suspend_prepare = False 3541 2828 if data.tKernSus == 0: 3542 2829 data.tKernSus = t.time 3543 2830 continue 3544 phase 2831 phase = data.setPhase('suspend_prepare', t.time, isbegin) 3545 conti 2832 continue 3546 # suspend sta 2833 # suspend start 3547 elif(re.match !! 2834 elif(re.match('dpm_suspend\[.*', t.name)): 3548 phase 2835 phase = data.setPhase('suspend', t.time, isbegin) 3549 conti 2836 continue 3550 # suspend_lat 2837 # suspend_late start 3551 elif(re.match !! 2838 elif(re.match('dpm_suspend_late\[.*', t.name)): 3552 phase 2839 phase = data.setPhase('suspend_late', t.time, isbegin) 3553 conti 2840 continue 3554 # suspend_noi 2841 # suspend_noirq start 3555 elif(re.match !! 2842 elif(re.match('dpm_suspend_noirq\[.*', t.name)): 3556 phase 2843 phase = data.setPhase('suspend_noirq', t.time, isbegin) 3557 conti 2844 continue 3558 # suspend_mac 2845 # suspend_machine/resume_machine 3559 elif(re.match !! 2846 elif(re.match('machine_suspend\[.*', t.name)): 3560 lp = << 3561 if(is 2847 if(isbegin): 3562 !! 2848 lp = data.lastPhase() 3563 << 3564 << 3565 << 3566 << 3567 << 3568 << 3569 << 3570 << 3571 << 3572 << 3573 << 3574 << 3575 2849 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True) 3576 2850 data.setPhase(phase, t.time, False) 3577 2851 if data.tSuspended == 0: 3578 2852 data.tSuspended = t.time 3579 else: 2853 else: 3580 << 3581 << 3582 << 3583 2854 phase = data.setPhase('resume_machine', t.time, True) 3584 2855 if(sysvals.suspendmode in ['mem', 'disk']): 3585 2856 susp = phase.replace('resume', 'suspend') 3586 2857 if susp in data.dmesg: 3587 2858 data.dmesg[susp]['end'] = t.time 3588 2859 data.tSuspended = t.time 3589 2860 data.tResumed = t.time 3590 conti 2861 continue 3591 # resume_noir 2862 # resume_noirq start 3592 elif(re.match !! 2863 elif(re.match('dpm_resume_noirq\[.*', t.name)): 3593 phase 2864 phase = data.setPhase('resume_noirq', t.time, isbegin) 3594 conti 2865 continue 3595 # resume_earl 2866 # resume_early start 3596 elif(re.match !! 2867 elif(re.match('dpm_resume_early\[.*', t.name)): 3597 phase 2868 phase = data.setPhase('resume_early', t.time, isbegin) 3598 conti 2869 continue 3599 # resume star 2870 # resume start 3600 elif(re.match !! 2871 elif(re.match('dpm_resume\[.*', t.name)): 3601 phase 2872 phase = data.setPhase('resume', t.time, isbegin) 3602 conti 2873 continue 3603 # resume comp 2874 # resume complete start 3604 elif(re.match !! 2875 elif(re.match('dpm_complete\[.*', t.name)): 3605 phase 2876 phase = data.setPhase('resume_complete', t.time, isbegin) 3606 conti 2877 continue 3607 # skip trace 2878 # skip trace events inside devices calls 3608 if(not data.i 2879 if(not data.isTraceEventOutsideDeviceCalls(pid, t.time)): 3609 conti 2880 continue 3610 # global even 2881 # global events (outside device calls) are graphed 3611 if(name not i 2882 if(name not in testrun.ttemp): 3612 testr 2883 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): 2884 if(isbegin): 3627 # cre 2885 # create a new list entry 3628 testr 2886 testrun.ttemp[name].append(\ 3629 2887 {'begin': t.time, 'end': t.time, 'pid': pid}) 3630 else: 2888 else: 3631 if(le 2889 if(len(testrun.ttemp[name]) > 0): 3632 2890 # if an entry exists, assume this is its end 3633 2891 testrun.ttemp[name][-1]['end'] = t.time 3634 # device callback sta 2892 # device callback start 3635 elif(t.type == 'devic 2893 elif(t.type == 'device_pm_callback_start'): 3636 if phase not 2894 if phase not in data.dmesg: 3637 conti 2895 continue 3638 m = re.match( !! 2896 m = re.match('(?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*',\ 3639 t.nam 2897 t.name); 3640 if(not m): 2898 if(not m): 3641 conti 2899 continue 3642 drv = m.group 2900 drv = m.group('drv') 3643 n = m.group(' 2901 n = m.group('d') 3644 p = m.group(' 2902 p = m.group('p') 3645 if(n and p): 2903 if(n and p): 3646 data. 2904 data.newAction(phase, n, pid, p, t.time, -1, drv) 3647 if pi 2905 if pid not in data.devpids: 3648 2906 data.devpids.append(pid) 3649 # device callback fin 2907 # device callback finish 3650 elif(t.type == 'devic 2908 elif(t.type == 'device_pm_callback_end'): 3651 if phase not 2909 if phase not in data.dmesg: 3652 conti 2910 continue 3653 m = re.match( !! 2911 m = re.match('(?P<drv>.*) (?P<d>.*), err.*', t.name); 3654 if(not m): 2912 if(not m): 3655 conti 2913 continue 3656 n = m.group(' 2914 n = m.group('d') 3657 dev = data.fi !! 2915 list = data.dmesg[phase]['list'] 3658 if dev: !! 2916 if(n in list): >> 2917 dev = list[n] 3659 dev[' 2918 dev['length'] = t.time - dev['start'] 3660 dev[' 2919 dev['end'] = t.time 3661 # kprobe event processing 2920 # kprobe event processing 3662 elif(t.fkprobe): 2921 elif(t.fkprobe): 3663 kprobename = t.type 2922 kprobename = t.type 3664 kprobedata = t.name 2923 kprobedata = t.name 3665 key = (kprobename, pi 2924 key = (kprobename, pid) 3666 # displayname is gene 2925 # displayname is generated from kprobe data 3667 displayname = '' 2926 displayname = '' 3668 if(t.fcall): 2927 if(t.fcall): 3669 displayname = 2928 displayname = sysvals.kprobeDisplayName(kprobename, kprobedata) 3670 if not displa 2929 if not displayname: 3671 conti 2930 continue 3672 if(key not in 2931 if(key not in tp.ktemp): 3673 tp.kt 2932 tp.ktemp[key] = [] 3674 tp.ktemp[key] 2933 tp.ktemp[key].append({ 3675 'pid' 2934 'pid': pid, 3676 'begi 2935 'begin': t.time, 3677 'end' !! 2936 'end': t.time, 3678 'name 2937 'name': displayname, 3679 'cdat 2938 'cdata': kprobedata, 3680 'proc 2939 'proc': m_proc, 3681 }) 2940 }) 3682 # start of ke 2941 # start of kernel resume 3683 if(data.tKern !! 2942 if(phase == 'suspend_prepare' and kprobename in ksuscalls): 3684 and k << 3685 data. 2943 data.tKernSus = t.time 3686 elif(t.freturn): 2944 elif(t.freturn): 3687 if(key not in 2945 if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1: 3688 conti 2946 continue 3689 e = next((x f !! 2947 e = tp.ktemp[key][-1] 3690 if not e: !! 2948 if e['begin'] < 0.0 or t.time - e['begin'] < 0.000001: 3691 conti << 3692 if (t.time - << 3693 tp.kt 2949 tp.ktemp[key].pop() 3694 conti !! 2950 else: 3695 e['end'] = t. !! 2951 e['end'] = t.time 3696 e['rdata'] = !! 2952 e['rdata'] = kprobedata 3697 # end of kern 2953 # end of kernel resume 3698 if(phase != ' 2954 if(phase != 'suspend_prepare' and kprobename in krescalls): 3699 if ph 2955 if phase in data.dmesg: 3700 2956 data.dmesg[phase]['end'] = t.time 3701 data. 2957 data.tKernRes = t.time 3702 2958 3703 # callgraph processing 2959 # callgraph processing 3704 elif sysvals.usecallgraph: 2960 elif sysvals.usecallgraph: 3705 # create a callgraph 2961 # create a callgraph object for the data 3706 key = (m_proc, pid) 2962 key = (m_proc, pid) 3707 if(key not in testrun 2963 if(key not in testrun.ftemp): 3708 testrun.ftemp 2964 testrun.ftemp[key] = [] 3709 testrun.ftemp 2965 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3710 # when the call is fi 2966 # when the call is finished, see which device matches it 3711 cg = testrun.ftemp[ke 2967 cg = testrun.ftemp[key][-1] 3712 res = cg.addLine(t) 2968 res = cg.addLine(t) 3713 if(res != 0): 2969 if(res != 0): 3714 testrun.ftemp 2970 testrun.ftemp[key].append(FTraceCallGraph(pid, sysvals)) 3715 if(res == -1): 2971 if(res == -1): 3716 testrun.ftemp 2972 testrun.ftemp[key][-1].addLine(t) 3717 if len(testdata) < 1: !! 2973 tf.close() 3718 sysvals.vprint('WARNING: ftra << 3719 if data and not data.devicegroups: 2974 if data and not data.devicegroups: 3720 sysvals.vprint('WARNING: ftra !! 2975 sysvals.vprint('WARNING: end marker is missing') 3721 data.handleEndMarker(t.time, !! 2976 data.handleEndMarker(t.time) 3722 2977 3723 if sysvals.suspendmode == 'command': 2978 if sysvals.suspendmode == 'command': 3724 for test in testruns: 2979 for test in testruns: 3725 for p in test.data.so 2980 for p in test.data.sortedPhases(): 3726 if p == 'susp 2981 if p == 'suspend_prepare': 3727 test. 2982 test.data.dmesg[p]['start'] = test.data.start 3728 test. 2983 test.data.dmesg[p]['end'] = test.data.end 3729 else: 2984 else: 3730 test. 2985 test.data.dmesg[p]['start'] = test.data.end 3731 test. 2986 test.data.dmesg[p]['end'] = test.data.end 3732 test.data.tSuspended 2987 test.data.tSuspended = test.data.end 3733 test.data.tResumed = 2988 test.data.tResumed = test.data.end 3734 test.data.fwValid = F 2989 test.data.fwValid = False 3735 2990 3736 # dev source and procmon events can b 2991 # dev source and procmon events can be unreadable with mixed phase height 3737 if sysvals.usedevsrc or sysvals.usepr 2992 if sysvals.usedevsrc or sysvals.useprocmon: 3738 sysvals.mixedphaseheight = Fa 2993 sysvals.mixedphaseheight = False 3739 2994 3740 # expand phase boundaries so there ar 2995 # expand phase boundaries so there are no gaps 3741 for data in testdata: 2996 for data in testdata: 3742 lp = data.sortedPhases()[0] 2997 lp = data.sortedPhases()[0] 3743 for p in data.sortedPhases(): 2998 for p in data.sortedPhases(): 3744 if(p != lp and not (' 2999 if(p != lp and not ('machine' in p and 'machine' in lp)): 3745 data.dmesg[lp 3000 data.dmesg[lp]['end'] = data.dmesg[p]['start'] 3746 lp = p 3001 lp = p 3747 3002 3748 for i in range(len(testruns)): 3003 for i in range(len(testruns)): 3749 test = testruns[i] 3004 test = testruns[i] 3750 data = test.data 3005 data = test.data 3751 # find the total time range f 3006 # find the total time range for this test (begin, end) 3752 tlb, tle = data.start, data.e 3007 tlb, tle = data.start, data.end 3753 if i < len(testruns) - 1: 3008 if i < len(testruns) - 1: 3754 tle = testruns[i+1].d 3009 tle = testruns[i+1].data.start 3755 # add the process usage data 3010 # add the process usage data to the timeline 3756 if sysvals.useprocmon: 3011 if sysvals.useprocmon: 3757 data.createProcessUsa 3012 data.createProcessUsageEvents() 3758 # add the traceevent data to 3013 # add the traceevent data to the device hierarchy 3759 if(sysvals.usetraceevents): 3014 if(sysvals.usetraceevents): 3760 # add actual trace fu 3015 # add actual trace funcs 3761 for name in sorted(te !! 3016 for name in test.ttemp: 3762 for event in 3017 for event in test.ttemp[name]: 3763 if ev !! 3018 data.newActionGlobal(name, event['begin'], event['end'], event['pid']) 3764 << 3765 title << 3766 if na << 3767 << 3768 data. << 3769 # add the kprobe base 3019 # add the kprobe based virtual tracefuncs as actual devices 3770 for key in sorted(tp. !! 3020 for key in tp.ktemp: 3771 name, pid = k 3021 name, pid = key 3772 if name not i 3022 if name not in sysvals.tracefuncs: 3773 conti 3023 continue 3774 if pid not in << 3775 data. << 3776 for e in tp.k 3024 for e in tp.ktemp[key]: 3777 kb, k 3025 kb, ke = e['begin'], e['end'] 3778 if ke !! 3026 if kb == ke or tlb > kb or tle <= kb: 3779 3027 continue 3780 color 3028 color = sysvals.kprobeColor(name) 3781 data. 3029 data.newActionGlobal(e['name'], kb, ke, pid, color) 3782 # add config base kpr 3030 # add config base kprobes and dev kprobes 3783 if sysvals.usedevsrc: 3031 if sysvals.usedevsrc: 3784 for key in so !! 3032 for key in tp.ktemp: 3785 name, 3033 name, pid = key 3786 if na 3034 if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs: 3787 3035 continue 3788 for e 3036 for e in tp.ktemp[key]: 3789 3037 kb, ke = e['begin'], e['end'] 3790 !! 3038 if kb == ke or tlb > kb or tle <= kb: 3791 3039 continue 3792 3040 data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb, 3793 3041 ke, e['cdata'], e['rdata']) 3794 if sysvals.usecallgraph: 3042 if sysvals.usecallgraph: 3795 # add the callgraph d 3043 # add the callgraph data to the device hierarchy 3796 sortlist = dict() 3044 sortlist = dict() 3797 for key in sorted(tes !! 3045 for key in test.ftemp: 3798 proc, pid = k 3046 proc, pid = key 3799 for cg in tes 3047 for cg in test.ftemp[key]: 3800 if le 3048 if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0): 3801 3049 continue 3802 if(no 3050 if(not cg.postProcess()): 3803 3051 id = 'task %s' % (pid) 3804 3052 sysvals.vprint('Sanity check failed for '+\ 3805 3053 id+', ignoring this callback') 3806 3054 continue 3807 # mat 3055 # match cg data to devices 3808 devna 3056 devname = '' 3809 if sy 3057 if sysvals.suspendmode != 'command': 3810 3058 devname = cg.deviceMatch(pid, data) 3811 if no 3059 if not devname: 3812 3060 sortkey = '%f%f%d' % (cg.start, cg.end, pid) 3813 3061 sortlist[sortkey] = cg 3814 elif !! 3062 elif len(cg.list) > 1000000: 3815 3063 sysvals.vprint('WARNING: the callgraph for %s is massive (%d lines)' %\ 3816 3064 (devname, len(cg.list))) 3817 # create blocks for o 3065 # create blocks for orphan cg data 3818 for sortkey in sorted 3066 for sortkey in sorted(sortlist): 3819 cg = sortlist 3067 cg = sortlist[sortkey] 3820 name = cg.nam 3068 name = cg.name 3821 if sysvals.is 3069 if sysvals.isCallgraphFunc(name): 3822 sysva 3070 sysvals.vprint('Callgraph found for task %d: %.3fms, %s' % (cg.pid, (cg.end - cg.start)*1000, name)) 3823 cg.ne 3071 cg.newActionFromFunction(data) 3824 if sysvals.suspendmode == 'command': 3072 if sysvals.suspendmode == 'command': 3825 return (testdata, '') 3073 return (testdata, '') 3826 3074 3827 # fill in any missing phases 3075 # fill in any missing phases 3828 error = [] 3076 error = [] 3829 for data in testdata: 3077 for data in testdata: 3830 tn = '' if len(testdata) == 1 3078 tn = '' if len(testdata) == 1 else ('%d' % (data.testnumber + 1)) 3831 terr = '' 3079 terr = '' 3832 phasedef = data.phasedef 3080 phasedef = data.phasedef 3833 lp = 'suspend_prepare' 3081 lp = 'suspend_prepare' 3834 for p in sorted(phasedef, key 3082 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']): 3835 if p not in data.dmes 3083 if p not in data.dmesg: 3836 if not terr: 3084 if not terr: 3837 ph = !! 3085 pprint('TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp)) 3838 if p !! 3086 terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp) 3839 << 3840 << 3841 << 3842 << 3843 else: << 3844 << 3845 pprin << 3846 error 3087 error.append(terr) 3847 if da 3088 if data.tSuspended == 0: 3848 3089 data.tSuspended = data.dmesg[lp]['end'] 3849 if da 3090 if data.tResumed == 0: 3850 3091 data.tResumed = data.dmesg[lp]['end'] 3851 data. 3092 data.fwValid = False 3852 sysvals.vprin 3093 sysvals.vprint('WARNING: phase "%s" is missing!' % p) 3853 lp = p 3094 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 3095 if not terr and data.enterfail: 3859 pprint('test%s FAILED 3096 pprint('test%s FAILED: enter %s failed with %s' % (tn, sysvals.suspendmode, data.enterfail)) 3860 terr = 'test%s failed 3097 terr = 'test%s failed to enter %s mode' % (tn, sysvals.suspendmode) 3861 error.append(terr) 3098 error.append(terr) 3862 if data.tSuspended == 0: 3099 if data.tSuspended == 0: 3863 data.tSuspended = dat 3100 data.tSuspended = data.tKernRes 3864 if data.tResumed == 0: 3101 if data.tResumed == 0: 3865 data.tResumed = data. 3102 data.tResumed = data.tSuspended 3866 3103 3867 if(len(sysvals.devicefilter) 3104 if(len(sysvals.devicefilter) > 0): 3868 data.deviceFilter(sys 3105 data.deviceFilter(sysvals.devicefilter) 3869 data.fixupInitcallsThatDidntR 3106 data.fixupInitcallsThatDidntReturn() 3870 if sysvals.usedevsrc: 3107 if sysvals.usedevsrc: 3871 data.optimizeDevSrc() 3108 data.optimizeDevSrc() 3872 3109 3873 # x2: merge any overlapping devices b 3110 # x2: merge any overlapping devices between test runs 3874 if sysvals.usedevsrc and len(testdata 3111 if sysvals.usedevsrc and len(testdata) > 1: 3875 tc = len(testdata) 3112 tc = len(testdata) 3876 for i in range(tc - 1): 3113 for i in range(tc - 1): 3877 devlist = testdata[i] 3114 devlist = testdata[i].overflowDevices() 3878 for j in range(i + 1, 3115 for j in range(i + 1, tc): 3879 testdata[j].m 3116 testdata[j].mergeOverlapDevices(devlist) 3880 testdata[0].stitchTouchingThr 3117 testdata[0].stitchTouchingThreads(testdata[1:]) 3881 return (testdata, ', '.join(error)) 3118 return (testdata, ', '.join(error)) 3882 3119 3883 # Function: loadKernelLog 3120 # Function: loadKernelLog 3884 # Description: 3121 # Description: >> 3122 # [deprecated for kernel 3.15.0 or newer] 3885 # load the dmesg file into memory and 3123 # load the dmesg file into memory and fix up any ordering issues >> 3124 # The dmesg filename is taken from sysvals 3886 # Output: 3125 # Output: 3887 # An array of empty Data objects with 3126 # An array of empty Data objects with only their dmesgtext attributes set 3888 def loadKernelLog(): 3127 def loadKernelLog(): 3889 sysvals.vprint('Analyzing the dmesg d 3128 sysvals.vprint('Analyzing the dmesg data (%s)...' % \ 3890 os.path.basename(sysvals.dmes 3129 os.path.basename(sysvals.dmesgfile)) 3891 if(os.path.exists(sysvals.dmesgfile) 3130 if(os.path.exists(sysvals.dmesgfile) == False): 3892 doError('%s does not exist' % 3131 doError('%s does not exist' % sysvals.dmesgfile) 3893 3132 3894 # there can be multiple test runs in 3133 # there can be multiple test runs in a single file 3895 tp = TestProps() 3134 tp = TestProps() 3896 tp.stamp = datetime.now().strftime('# 3135 tp.stamp = datetime.now().strftime('# suspend-%m%d%y-%H%M%S localhost mem unknown') 3897 testruns = [] 3136 testruns = [] 3898 data = 0 3137 data = 0 3899 lf = sysvals.openlog(sysvals.dmesgfil 3138 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 3900 for line in lf: 3139 for line in lf: 3901 line = line.replace('\r\n', ' 3140 line = line.replace('\r\n', '') 3902 idx = line.find('[') 3141 idx = line.find('[') 3903 if idx > 1: 3142 if idx > 1: 3904 line = line[idx:] 3143 line = line[idx:] 3905 if tp.stampInfo(line, sysvals !! 3144 # grab the stamp and sysinfo >> 3145 if re.match(tp.stampfmt, line): >> 3146 tp.stamp = line 3906 continue 3147 continue 3907 m = re.match(r'[ \t]*(\[ *)(? !! 3148 elif re.match(tp.sysinfofmt, line): >> 3149 tp.sysinfo = line >> 3150 continue >> 3151 elif re.match(tp.cmdlinefmt, line): >> 3152 tp.cmdline = line >> 3153 continue >> 3154 elif re.match(tp.batteryfmt, line): >> 3155 tp.battery.append(line) >> 3156 continue >> 3157 elif re.match(tp.testerrfmt, line): >> 3158 tp.testerror.append(line) >> 3159 continue >> 3160 m = re.match(tp.firmwarefmt, line) >> 3161 if(m): >> 3162 tp.fwdata.append((int(m.group('s')), int(m.group('r')))) >> 3163 continue >> 3164 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 3908 if(not m): 3165 if(not m): 3909 continue 3166 continue 3910 msg = m.group("msg") 3167 msg = m.group("msg") 3911 if re.match(r'PM: Syncing fil !! 3168 if(re.match('PM: Syncing filesystems.*', msg)): 3912 re.match(r'PM: suspen << 3913 if(data): 3169 if(data): 3914 testruns.appe 3170 testruns.append(data) 3915 data = Data(len(testr 3171 data = Data(len(testruns)) 3916 tp.parseStamp(data, s 3172 tp.parseStamp(data, sysvals) 3917 if(not data): 3173 if(not data): 3918 continue 3174 continue 3919 m = re.match(r'.* *(?P<k>[0-9 !! 3175 m = re.match('.* *(?P<k>[0-9]\.[0-9]{2}\.[0-9]-.*) .*', msg) 3920 if(m): 3176 if(m): 3921 sysvals.stamp['kernel 3177 sysvals.stamp['kernel'] = m.group('k') 3922 m = re.match(r'PM: Preparing !! 3178 m = re.match('PM: Preparing system for (?P<m>.*) sleep', msg) 3923 if not m: !! 3179 if(m): 3924 m = re.match(r'PM: Pr << 3925 if m: << 3926 sysvals.stamp['mode'] 3180 sysvals.stamp['mode'] = sysvals.suspendmode = m.group('m') 3927 data.dmesgtext.append(line) 3181 data.dmesgtext.append(line) 3928 lf.close() 3182 lf.close() 3929 3183 3930 if sysvals.suspendmode == 's2idle': << 3931 sysvals.suspendmode = 'freeze << 3932 elif sysvals.suspendmode == 'deep': << 3933 sysvals.suspendmode = 'mem' << 3934 if data: 3184 if data: 3935 testruns.append(data) 3185 testruns.append(data) 3936 if len(testruns) < 1: 3186 if len(testruns) < 1: 3937 doError('dmesg log has no sus !! 3187 pprint('ERROR: dmesg log has no suspend/resume data: %s' \ 3938 % sysvals.dmesgfile) 3188 % sysvals.dmesgfile) 3939 3189 3940 # fix lines with same timestamp/funct 3190 # fix lines with same timestamp/function with the call and return swapped 3941 for data in testruns: 3191 for data in testruns: 3942 last = '' 3192 last = '' 3943 for line in data.dmesgtext: 3193 for line in data.dmesgtext: 3944 ct, cf, n, p = data.i !! 3194 mc = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) calling '+\ 3945 rt, rf, l = data.init !! 3195 '(?P<f>.*)\+ @ .*, parent: .*', line) 3946 if ct and rt and ct = !! 3196 mr = re.match('.*(\[ *)(?P<t>[0-9\.]*)(\]) call '+\ >> 3197 '(?P<f>.*)\+ returned .* after (?P<dt>.*) usecs', last) >> 3198 if(mc and mr and (mc.group('t') == mr.group('t')) and >> 3199 (mc.group('f') == mr.group('f'))): 3947 i = data.dmes 3200 i = data.dmesgtext.index(last) 3948 j = data.dmes 3201 j = data.dmesgtext.index(line) 3949 data.dmesgtex 3202 data.dmesgtext[i] = line 3950 data.dmesgtex 3203 data.dmesgtext[j] = last 3951 last = line 3204 last = line 3952 return testruns 3205 return testruns 3953 3206 3954 # Function: parseKernelLog 3207 # Function: parseKernelLog 3955 # Description: 3208 # Description: >> 3209 # [deprecated for kernel 3.15.0 or newer] 3956 # Analyse a dmesg log output file gene 3210 # Analyse a dmesg log output file generated from this app during 3957 # the execution phase. Create a set of 3211 # the execution phase. Create a set of device structures in memory 3958 # for subsequent formatting in the htm 3212 # for subsequent formatting in the html output file 3959 # This call is only for legacy support 3213 # This call is only for legacy support on kernels where the ftrace 3960 # data lacks the suspend_resume or dev 3214 # data lacks the suspend_resume or device_pm_callbacks trace events. 3961 # Arguments: 3215 # Arguments: 3962 # data: an empty Data object (with dme 3216 # data: an empty Data object (with dmesgtext) obtained from loadKernelLog 3963 # Output: 3217 # Output: 3964 # The filled Data object 3218 # The filled Data object 3965 def parseKernelLog(data): 3219 def parseKernelLog(data): 3966 phase = 'suspend_runtime' 3220 phase = 'suspend_runtime' 3967 3221 3968 if(data.fwValid): 3222 if(data.fwValid): 3969 sysvals.vprint('Firmware Susp 3223 sysvals.vprint('Firmware Suspend = %u ns, Firmware Resume = %u ns' % \ 3970 (data.fwSuspend, data 3224 (data.fwSuspend, data.fwResume)) 3971 3225 3972 # dmesg phase match table 3226 # dmesg phase match table 3973 dm = { 3227 dm = { 3974 'suspend_prepare': ['PM: Sync !! 3228 'suspend_prepare': ['PM: Syncing filesystems.*'], 3975 'suspend': ['PM: Ente !! 3229 'suspend': ['PM: Entering [a-z]* sleep.*', 'Suspending console.*'], 3976 'PM: Susp !! 3230 'suspend_late': ['PM: suspend of devices complete after.*'], 3977 'suspend_late': ['PM: susp !! 3231 'suspend_noirq': ['PM: late suspend of devices complete after.*'], 3978 !! 3232 'suspend_machine': ['PM: noirq suspend of devices complete after.*'], 3979 'suspend_noirq': ['PM: late !! 3233 'resume_machine': ['ACPI: Low-level resume complete.*'], 3980 !! 3234 'resume_noirq': ['ACPI: Waking up from system sleep state.*'], 3981 'suspend_machine': ['PM: susp !! 3235 'resume_early': ['PM: noirq resume of devices complete after.*'], 3982 !! 3236 'resume': ['PM: early resume of devices complete after.*'], 3983 !! 3237 'resume_complete': ['PM: resume of devices complete after.*'], 3984 'resume_machine': ['[PM: ]*T !! 3238 '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 } 3239 } >> 3240 if(sysvals.suspendmode == 'standby'): >> 3241 dm['resume_machine'] = ['PM: Restoring platform NVS memory'] >> 3242 elif(sysvals.suspendmode == 'disk'): >> 3243 dm['suspend_late'] = ['PM: freeze of devices complete after.*'] >> 3244 dm['suspend_noirq'] = ['PM: late freeze of devices complete after.*'] >> 3245 dm['suspend_machine'] = ['PM: noirq freeze of devices complete after.*'] >> 3246 dm['resume_machine'] = ['PM: Restoring platform NVS memory'] >> 3247 dm['resume_early'] = ['PM: noirq restore of devices complete after.*'] >> 3248 dm['resume'] = ['PM: early restore of devices complete after.*'] >> 3249 dm['resume_complete'] = ['PM: restore of devices complete after.*'] >> 3250 elif(sysvals.suspendmode == 'freeze'): >> 3251 dm['resume_machine'] = ['ACPI: resume from mwait'] 3998 3252 3999 # action table (expected events that 3253 # action table (expected events that occur and show up in dmesg) 4000 at = { 3254 at = { 4001 'sync_filesystems': { 3255 'sync_filesystems': { 4002 'smsg': '.*[Ff]+ilesy !! 3256 'smsg': 'PM: Syncing filesystems.*', 4003 'emsg': 'PM: Preparin !! 3257 'emsg': 'PM: Preparing system for mem sleep.*' }, 4004 'freeze_user_processes': { 3258 'freeze_user_processes': { 4005 'smsg': 'Freezing use !! 3259 'smsg': 'Freezing user space processes .*', 4006 'emsg': 'Freezing rem 3260 'emsg': 'Freezing remaining freezable tasks.*' }, 4007 'freeze_tasks': { 3261 'freeze_tasks': { 4008 'smsg': 'Freezing rem 3262 'smsg': 'Freezing remaining freezable tasks.*', 4009 'emsg': 'PM: Suspendi !! 3263 'emsg': 'PM: Entering (?P<mode>[a-z,A-Z]*) sleep.*' }, 4010 'ACPI prepare': { 3264 'ACPI prepare': { 4011 'smsg': 'ACPI: Prepar 3265 'smsg': 'ACPI: Preparing to enter system sleep state.*', 4012 'emsg': 'PM: Saving p 3266 'emsg': 'PM: Saving platform NVS memory.*' }, 4013 'PM vns': { 3267 'PM vns': { 4014 'smsg': 'PM: Saving p 3268 'smsg': 'PM: Saving platform NVS memory.*', 4015 'emsg': 'Disabling no 3269 'emsg': 'Disabling non-boot CPUs .*' }, 4016 } 3270 } 4017 3271 4018 t0 = -1.0 3272 t0 = -1.0 4019 cpu_start = -1.0 3273 cpu_start = -1.0 4020 prevktime = -1.0 3274 prevktime = -1.0 4021 actions = dict() 3275 actions = dict() 4022 for line in data.dmesgtext: 3276 for line in data.dmesgtext: 4023 # parse each dmesg line into 3277 # parse each dmesg line into the time and message 4024 m = re.match(r'[ \t]*(\[ *)(? !! 3278 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 4025 if(m): 3279 if(m): 4026 val = m.group('ktime' 3280 val = m.group('ktime') 4027 try: 3281 try: 4028 ktime = float 3282 ktime = float(val) 4029 except: 3283 except: 4030 continue 3284 continue 4031 msg = m.group('msg') 3285 msg = m.group('msg') 4032 # initialize data sta 3286 # initialize data start to first line time 4033 if t0 < 0: 3287 if t0 < 0: 4034 data.setStart 3288 data.setStart(ktime) 4035 t0 = ktime 3289 t0 = ktime 4036 else: 3290 else: 4037 continue 3291 continue 4038 3292 4039 # check for a phase change li 3293 # check for a phase change line 4040 phasechange = False 3294 phasechange = False 4041 for p in dm: 3295 for p in dm: 4042 for s in dm[p]: 3296 for s in dm[p]: 4043 if(re.match(s 3297 if(re.match(s, msg)): 4044 phase 3298 phasechange, phase = True, p 4045 dm[p] << 4046 break 3299 break 4047 3300 4048 # hack for determining resume 3301 # hack for determining resume_machine end for freeze 4049 if(not sysvals.usetraceevents 3302 if(not sysvals.usetraceevents and sysvals.suspendmode == 'freeze' \ 4050 and phase == 'resume_ 3303 and phase == 'resume_machine' and \ 4051 data.initcall_debug_c !! 3304 re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4052 data.setPhase(phase, 3305 data.setPhase(phase, ktime, False) 4053 phase = 'resume_noirq 3306 phase = 'resume_noirq' 4054 data.setPhase(phase, 3307 data.setPhase(phase, ktime, True) 4055 3308 4056 if phasechange: 3309 if phasechange: 4057 if phase == 'suspend_ 3310 if phase == 'suspend_prepare': 4058 data.setPhase 3311 data.setPhase(phase, ktime, True) 4059 data.setStart 3312 data.setStart(ktime) 4060 data.tKernSus 3313 data.tKernSus = ktime 4061 elif phase == 'suspen 3314 elif phase == 'suspend': 4062 lp = data.las 3315 lp = data.lastPhase() 4063 if lp: 3316 if lp: 4064 data. 3317 data.setPhase(lp, ktime, False) 4065 data.setPhase 3318 data.setPhase(phase, ktime, True) 4066 elif phase == 'suspen 3319 elif phase == 'suspend_late': 4067 lp = data.las 3320 lp = data.lastPhase() 4068 if lp: 3321 if lp: 4069 data. 3322 data.setPhase(lp, ktime, False) 4070 data.setPhase 3323 data.setPhase(phase, ktime, True) 4071 elif phase == 'suspen 3324 elif phase == 'suspend_noirq': 4072 lp = data.las 3325 lp = data.lastPhase() 4073 if lp: 3326 if lp: 4074 data. 3327 data.setPhase(lp, ktime, False) 4075 data.setPhase 3328 data.setPhase(phase, ktime, True) 4076 elif phase == 'suspen 3329 elif phase == 'suspend_machine': 4077 lp = data.las 3330 lp = data.lastPhase() 4078 if lp: 3331 if lp: 4079 data. 3332 data.setPhase(lp, ktime, False) 4080 data.setPhase 3333 data.setPhase(phase, ktime, True) 4081 elif phase == 'resume 3334 elif phase == 'resume_machine': 4082 lp = data.las 3335 lp = data.lastPhase() 4083 if(sysvals.su 3336 if(sysvals.suspendmode in ['freeze', 'standby']): 4084 data. 3337 data.tSuspended = prevktime 4085 if lp 3338 if lp: 4086 3339 data.setPhase(lp, prevktime, False) 4087 else: 3340 else: 4088 data. 3341 data.tSuspended = ktime 4089 if lp 3342 if lp: 4090 3343 data.setPhase(lp, prevktime, False) 4091 data.tResumed 3344 data.tResumed = ktime 4092 data.setPhase 3345 data.setPhase(phase, ktime, True) 4093 elif phase == 'resume 3346 elif phase == 'resume_noirq': 4094 lp = data.las 3347 lp = data.lastPhase() 4095 if lp: 3348 if lp: 4096 data. 3349 data.setPhase(lp, ktime, False) 4097 data.setPhase 3350 data.setPhase(phase, ktime, True) 4098 elif phase == 'resume 3351 elif phase == 'resume_early': 4099 lp = data.las 3352 lp = data.lastPhase() 4100 if lp: 3353 if lp: 4101 data. 3354 data.setPhase(lp, ktime, False) 4102 data.setPhase 3355 data.setPhase(phase, ktime, True) 4103 elif phase == 'resume 3356 elif phase == 'resume': 4104 lp = data.las 3357 lp = data.lastPhase() 4105 if lp: 3358 if lp: 4106 data. 3359 data.setPhase(lp, ktime, False) 4107 data.setPhase 3360 data.setPhase(phase, ktime, True) 4108 elif phase == 'resume 3361 elif phase == 'resume_complete': 4109 lp = data.las 3362 lp = data.lastPhase() 4110 if lp: 3363 if lp: 4111 data. 3364 data.setPhase(lp, ktime, False) 4112 data.setPhase 3365 data.setPhase(phase, ktime, True) 4113 elif phase == 'post_r 3366 elif phase == 'post_resume': 4114 lp = data.las 3367 lp = data.lastPhase() 4115 if lp: 3368 if lp: 4116 data. 3369 data.setPhase(lp, ktime, False) 4117 data.setEnd(k 3370 data.setEnd(ktime) 4118 data.tKernRes 3371 data.tKernRes = ktime 4119 break 3372 break 4120 3373 4121 # -- device callbacks -- 3374 # -- device callbacks -- 4122 if(phase in data.sortedPhases 3375 if(phase in data.sortedPhases()): 4123 # device init call 3376 # device init call 4124 t, f, n, p = data.ini !! 3377 if(re.match('calling (?P<f>.*)\+ @ .*, parent: .*', msg)): 4125 if t and f and n and !! 3378 sm = re.match('calling (?P<f>.*)\+ @ '+\ 4126 data.newActio !! 3379 '(?P<n>.*), parent: (?P<p>.*)', msg); 4127 else: !! 3380 f = sm.group('f') 4128 # device init !! 3381 n = sm.group('n') 4129 t, f, l = dat !! 3382 p = sm.group('p') 4130 if t and f an !! 3383 if(f and n and p): 4131 list !! 3384 data.newAction(phase, f, int(n), p, ktime, -1, '') 4132 if(f !! 3385 # device init return 4133 !! 3386 elif(re.match('call (?P<f>.*)\+ returned .* after '+\ 4134 !! 3387 '(?P<t>.*) usecs', msg)): 4135 !! 3388 sm = re.match('call (?P<f>.*)\+ returned .* after '+\ >> 3389 '(?P<t>.*) usecs(?P<a>.*)', msg); >> 3390 f = sm.group('f') >> 3391 t = sm.group('t') >> 3392 list = data.dmesg[phase]['list'] >> 3393 if(f in list): >> 3394 dev = list[f] >> 3395 dev['length'] = int(t) >> 3396 dev['end'] = ktime 4136 3397 4137 # if trace events are not ava 3398 # if trace events are not available, these are better than nothing 4138 if(not sysvals.usetraceevents 3399 if(not sysvals.usetraceevents): 4139 # look for known acti 3400 # look for known actions 4140 for a in sorted(at): !! 3401 for a in at: 4141 if(re.match(a 3402 if(re.match(at[a]['smsg'], msg)): 4142 if(a 3403 if(a not in actions): 4143 !! 3404 actions[a] = [] >> 3405 actions[a].append({'begin': ktime, 'end': ktime}) 4144 if(re.match(a 3406 if(re.match(at[a]['emsg'], msg)): 4145 if(a !! 3407 if(a in actions): 4146 3408 actions[a][-1]['end'] = ktime 4147 # now look for CPU on 3409 # now look for CPU on/off events 4148 if(re.match(r'Disabli !! 3410 if(re.match('Disabling non-boot CPUs .*', msg)): 4149 # start of fi 3411 # start of first cpu suspend 4150 cpu_start = k 3412 cpu_start = ktime 4151 elif(re.match(r'Enabl !! 3413 elif(re.match('Enabling non-boot CPUs .*', msg)): 4152 # start of fi 3414 # start of first cpu resume 4153 cpu_start = k 3415 cpu_start = ktime 4154 elif(re.match(r'smpbo !! 3416 elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)): 4155 or re.match(r << 4156 # end of a cp 3417 # end of a cpu suspend, start of the next 4157 m = re.match( !! 3418 m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) 4158 if(not m): << 4159 m = r << 4160 cpu = 'CPU'+m 3419 cpu = 'CPU'+m.group('cpu') 4161 if(cpu not in 3420 if(cpu not in actions): 4162 actio 3421 actions[cpu] = [] 4163 actions[cpu]. 3422 actions[cpu].append({'begin': cpu_start, 'end': ktime}) 4164 cpu_start = k 3423 cpu_start = ktime 4165 elif(re.match(r'CPU(? !! 3424 elif(re.match('CPU(?P<cpu>[0-9]*) is up', msg)): 4166 # end of a cp 3425 # end of a cpu resume, start of the next 4167 m = re.match( !! 3426 m = re.match('CPU(?P<cpu>[0-9]*) is up', msg) 4168 cpu = 'CPU'+m 3427 cpu = 'CPU'+m.group('cpu') 4169 if(cpu not in 3428 if(cpu not in actions): 4170 actio 3429 actions[cpu] = [] 4171 actions[cpu]. 3430 actions[cpu].append({'begin': cpu_start, 'end': ktime}) 4172 cpu_start = k 3431 cpu_start = ktime 4173 prevktime = ktime 3432 prevktime = ktime 4174 data.initDevicegroups() 3433 data.initDevicegroups() 4175 3434 4176 # fill in any missing phases 3435 # fill in any missing phases 4177 phasedef = data.phasedef 3436 phasedef = data.phasedef 4178 terr, lp = '', 'suspend_prepare' 3437 terr, lp = '', 'suspend_prepare' 4179 if lp not in data.dmesg: << 4180 doError('dmesg log format has << 4181 for p in sorted(phasedef, key=lambda 3438 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']): 4182 if p not in data.dmesg: 3439 if p not in data.dmesg: 4183 if not terr: 3440 if not terr: 4184 pprint('TEST 3441 pprint('TEST FAILED: %s failed in %s phase' % (sysvals.suspendmode, lp)) 4185 terr = '%s fa 3442 terr = '%s failed in %s phase' % (sysvals.suspendmode, lp) 4186 if data.tSusp 3443 if data.tSuspended == 0: 4187 data. 3444 data.tSuspended = data.dmesg[lp]['end'] 4188 if data.tResu 3445 if data.tResumed == 0: 4189 data. 3446 data.tResumed = data.dmesg[lp]['end'] 4190 sysvals.vprint('WARNI 3447 sysvals.vprint('WARNING: phase "%s" is missing!' % p) 4191 lp = p 3448 lp = p 4192 lp = data.sortedPhases()[0] 3449 lp = data.sortedPhases()[0] 4193 for p in data.sortedPhases(): 3450 for p in data.sortedPhases(): 4194 if(p != lp and not ('machine' 3451 if(p != lp and not ('machine' in p and 'machine' in lp)): 4195 data.dmesg[lp]['end'] 3452 data.dmesg[lp]['end'] = data.dmesg[p]['start'] 4196 lp = p 3453 lp = p 4197 if data.tSuspended == 0: 3454 if data.tSuspended == 0: 4198 data.tSuspended = data.tKernR 3455 data.tSuspended = data.tKernRes 4199 if data.tResumed == 0: 3456 if data.tResumed == 0: 4200 data.tResumed = data.tSuspend 3457 data.tResumed = data.tSuspended 4201 3458 4202 # fill in any actions we've found 3459 # fill in any actions we've found 4203 for name in sorted(actions): !! 3460 for name in actions: 4204 for event in actions[name]: 3461 for event in actions[name]: 4205 data.newActionGlobal( 3462 data.newActionGlobal(name, event['begin'], event['end']) 4206 3463 4207 if(len(sysvals.devicefilter) > 0): 3464 if(len(sysvals.devicefilter) > 0): 4208 data.deviceFilter(sysvals.dev 3465 data.deviceFilter(sysvals.devicefilter) 4209 data.fixupInitcallsThatDidntReturn() 3466 data.fixupInitcallsThatDidntReturn() 4210 return True 3467 return True 4211 3468 4212 def callgraphHTML(sv, hf, num, cg, title, col 3469 def callgraphHTML(sv, hf, num, cg, title, color, devid): 4213 html_func_top = '<article id="{0}" cl 3470 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 3471 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' 3472 html_func_end = '</article>\n' 4216 html_func_leaf = '<article>{0} {1}</a 3473 html_func_leaf = '<article>{0} {1}</article>\n' 4217 3474 4218 cgid = devid 3475 cgid = devid 4219 if cg.id: 3476 if cg.id: 4220 cgid += cg.id 3477 cgid += cg.id 4221 cglen = (cg.end - cg.start) * 1000 3478 cglen = (cg.end - cg.start) * 1000 4222 if cglen < sv.mincglen: 3479 if cglen < sv.mincglen: 4223 return num 3480 return num 4224 3481 4225 fmt = '<r>(%.3f ms @ '+sv.timeformat+' 3482 fmt = '<r>(%.3f ms @ '+sv.timeformat+' to '+sv.timeformat+')</r>' 4226 flen = fmt % (cglen, cg.start, cg.end 3483 flen = fmt % (cglen, cg.start, cg.end) 4227 hf.write(html_func_top.format(cgid, c 3484 hf.write(html_func_top.format(cgid, color, num, title, flen)) 4228 num += 1 3485 num += 1 4229 for line in cg.list: 3486 for line in cg.list: 4230 if(line.length < 0.000000001) 3487 if(line.length < 0.000000001): 4231 flen = '' 3488 flen = '' 4232 else: 3489 else: 4233 fmt = '<n>(%.3f ms @ ' 3490 fmt = '<n>(%.3f ms @ '+sv.timeformat+')</n>' 4234 flen = fmt % (line.le 3491 flen = fmt % (line.length*1000, line.time) 4235 if line.isLeaf(): 3492 if line.isLeaf(): 4236 if line.length * 1000 << 4237 continue << 4238 hf.write(html_func_le 3493 hf.write(html_func_leaf.format(line.name, flen)) 4239 elif line.freturn: 3494 elif line.freturn: 4240 hf.write(html_func_en 3495 hf.write(html_func_end) 4241 else: 3496 else: 4242 hf.write(html_func_st 3497 hf.write(html_func_start.format(num, line.name, flen)) 4243 num += 1 3498 num += 1 4244 hf.write(html_func_end) 3499 hf.write(html_func_end) 4245 return num 3500 return num 4246 3501 4247 def addCallgraphs(sv, hf, data): 3502 def addCallgraphs(sv, hf, data): 4248 hf.write('<section id="callgraphs" cl 3503 hf.write('<section id="callgraphs" class="callgraph">\n') 4249 # write out the ftrace data converted 3504 # write out the ftrace data converted to html 4250 num = 0 3505 num = 0 4251 for p in data.sortedPhases(): 3506 for p in data.sortedPhases(): 4252 if sv.cgphase and p != sv.cgp 3507 if sv.cgphase and p != sv.cgphase: 4253 continue 3508 continue 4254 list = data.dmesg[p]['list'] 3509 list = data.dmesg[p]['list'] 4255 for d in data.sortedDevices(p !! 3510 for devname in data.sortedDevices(p): 4256 if len(sv.cgfilter) > !! 3511 if len(sv.cgfilter) > 0 and devname not in sv.cgfilter: 4257 continue 3512 continue 4258 dev = list[d] !! 3513 dev = list[devname] 4259 color = 'white' 3514 color = 'white' 4260 if 'color' in data.dm 3515 if 'color' in data.dmesg[p]: 4261 color = data. 3516 color = data.dmesg[p]['color'] 4262 if 'color' in dev: 3517 if 'color' in dev: 4263 color = dev[' 3518 color = dev['color'] 4264 name = d if '[' not i !! 3519 name = devname 4265 if(d in sv.devprops): !! 3520 if(devname in sv.devprops): 4266 name = sv.dev !! 3521 name = sv.devprops[devname].altName(devname) 4267 if 'drv' in dev and d << 4268 name += ' {%s << 4269 if sv.suspendmode in 3522 if sv.suspendmode in suspendmodename: 4270 name += ' '+p 3523 name += ' '+p 4271 if('ftrace' in dev): 3524 if('ftrace' in dev): 4272 cg = dev['ftr 3525 cg = dev['ftrace'] 4273 if cg.name == << 4274 name << 4275 num = callgra 3526 num = callgraphHTML(sv, hf, num, cg, 4276 name, 3527 name, color, dev['id']) 4277 if('ftraces' in dev): 3528 if('ftraces' in dev): 4278 for cg in dev 3529 for cg in dev['ftraces']: 4279 num = 3530 num = callgraphHTML(sv, hf, num, cg, 4280 3531 name+' → '+cg.name, color, dev['id']) 4281 hf.write('\n\n </section>\n') 3532 hf.write('\n\n </section>\n') 4282 3533 4283 def summaryCSS(title, center=True): !! 3534 # Function: createHTMLSummarySimple 4284 tdcenter = 'text-align:center;' if ce !! 3535 # Description: 4285 out = '<!DOCTYPE html>\n<html>\n<head !! 3536 # Create summary html file for a series of tests >> 3537 # Arguments: >> 3538 # testruns: array of Data objects from parseTraceLog >> 3539 def createHTMLSummarySimple(testruns, htmlfile, title): >> 3540 # write the html header first (html head, css code, up to body start) >> 3541 html = '<!DOCTYPE html>\n<html>\n<head>\n\ 4286 <meta http-equiv="content-type" conte 3542 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 4287 <title>'+title+'</title>\n\ !! 3543 <title>SleepGraph Summary</title>\n\ 4288 <style type=\'text/css\'>\n\ 3544 <style type=\'text/css\'>\n\ 4289 .stamp {width: 100%;text-alig 3545 .stamp {width: 100%;text-align:center;background:#888;line-height:30px;color:white;font: 25px Arial;}\n\ 4290 table {width:100%;border-coll !! 3546 table {width:100%;border-collapse: collapse;}\n\ >> 3547 .summary {border:1px solid;}\n\ 4291 th {border: 1px solid black;b 3548 th {border: 1px solid black;background:#222;color:white;}\n\ 4292 td {font: 14px "Times New Rom !! 3549 td {font: 14px "Times New Roman";text-align: center;}\n\ 4293 tr.head td {border: 1px solid 3550 tr.head td {border: 1px solid black;background:#aaa;}\n\ 4294 tr.alt {background-color:#ddd 3551 tr.alt {background-color:#ddd;}\n\ 4295 tr.notice {color:red;}\n\ 3552 tr.notice {color:red;}\n\ 4296 .minval {background-color:#BB 3553 .minval {background-color:#BBFFBB;}\n\ 4297 .medval {background-color:#BB 3554 .medval {background-color:#BBBBFF;}\n\ 4298 .maxval {background-color:#FF 3555 .maxval {background-color:#FFBBBB;}\n\ 4299 .head a {color:#000;text-deco 3556 .head a {color:#000;text-decoration: none;}\n\ 4300 </style>\n</head>\n<body>\n' 3557 </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 3558 4312 # extract the test data into list 3559 # extract the test data into list 4313 list = dict() 3560 list = dict() 4314 tAvg, tMin, tMax, tMed = [0.0, 0.0], !! 3561 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 3562 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0] 4316 num = 0 3563 num = 0 4317 useturbo = usewifi = False << 4318 lastmode = '' 3564 lastmode = '' 4319 cnt = dict() 3565 cnt = dict() 4320 for data in sorted(testruns, key=lamb 3566 for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])): 4321 mode = data['mode'] 3567 mode = data['mode'] 4322 if mode not in list: 3568 if mode not in list: 4323 list[mode] = {'data': 3569 list[mode] = {'data': [], 'avg': [0,0], 'min': [0,0], 'max': [0,0], 'med': [0,0]} 4324 if lastmode and lastmode != m 3570 if lastmode and lastmode != mode and num > 0: 4325 for i in range(2): 3571 for i in range(2): 4326 s = sorted(tM 3572 s = sorted(tMed[i]) 4327 list[lastmode !! 3573 list[lastmode]['med'][i] = s[int(len(s)/2)] 4328 iMed[i] = tMe !! 3574 iMed[i] = tMed[i].index(list[lastmode]['med'][i]) 4329 list[lastmode]['avg'] 3575 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 4330 list[lastmode]['min'] 3576 list[lastmode]['min'] = tMin 4331 list[lastmode]['max'] 3577 list[lastmode]['max'] = tMax 4332 list[lastmode]['idx'] 3578 list[lastmode]['idx'] = (iMin, iMed, iMax) 4333 tAvg, tMin, tMax, tMe !! 3579 tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []] 4334 iMin, iMed, iMax = [0 3580 iMin, iMed, iMax = [0, 0], [0, 0], [0, 0] 4335 num = 0 3581 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'] 3582 tVal = [float(data['suspend']), float(data['resume'])] 4343 list[mode]['data'].append([da 3583 list[mode]['data'].append([data['host'], data['kernel'], 4344 data['time'], tVal[0] !! 3584 data['time'], tVal[0], tVal[1], data['url'], data['result'], 4345 data['issues'], data[ 3585 data['issues'], data['sus_worst'], data['sus_worsttime'], 4346 data['res_worst'], da !! 3586 data['res_worst'], data['res_worsttime']]) 4347 (data['fullmode'] if << 4348 idx = len(list[mode]['data']) 3587 idx = len(list[mode]['data']) - 1 4349 if res.startswith('fail in'): !! 3588 if data['result'] not in cnt: 4350 res = 'fail' !! 3589 cnt[data['result']] = 1 4351 if res not in cnt: << 4352 cnt[res] = 1 << 4353 else: 3590 else: 4354 cnt[res] += 1 !! 3591 cnt[data['result']] += 1 4355 if res == 'pass': !! 3592 if data['result'] == 'pass': 4356 for i in range(2): 3593 for i in range(2): 4357 tMed[i][tVal[ !! 3594 tMed[i].append(tVal[i]) 4358 tAvg[i] += tV 3595 tAvg[i] += tVal[i] 4359 if tMin[i] == 3596 if tMin[i] == 0 or tVal[i] < tMin[i]: 4360 iMin[ 3597 iMin[i] = idx 4361 tMin[ 3598 tMin[i] = tVal[i] 4362 if tMax[i] == 3599 if tMax[i] == 0 or tVal[i] > tMax[i]: 4363 iMax[ 3600 iMax[i] = idx 4364 tMax[ 3601 tMax[i] = tVal[i] 4365 num += 1 3602 num += 1 4366 lastmode = mode 3603 lastmode = mode 4367 if lastmode and num > 0: 3604 if lastmode and num > 0: 4368 for i in range(2): 3605 for i in range(2): 4369 s = sorted(tMed[i]) 3606 s = sorted(tMed[i]) 4370 list[lastmode]['med'] !! 3607 list[lastmode]['med'][i] = s[int(len(s)/2)] 4371 iMed[i] = tMed[i][lis !! 3608 iMed[i] = tMed[i].index(list[lastmode]['med'][i]) 4372 list[lastmode]['avg'] = [tAvg 3609 list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num] 4373 list[lastmode]['min'] = tMin 3610 list[lastmode]['min'] = tMin 4374 list[lastmode]['max'] = tMax 3611 list[lastmode]['max'] = tMax 4375 list[lastmode]['idx'] = (iMin 3612 list[lastmode]['idx'] = (iMin, iMed, iMax) 4376 3613 4377 # group test header 3614 # group test header 4378 desc = [] 3615 desc = [] 4379 for ilk in sorted(cnt, reverse=True): 3616 for ilk in sorted(cnt, reverse=True): 4380 if cnt[ilk] > 0: 3617 if cnt[ilk] > 0: 4381 desc.append('%d %s' % 3618 desc.append('%d %s' % (cnt[ilk], ilk)) 4382 html += '<div class="stamp">%s (%d te 3619 html += '<div class="stamp">%s (%d tests: %s)</div>\n' % (title, len(testruns), ', '.join(desc)) 4383 th = '\t<th>{0}</th>\n' 3620 th = '\t<th>{0}</th>\n' 4384 td = '\t<td>{0}</td>\n' 3621 td = '\t<td>{0}</td>\n' 4385 tdh = '\t<td{1}>{0}</td>\n' 3622 tdh = '\t<td{1}>{0}</td>\n' 4386 tdlink = '\t<td><a href="{0}">html</a 3623 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 3624 4394 # table header 3625 # table header 4395 html += '<table>\n<tr>\n' + th.format !! 3626 html += '<table class="summary">\n<tr>\n' + th.format('#') +\ 4396 th.format('Mode') + th.format 3627 th.format('Mode') + th.format('Host') + th.format('Kernel') +\ 4397 th.format('Test Time') + th.f 3628 th.format('Test Time') + th.format('Result') + th.format('Issues') +\ 4398 th.format('Suspend') + th.for 3629 th.format('Suspend') + th.format('Resume') +\ 4399 th.format('Worst Suspend Devi 3630 th.format('Worst Suspend Device') + th.format('SD Time') +\ 4400 th.format('Worst Resume Devic !! 3631 th.format('Worst Resume Device') + th.format('RD Time') +\ 4401 if useturbo: !! 3632 th.format('Detail') + '</tr>\n' 4402 html += th.format('PkgPC10') !! 3633 4403 if usewifi: << 4404 html += th.format('Wifi') << 4405 html += th.format('Detail')+'</tr>\n' << 4406 # export list into html 3634 # export list into html 4407 head = '<tr class="head"><td>{0}</td> 3635 head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\ 4408 '<td colspan='+colspan+' clas !! 3636 '<td colspan=12 class="sus">Suspend Avg={2} '+\ 4409 '<span class=minval><a href=" 3637 '<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\ 4410 '<span class=medval><a href=" 3638 '<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\ 4411 '<span class=maxval><a href=" 3639 '<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\ 4412 'Resume Avg={6} '+\ 3640 'Resume Avg={6} '+\ 4413 '<span class=minval><a href=" 3641 '<span class=minval><a href="#r{10}min">Min={7}</a></span> '+\ 4414 '<span class=medval><a href=" 3642 '<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\ 4415 '<span class=maxval><a href=" 3643 '<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\ 4416 '</tr>\n' 3644 '</tr>\n' 4417 headnone = '<tr class="head"><td>{0}< !! 3645 headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan=12></td></tr>\n' 4418 colspan+'></td></tr>\n' !! 3646 for mode in list: 4419 for mode in sorted(list): << 4420 # header line for each suspen 3647 # header line for each suspend mode 4421 num = 0 3648 num = 0 4422 tAvg, tMin, tMax, tMed = list 3649 tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\ 4423 list[mode]['max'], li 3650 list[mode]['max'], list[mode]['med'] 4424 count = len(list[mode]['data' 3651 count = len(list[mode]['data']) 4425 if 'idx' in list[mode]: 3652 if 'idx' in list[mode]: 4426 iMin, iMed, iMax = li 3653 iMin, iMed, iMax = list[mode]['idx'] 4427 html += head.format(' 3654 html += head.format('%d' % count, mode.upper(), 4428 '%.3f' % tAvg 3655 '%.3f' % tAvg[0], '%.3f' % tMin[0], '%.3f' % tMed[0], '%.3f' % tMax[0], 4429 '%.3f' % tAvg 3656 '%.3f' % tAvg[1], '%.3f' % tMin[1], '%.3f' % tMed[1], '%.3f' % tMax[1], 4430 mode.lower() 3657 mode.lower() 4431 ) 3658 ) 4432 else: 3659 else: 4433 iMin = iMed = iMax = 3660 iMin = iMed = iMax = [-1, -1, -1] 4434 html += headnone.form 3661 html += headnone.format('%d' % count, mode.upper()) 4435 for d in list[mode]['data']: 3662 for d in list[mode]['data']: 4436 # row classes - alter 3663 # row classes - alternate row color 4437 rcls = ['alt'] if num 3664 rcls = ['alt'] if num % 2 == 1 else [] 4438 if d[6] != 'pass': 3665 if d[6] != 'pass': 4439 rcls.append(' 3666 rcls.append('notice') 4440 html += '<tr class="' 3667 html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n' 4441 # figure out if the l 3668 # figure out if the line has sus or res highlighted 4442 idx = list[mode]['dat 3669 idx = list[mode]['data'].index(d) 4443 tHigh = ['', ''] 3670 tHigh = ['', ''] 4444 for i in range(2): 3671 for i in range(2): 4445 tag = 's%s' % 3672 tag = 's%s' % mode if i == 0 else 'r%s' % mode 4446 if idx == iMi 3673 if idx == iMin[i]: 4447 tHigh 3674 tHigh[i] = ' id="%smin" class=minval title="Minimum"' % tag 4448 elif idx == i 3675 elif idx == iMax[i]: 4449 tHigh 3676 tHigh[i] = ' id="%smax" class=maxval title="Maximum"' % tag 4450 elif idx == i 3677 elif idx == iMed[i]: 4451 tHigh 3678 tHigh[i] = ' id="%smed" class=medval title="Median"' % tag 4452 html += td.format("%d 3679 html += td.format("%d" % (list[mode]['data'].index(d) + 1)) # row 4453 html += td.format(d[1 !! 3680 html += td.format(mode) # mode 4454 html += td.format(d[0 3681 html += td.format(d[0]) # host 4455 html += td.format(d[1 3682 html += td.format(d[1]) # kernel 4456 html += td.format(d[2 3683 html += td.format(d[2]) # time 4457 html += td.format(d[6 3684 html += td.format(d[6]) # result 4458 html += td.format(d[7 3685 html += td.format(d[7]) # issues 4459 html += tdh.format('% 3686 html += tdh.format('%.3f ms' % d[3], tHigh[0]) if d[3] else td.format('') # suspend 4460 html += tdh.format('% 3687 html += tdh.format('%.3f ms' % d[4], tHigh[1]) if d[4] else td.format('') # resume 4461 html += td.format(d[8 3688 html += td.format(d[8]) # sus_worst 4462 html += td.format('%. 3689 html += td.format('%.3f ms' % d[9]) if d[9] else td.format('') # sus_worst time 4463 html += td.format(d[1 3690 html += td.format(d[10]) # res_worst 4464 html += td.format('%. 3691 html += td.format('%.3f ms' % d[11]) if d[11] else td.format('') # res_worst time 4465 if useturbo: << 4466 html += td.fo << 4467 html += td.fo << 4468 if usewifi: << 4469 html += td.fo << 4470 html += tdlink.format 3692 html += tdlink.format(d[5]) if d[5] else td.format('') # url 4471 html += '</tr>\n' 3693 html += '</tr>\n' 4472 num += 1 3694 num += 1 4473 3695 4474 # flush the data to file 3696 # flush the data to file 4475 hf = open(htmlfile, 'w') 3697 hf = open(htmlfile, 'w') 4476 hf.write(html+'</table>\n</body>\n</h 3698 hf.write(html+'</table>\n</body>\n</html>\n') 4477 hf.close() 3699 hf.close() 4478 3700 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): 3701 def ordinal(value): 4590 suffix = 'th' 3702 suffix = 'th' 4591 if value < 10 or value > 19: 3703 if value < 10 or value > 19: 4592 if value % 10 == 1: 3704 if value % 10 == 1: 4593 suffix = 'st' 3705 suffix = 'st' 4594 elif value % 10 == 2: 3706 elif value % 10 == 2: 4595 suffix = 'nd' 3707 suffix = 'nd' 4596 elif value % 10 == 3: 3708 elif value % 10 == 3: 4597 suffix = 'rd' 3709 suffix = 'rd' 4598 return '%d%s' % (value, suffix) 3710 return '%d%s' % (value, suffix) 4599 3711 4600 # Function: createHTML 3712 # Function: createHTML 4601 # Description: 3713 # Description: 4602 # Create the output html file from the 3714 # Create the output html file from the resident test data 4603 # Arguments: 3715 # Arguments: 4604 # testruns: array of Data objects from 3716 # testruns: array of Data objects from parseKernelLog or parseTraceLog 4605 # Output: 3717 # Output: 4606 # True if the html file was created, f 3718 # True if the html file was created, false if it failed 4607 def createHTML(testruns, testfail): 3719 def createHTML(testruns, testfail): 4608 if len(testruns) < 1: 3720 if len(testruns) < 1: 4609 pprint('ERROR: Not enough tes 3721 pprint('ERROR: Not enough test data to build a timeline') 4610 return 3722 return 4611 3723 4612 kerror = False 3724 kerror = False 4613 for data in testruns: 3725 for data in testruns: 4614 if data.kerror: 3726 if data.kerror: 4615 kerror = True 3727 kerror = True 4616 if(sysvals.suspendmode in ['f 3728 if(sysvals.suspendmode in ['freeze', 'standby']): 4617 data.trimFreezeTime(t 3729 data.trimFreezeTime(testruns[-1].tSuspended) 4618 else: << 4619 data.getMemTime() << 4620 3730 4621 # html function templates 3731 # html function templates 4622 html_error = '<div id="{1}" title="ke 3732 html_error = '<div id="{1}" title="kernel error/warning" class="err" style="right:{0}%">{2}→</div>\n' 4623 html_traceevent = '<div title="{0}" c 3733 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 3734 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 3735 html_timetotal = '<table class="time1">\n<tr>'\ 4626 '<td class="green" title="{3} 3736 '<td class="green" title="{3}">{2} Suspend Time: <b>{0} ms</b></td>'\ 4627 '<td class="yellow" title="{4 3737 '<td class="yellow" title="{4}">{2} Resume Time: <b>{1} ms</b></td>'\ 4628 '</tr>\n</table>\n' 3738 '</tr>\n</table>\n' 4629 html_timetotal2 = '<table class="time 3739 html_timetotal2 = '<table class="time1">\n<tr>'\ 4630 '<td class="green" title="{4} 3740 '<td class="green" title="{4}">{3} Suspend Time: <b>{0} ms</b></td>'\ 4631 '<td class="gray" title="time 3741 '<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 3742 '<td class="yellow" title="{5}">{3} Resume Time: <b>{2} ms</b></td>'\ 4633 '</tr>\n</table>\n' 3743 '</tr>\n</table>\n' 4634 html_timetotal3 = '<table class="time 3744 html_timetotal3 = '<table class="time1">\n<tr>'\ 4635 '<td class="green">Execution 3745 '<td class="green">Execution Time: <b>{0} ms</b></td>'\ 4636 '<td class="yellow">Command: 3746 '<td class="yellow">Command: <b>{1}</b></td>'\ 4637 '</tr>\n</table>\n' 3747 '</tr>\n</table>\n' >> 3748 html_timegroups = '<table class="time2">\n<tr>'\ >> 3749 '<td class="green" title="time from kernel enter_state({5}) to firmware mode [kernel time only]">{4}Kernel Suspend: {0} ms</td>'\ >> 3750 '<td class="purple">{4}Firmware Suspend: {1} ms</td>'\ >> 3751 '<td class="purple">{4}Firmware Resume: {2} ms</td>'\ >> 3752 '<td class="yellow" title="time from firmware mode to return from kernel enter_state({5}) [kernel time only]">{4}Kernel Resume: {3} ms</td>'\ >> 3753 '</tr>\n</table>\n' 4638 html_fail = '<table class="testfail"> 3754 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 3755 4643 # html format variables 3756 # html format variables 4644 scaleH = 20 3757 scaleH = 20 4645 if kerror: 3758 if kerror: 4646 scaleH = 40 3759 scaleH = 40 4647 3760 4648 # device timeline 3761 # device timeline 4649 devtl = Timeline(30, scaleH) 3762 devtl = Timeline(30, scaleH) 4650 3763 4651 # write the test title and general in 3764 # write the test title and general info header 4652 devtl.createHeader(sysvals, testruns[ 3765 devtl.createHeader(sysvals, testruns[0].stamp) 4653 3766 4654 # Generate the header for this timeli 3767 # Generate the header for this timeline 4655 for data in testruns: 3768 for data in testruns: 4656 tTotal = data.end - data.star 3769 tTotal = data.end - data.start >> 3770 sktime, rktime = data.getTimeValues() 4657 if(tTotal == 0): 3771 if(tTotal == 0): 4658 doError('No timeline 3772 doError('No timeline data') >> 3773 if(len(data.tLow) > 0): >> 3774 low_time = '|'.join(data.tLow) 4659 if sysvals.suspendmode == 'co 3775 if sysvals.suspendmode == 'command': 4660 run_time = '%.0f' % ( !! 3776 run_time = '%.0f'%((data.end-data.start)*1000) 4661 if sysvals.testcomman 3777 if sysvals.testcommand: 4662 testdesc = sy 3778 testdesc = sysvals.testcommand 4663 else: 3779 else: 4664 testdesc = 'u 3780 testdesc = 'unknown' 4665 if(len(testruns) > 1) 3781 if(len(testruns) > 1): 4666 testdesc = or 3782 testdesc = ordinal(data.testnumber+1)+' '+testdesc 4667 thtml = html_timetota 3783 thtml = html_timetotal3.format(run_time, testdesc) 4668 devtl.html += thtml 3784 devtl.html += thtml 4669 continue !! 3785 elif data.fwValid: 4670 # typical full suspend/resume !! 3786 suspend_time = '%.0f'%(sktime + (data.fwSuspend/1000000.0)) 4671 stot, rtot = sktime, rktime = !! 3787 resume_time = '%.0f'%(rktime + (data.fwResume/1000000.0)) 4672 ssrc, rsrc, testdesc, testdes !! 3788 testdesc1 = 'Total' 4673 if data.fwValid: !! 3789 testdesc2 = '' 4674 stot += (data.fwSuspe !! 3790 stitle = 'time from kernel enter_state(%s) to low-power mode [kernel & firmware time]' % sysvals.suspendmode 4675 rtot += (data.fwResum !! 3791 rtitle = 'time from low-power mode to return from kernel enter_state(%s) [firmware & kernel time]' % sysvals.suspendmode 4676 ssrc.append('firmware !! 3792 if(len(testruns) > 1): 4677 rsrc.append('firmware !! 3793 testdesc1 = testdesc2 = ordinal(data.testnumber+1) 4678 testdesc = 'Total' !! 3794 testdesc2 += ' ' 4679 if 'time' in data.wifi and da !! 3795 if(len(data.tLow) == 0): 4680 rtot += data.end - da !! 3796 thtml = html_timetotal.format(suspend_time, \ 4681 rsrc.append('wifi') !! 3797 resume_time, testdesc1, stitle, rtitle) 4682 testdesc = 'Total' !! 3798 else: 4683 suspend_time, resume_time = ' !! 3799 thtml = html_timetotal2.format(suspend_time, low_time, \ 4684 stitle = 'time from kernel su !! 3800 resume_time, testdesc1, stitle, rtitle) 4685 (sysvals.suspendmode, !! 3801 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 3802 sftime = '%.3f'%(data.fwSuspend / 1000000.0) 4706 rftime = '%.3f'%(data 3803 rftime = '%.3f'%(data.fwResume / 1000000.0) 4707 thtml += html_fwdesc. !! 3804 devtl.html += html_timegroups.format('%.3f'%sktime, \ 4708 thtml += html_fwdesc. !! 3805 sftime, rftime, '%.3f'%rktime, testdesc2, sysvals.suspendmode) 4709 thtml += html_kdesc.format(te !! 3806 else: 4710 if 'time' in data.wifi: !! 3807 suspend_time = '%.3f' % sktime 4711 if data.wifi['stat'] !! 3808 resume_time = '%.3f' % rktime 4712 wtime = '%.0f !! 3809 testdesc = 'Kernel' >> 3810 stitle = 'time from kernel enter_state(%s) to firmware mode [kernel time only]' % sysvals.suspendmode >> 3811 rtitle = 'time from firmware mode to return from kernel enter_state(%s) [kernel time only]' % sysvals.suspendmode >> 3812 if(len(testruns) > 1): >> 3813 testdesc = ordinal(data.testnumber+1)+' '+testdesc >> 3814 if(len(data.tLow) == 0): >> 3815 thtml = html_timetotal.format(suspend_time, \ >> 3816 resume_time, testdesc, stitle, rtitle) 4713 else: 3817 else: 4714 wtime = 'TIME !! 3818 thtml = html_timetotal2.format(suspend_time, low_time, \ 4715 thtml += html_wifdesc !! 3819 resume_time, testdesc, stitle, rtitle) 4716 thtml += '</tr>\n</table>\n' !! 3820 devtl.html += thtml 4717 devtl.html += thtml !! 3821 4718 if testfail: 3822 if testfail: 4719 devtl.html += html_fail.forma 3823 devtl.html += html_fail.format(testfail) 4720 3824 4721 # time scale for potentially multiple 3825 # time scale for potentially multiple datasets 4722 t0 = testruns[0].start 3826 t0 = testruns[0].start 4723 tMax = testruns[-1].end 3827 tMax = testruns[-1].end 4724 tTotal = tMax - t0 3828 tTotal = tMax - t0 4725 3829 4726 # determine the maximum number of row 3830 # determine the maximum number of rows we need to draw 4727 fulllist = [] 3831 fulllist = [] 4728 threadlist = [] 3832 threadlist = [] 4729 pscnt = 0 3833 pscnt = 0 4730 devcnt = 0 3834 devcnt = 0 4731 for data in testruns: 3835 for data in testruns: 4732 data.selectTimelineDevices('% 3836 data.selectTimelineDevices('%f', tTotal, sysvals.mindevlen) 4733 for group in data.devicegroup 3837 for group in data.devicegroups: 4734 devlist = [] 3838 devlist = [] 4735 for phase in group: 3839 for phase in group: 4736 for devname i !! 3840 for devname in data.tdevlist[phase]: 4737 d = D 3841 d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname]) 4738 devli 3842 devlist.append(d) 4739 if d. 3843 if d.isa('kth'): 4740 3844 threadlist.append(d) 4741 else: 3845 else: 4742 3846 if d.isa('ps'): 4743 3847 pscnt += 1 4744 3848 else: 4745 3849 devcnt += 1 4746 3850 fulllist.append(d) 4747 if sysvals.mixedphase 3851 if sysvals.mixedphaseheight: 4748 devtl.getPhas 3852 devtl.getPhaseRows(devlist) 4749 if not sysvals.mixedphaseheight: 3853 if not sysvals.mixedphaseheight: 4750 if len(threadlist) > 0 and le 3854 if len(threadlist) > 0 and len(fulllist) > 0: 4751 if pscnt > 0 and devc 3855 if pscnt > 0 and devcnt > 0: 4752 msg = 'user p 3856 msg = 'user processes & device pm callbacks' 4753 elif pscnt > 0: 3857 elif pscnt > 0: 4754 msg = 'user p 3858 msg = 'user processes' 4755 else: 3859 else: 4756 msg = 'device 3860 msg = 'device pm callbacks' 4757 d = testruns[0].addHo 3861 d = testruns[0].addHorizontalDivider(msg, testruns[-1].end) 4758 fulllist.insert(0, d) 3862 fulllist.insert(0, d) 4759 devtl.getPhaseRows(fulllist) 3863 devtl.getPhaseRows(fulllist) 4760 if len(threadlist) > 0: 3864 if len(threadlist) > 0: 4761 d = testruns[0].addHo 3865 d = testruns[0].addHorizontalDivider('asynchronous kernel threads', testruns[-1].end) 4762 threadlist.insert(0, 3866 threadlist.insert(0, d) 4763 devtl.getPhaseRows(th 3867 devtl.getPhaseRows(threadlist, devtl.rows) 4764 devtl.calcTotalRows() 3868 devtl.calcTotalRows() 4765 3869 4766 # draw the full timeline 3870 # draw the full timeline 4767 devtl.createZoomBox(sysvals.suspendmo 3871 devtl.createZoomBox(sysvals.suspendmode, len(testruns)) 4768 for data in testruns: 3872 for data in testruns: 4769 # draw each test run and bloc 3873 # draw each test run and block chronologically 4770 phases = {'suspend':[],'resum 3874 phases = {'suspend':[],'resume':[]} 4771 for phase in data.sortedPhase 3875 for phase in data.sortedPhases(): 4772 if data.dmesg[phase][ 3876 if data.dmesg[phase]['start'] >= data.tSuspended: 4773 phases['resum 3877 phases['resume'].append(phase) 4774 else: 3878 else: 4775 phases['suspe 3879 phases['suspend'].append(phase) 4776 # now draw the actual timelin 3880 # now draw the actual timeline blocks 4777 for dir in phases: 3881 for dir in phases: 4778 # draw suspend and re 3882 # draw suspend and resume blocks separately 4779 bname = '%s%d' % (dir 3883 bname = '%s%d' % (dir[0], data.testnumber) 4780 if dir == 'suspend': 3884 if dir == 'suspend': 4781 m0 = data.sta 3885 m0 = data.start 4782 mMax = data.t 3886 mMax = data.tSuspended 4783 left = '%f' % 3887 left = '%f' % (((m0-t0)*100.0)/tTotal) 4784 else: 3888 else: 4785 m0 = data.tSu 3889 m0 = data.tSuspended 4786 mMax = data.e 3890 mMax = data.end 4787 # in an x2 ru 3891 # in an x2 run, remove any gap between blocks 4788 if len(testru 3892 if len(testruns) > 1 and data.testnumber == 0: 4789 mMax 3893 mMax = testruns[1].start 4790 left = '%f' % 3894 left = '%f' % ((((m0-t0)*100.0)+sysvals.srgap/2)/tTotal) 4791 mTotal = mMax - m0 3895 mTotal = mMax - m0 4792 # if a timeline block 3896 # if a timeline block is 0 length, skip altogether 4793 if mTotal == 0: 3897 if mTotal == 0: 4794 continue 3898 continue 4795 width = '%f' % (((mTo 3899 width = '%f' % (((mTotal*100.0)-sysvals.srgap/2)/tTotal) 4796 devtl.html += devtl.h 3900 devtl.html += devtl.html_tblock.format(bname, left, width, devtl.scaleH) 4797 for b in phases[dir]: 3901 for b in phases[dir]: 4798 # draw the ph 3902 # draw the phase color background 4799 phase = data. 3903 phase = data.dmesg[b] 4800 length = phas 3904 length = phase['end']-phase['start'] 4801 left = '%f' % 3905 left = '%f' % (((phase['start']-m0)*100.0)/mTotal) 4802 width = '%f' 3906 width = '%f' % ((length*100.0)/mTotal) 4803 devtl.html += 3907 devtl.html += devtl.html_phase.format(left, width, \ 4804 '%.3f 3908 '%.3f'%devtl.scaleH, '%.3f'%devtl.bodyH, \ 4805 data. 3909 data.dmesg[b]['color'], '') 4806 for e in data.errorin 3910 for e in data.errorinfo[dir]: 4807 # draw red li 3911 # draw red lines for any kernel errors found 4808 type, t, idx1 3912 type, t, idx1, idx2 = e 4809 id = '%d_%d' 3913 id = '%d_%d' % (idx1, idx2) 4810 right = '%f' 3914 right = '%f' % (((mMax-t)*100.0)/mTotal) 4811 devtl.html += 3915 devtl.html += html_error.format(right, id, type) 4812 for b in phases[dir]: 3916 for b in phases[dir]: 4813 # draw the de 3917 # draw the devices for this phase 4814 phaselist = d 3918 phaselist = data.dmesg[b]['list'] 4815 for d in sort !! 3919 for d in data.tdevlist[b]: 4816 dname !! 3920 name = d 4817 name, !! 3921 drv = '' 4818 drv = !! 3922 dev = phaselist[d] >> 3923 xtraclass = '' >> 3924 xtrainfo = '' >> 3925 xtrastyle = '' 4819 if 'h 3926 if 'htmlclass' in dev: 4820 3927 xtraclass = dev['htmlclass'] 4821 if 'c 3928 if 'color' in dev: 4822 3929 xtrastyle = 'background:%s;' % dev['color'] 4823 if(d 3930 if(d in sysvals.devprops): 4824 3931 name = sysvals.devprops[d].altName(d) 4825 3932 xtraclass = sysvals.devprops[d].xtraClass() 4826 3933 xtrainfo = sysvals.devprops[d].xtraInfo() 4827 elif 3934 elif xtraclass == ' kth': 4828 3935 xtrainfo = ' kernel_thread' 4829 if('d 3936 if('drv' in dev and dev['drv']): 4830 3937 drv = ' {%s}' % dev['drv'] 4831 rowhe 3938 rowheight = devtl.phaseRowHeight(data.testnumber, b, dev['row']) 4832 rowto 3939 rowtop = devtl.phaseRowTop(data.testnumber, b, dev['row']) 4833 top = 3940 top = '%.3f' % (rowtop + devtl.scaleH) 4834 left 3941 left = '%f' % (((dev['start']-m0)*100)/mTotal) 4835 width 3942 width = '%f' % (((dev['end']-dev['start'])*100)/mTotal) 4836 lengt 3943 length = ' (%0.3f ms) ' % ((dev['end']-dev['start'])*1000) 4837 title 3944 title = name+drv+xtrainfo+length 4838 if sy 3945 if sysvals.suspendmode == 'command': 4839 3946 title += sysvals.testcommand 4840 elif 3947 elif xtraclass == ' ps': 4841 3948 if 'suspend' in b: 4842 3949 title += 'pre_suspend_process' 4843 3950 else: 4844 3951 title += 'post_resume_process' 4845 else: 3952 else: 4846 3953 title += b 4847 devtl 3954 devtl.html += devtl.html_device.format(dev['id'], \ 4848 3955 title, left, top, '%.3f'%rowheight, width, \ 4849 !! 3956 d+drv, xtraclass, xtrastyle) 4850 if('c 3957 if('cpuexec' in dev): 4851 3958 for t in sorted(dev['cpuexec']): 4852 3959 start, end = t >> 3960 j = float(dev['cpuexec'][t]) / 5 >> 3961 if j > 1.0: >> 3962 j = 1.0 4853 3963 height = '%.3f' % (rowheight/3) 4854 3964 top = '%.3f' % (rowtop + devtl.scaleH + 2*rowheight/3) 4855 3965 left = '%f' % (((start-m0)*100)/mTotal) 4856 3966 width = '%f' % ((end-start)*100/mTotal) 4857 !! 3967 color = 'rgba(255, 0, 0, %f)' % j 4858 3968 devtl.html += \ 4859 3969 html_cpuexec.format(left, top, height, width, color) 4860 if('s 3970 if('src' not in dev): 4861 3971 continue 4862 # dra 3972 # draw any trace events for this device 4863 for e 3973 for e in dev['src']: 4864 << 4865 << 4866 3974 height = '%.3f' % devtl.rowH 4867 3975 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH)) 4868 3976 left = '%f' % (((e.time-m0)*100)/mTotal) 4869 3977 width = '%f' % (e.length*100/mTotal) 4870 3978 xtrastyle = '' 4871 3979 if e.color: 4872 3980 xtrastyle = 'background:%s;' % e.color 4873 3981 devtl.html += \ 4874 3982 html_traceevent.format(e.title(), \ 4875 3983 left, top, height, width, e.text(), '', xtrastyle) 4876 # draw the time scale 3984 # draw the time scale, try to make the number of labels readable 4877 devtl.createTimeScale 3985 devtl.createTimeScale(m0, mMax, tTotal, dir) 4878 devtl.html += '</div> 3986 devtl.html += '</div>\n' 4879 3987 4880 # timeline is finished 3988 # timeline is finished 4881 devtl.html += '</div>\n</div>\n' 3989 devtl.html += '</div>\n</div>\n' 4882 3990 4883 # draw a legend which describes the p 3991 # draw a legend which describes the phases by color 4884 if sysvals.suspendmode != 'command': 3992 if sysvals.suspendmode != 'command': 4885 phasedef = testruns[-1].phase 3993 phasedef = testruns[-1].phasedef 4886 devtl.html += '<div class="le 3994 devtl.html += '<div class="legend">\n' 4887 pdelta = 100.0/len(phasedef.k 3995 pdelta = 100.0/len(phasedef.keys()) 4888 pmargin = pdelta / 4.0 3996 pmargin = pdelta / 4.0 4889 for phase in sorted(phasedef, 3997 for phase in sorted(phasedef, key=lambda k:phasedef[k]['order']): 4890 id, p = '', phasedef[ 3998 id, p = '', phasedef[phase] 4891 for word in phase.spl 3999 for word in phase.split('_'): 4892 id += word[0] 4000 id += word[0] 4893 order = '%.2f' % ((p[ 4001 order = '%.2f' % ((p['order'] * pdelta) + pmargin) 4894 name = phase.replace( !! 4002 name = string.replace(phase, '_', ' ') 4895 devtl.html += devtl.h 4003 devtl.html += devtl.html_legend.format(order, p['color'], name, id) 4896 devtl.html += '</div>\n' 4004 devtl.html += '</div>\n' 4897 4005 4898 hf = open(sysvals.htmlfile, 'w') 4006 hf = open(sysvals.htmlfile, 'w') 4899 addCSS(hf, sysvals, len(testruns), ke 4007 addCSS(hf, sysvals, len(testruns), kerror) 4900 4008 4901 # write the device timeline 4009 # write the device timeline 4902 hf.write(devtl.html) 4010 hf.write(devtl.html) 4903 hf.write('<div id="devicedetailtitle" 4011 hf.write('<div id="devicedetailtitle"></div>\n') 4904 hf.write('<div id="devicedetail" styl 4012 hf.write('<div id="devicedetail" style="display:none;">\n') 4905 # draw the colored boxes for the devi 4013 # draw the colored boxes for the device detail section 4906 for data in testruns: 4014 for data in testruns: 4907 hf.write('<div id="devicedeta 4015 hf.write('<div id="devicedetail%d">\n' % data.testnumber) 4908 pscolor = 'linear-gradient(to 4016 pscolor = 'linear-gradient(to top left, #ccc, #eee)' 4909 hf.write(devtl.html_phaselet. 4017 hf.write(devtl.html_phaselet.format('pre_suspend_process', \ 4910 '0', '0', pscolor)) 4018 '0', '0', pscolor)) 4911 for b in data.sortedPhases(): 4019 for b in data.sortedPhases(): 4912 phase = data.dmesg[b] 4020 phase = data.dmesg[b] 4913 length = phase['end'] 4021 length = phase['end']-phase['start'] 4914 left = '%.3f' % (((ph 4022 left = '%.3f' % (((phase['start']-t0)*100.0)/tTotal) 4915 width = '%.3f' % ((le 4023 width = '%.3f' % ((length*100.0)/tTotal) 4916 hf.write(devtl.html_p 4024 hf.write(devtl.html_phaselet.format(b, left, width, \ 4917 data.dmesg[b] 4025 data.dmesg[b]['color'])) 4918 hf.write(devtl.html_phaselet. 4026 hf.write(devtl.html_phaselet.format('post_resume_process', \ 4919 '0', '0', pscolor)) 4027 '0', '0', pscolor)) 4920 if sysvals.suspendmode == 'co 4028 if sysvals.suspendmode == 'command': 4921 hf.write(devtl.html_p 4029 hf.write(devtl.html_phaselet.format('cmdexec', '0', '0', pscolor)) 4922 hf.write('</div>\n') 4030 hf.write('</div>\n') 4923 hf.write('</div>\n') 4031 hf.write('</div>\n') 4924 4032 4925 # write the ftrace data (callgraph) 4033 # write the ftrace data (callgraph) 4926 if sysvals.cgtest >= 0 and len(testru 4034 if sysvals.cgtest >= 0 and len(testruns) > sysvals.cgtest: 4927 data = testruns[sysvals.cgtes 4035 data = testruns[sysvals.cgtest] 4928 else: 4036 else: 4929 data = testruns[-1] 4037 data = testruns[-1] 4930 if sysvals.usecallgraph: 4038 if sysvals.usecallgraph: 4931 addCallgraphs(sysvals, hf, da 4039 addCallgraphs(sysvals, hf, data) 4932 4040 4933 # add the test log as a hidden div 4041 # add the test log as a hidden div 4934 if sysvals.testlog and sysvals.logmsg 4042 if sysvals.testlog and sysvals.logmsg: 4935 hf.write('<div id="testlog" s 4043 hf.write('<div id="testlog" style="display:none;">\n'+sysvals.logmsg+'</div>\n') 4936 # add the dmesg log as a hidden div 4044 # add the dmesg log as a hidden div 4937 if sysvals.dmesglog and sysvals.dmesg 4045 if sysvals.dmesglog and sysvals.dmesgfile: 4938 hf.write('<div id="dmesglog" 4046 hf.write('<div id="dmesglog" style="display:none;">\n') 4939 lf = sysvals.openlog(sysvals. 4047 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 4940 for line in lf: 4048 for line in lf: 4941 line = line.replace(' 4049 line = line.replace('<', '<').replace('>', '>') 4942 hf.write(line) 4050 hf.write(line) 4943 lf.close() 4051 lf.close() 4944 hf.write('</div>\n') 4052 hf.write('</div>\n') 4945 # add the ftrace log as a hidden div 4053 # add the ftrace log as a hidden div 4946 if sysvals.ftracelog and sysvals.ftra 4054 if sysvals.ftracelog and sysvals.ftracefile: 4947 hf.write('<div id="ftracelog" 4055 hf.write('<div id="ftracelog" style="display:none;">\n') 4948 lf = sysvals.openlog(sysvals. 4056 lf = sysvals.openlog(sysvals.ftracefile, 'r') 4949 for line in lf: 4057 for line in lf: 4950 hf.write(line) 4058 hf.write(line) 4951 lf.close() 4059 lf.close() 4952 hf.write('</div>\n') 4060 hf.write('</div>\n') 4953 4061 4954 # write the footer and close 4062 # write the footer and close 4955 addScriptCode(hf, testruns) 4063 addScriptCode(hf, testruns) 4956 hf.write('</body>\n</html>\n') 4064 hf.write('</body>\n</html>\n') 4957 hf.close() 4065 hf.close() 4958 return True 4066 return True 4959 4067 4960 def addCSS(hf, sv, testcount=1, kerror=False, 4068 def addCSS(hf, sv, testcount=1, kerror=False, extra=''): 4961 kernel = sv.stamp['kernel'] 4069 kernel = sv.stamp['kernel'] 4962 host = sv.hostname[0].upper()+sv.host 4070 host = sv.hostname[0].upper()+sv.hostname[1:] 4963 mode = sv.suspendmode 4071 mode = sv.suspendmode 4964 if sv.suspendmode in suspendmodename: 4072 if sv.suspendmode in suspendmodename: 4965 mode = suspendmodename[sv.sus 4073 mode = suspendmodename[sv.suspendmode] 4966 title = host+' '+mode+' '+kernel 4074 title = host+' '+mode+' '+kernel 4967 4075 4968 # various format changes by flags 4076 # various format changes by flags 4969 cgchk = 'checked' 4077 cgchk = 'checked' 4970 cgnchk = 'not(:checked)' 4078 cgnchk = 'not(:checked)' 4971 if sv.cgexp: 4079 if sv.cgexp: 4972 cgchk = 'not(:checked)' 4080 cgchk = 'not(:checked)' 4973 cgnchk = 'checked' 4081 cgnchk = 'checked' 4974 4082 4975 hoverZ = 'z-index:8;' 4083 hoverZ = 'z-index:8;' 4976 if sv.usedevsrc: 4084 if sv.usedevsrc: 4977 hoverZ = '' 4085 hoverZ = '' 4978 4086 4979 devlistpos = 'absolute' 4087 devlistpos = 'absolute' 4980 if testcount > 1: 4088 if testcount > 1: 4981 devlistpos = 'relative' 4089 devlistpos = 'relative' 4982 4090 4983 scaleTH = 20 4091 scaleTH = 20 4984 if kerror: 4092 if kerror: 4985 scaleTH = 60 4093 scaleTH = 60 4986 4094 4987 # write the html header first (html h 4095 # write the html header first (html head, css code, up to body start) 4988 html_header = '<!DOCTYPE html>\n<html 4096 html_header = '<!DOCTYPE html>\n<html>\n<head>\n\ 4989 <meta http-equiv="content-type" conte 4097 <meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\ 4990 <title>'+title+'</title>\n\ 4098 <title>'+title+'</title>\n\ 4991 <style type=\'text/css\'>\n\ 4099 <style type=\'text/css\'>\n\ 4992 body {overflow-y:scroll;}\n\ 4100 body {overflow-y:scroll;}\n\ 4993 .stamp {width:100%;text-align 4101 .stamp {width:100%;text-align:center;background:gray;line-height:30px;color:white;font:25px Arial;}\n\ 4994 .stamp.sysinfo {font:10px Ari 4102 .stamp.sysinfo {font:10px Arial;}\n\ 4995 .callgraph {margin-top:30px;b 4103 .callgraph {margin-top:30px;box-shadow:5px 5px 20px black;}\n\ 4996 .callgraph article * {padding 4104 .callgraph article * {padding-left:28px;}\n\ 4997 h1 {color:black;font:bold 30p 4105 h1 {color:black;font:bold 30px Times;}\n\ 4998 t0 {color:black;font:bold 30p 4106 t0 {color:black;font:bold 30px Times;}\n\ 4999 t1 {color:black;font:30px Tim 4107 t1 {color:black;font:30px Times;}\n\ 5000 t2 {color:black;font:25px Tim 4108 t2 {color:black;font:25px Times;}\n\ 5001 t3 {color:black;font:20px Tim 4109 t3 {color:black;font:20px Times;white-space:nowrap;}\n\ 5002 t4 {color:black;font:bold 30p 4110 t4 {color:black;font:bold 30px Times;line-height:60px;white-space:nowrap;}\n\ 5003 cS {font:bold 13px Times;}\n\ 4111 cS {font:bold 13px Times;}\n\ 5004 table {width:100%;}\n\ 4112 table {width:100%;}\n\ 5005 .gray {background:rgba(80,80, 4113 .gray {background:rgba(80,80,80,0.1);}\n\ 5006 .green {background:rgba(204,2 4114 .green {background:rgba(204,255,204,0.4);}\n\ 5007 .purple {background:rgba(128, 4115 .purple {background:rgba(128,0,128,0.2);}\n\ 5008 .yellow {background:rgba(255, 4116 .yellow {background:rgba(255,255,204,0.4);}\n\ 5009 .blue {background:rgba(169,20 4117 .blue {background:rgba(169,208,245,0.4);}\n\ 5010 .time1 {font:22px Arial;borde 4118 .time1 {font:22px Arial;border:1px solid;}\n\ 5011 .time2 {font:15px Arial;borde 4119 .time2 {font:15px Arial;border-bottom:1px solid;border-left:1px solid;border-right:1px solid;}\n\ 5012 .testfail {font:bold 22px Ari 4120 .testfail {font:bold 22px Arial;color:red;border:1px dashed;}\n\ 5013 td {text-align:center;}\n\ 4121 td {text-align:center;}\n\ 5014 r {color:#500000;font:15px Ta 4122 r {color:#500000;font:15px Tahoma;}\n\ 5015 n {color:#505050;font:15px Ta 4123 n {color:#505050;font:15px Tahoma;}\n\ 5016 .tdhl {color:red;}\n\ 4124 .tdhl {color:red;}\n\ 5017 .hide {display:none;}\n\ 4125 .hide {display:none;}\n\ 5018 .pf {display:none;}\n\ 4126 .pf {display:none;}\n\ 5019 .pf:'+cgchk+' + label {backgr 4127 .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 4128 .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 4129 .pf:'+cgchk+' ~ *:not(:nth-child(2)) {display:none;}\n\ 5022 .zoombox {position:relative;w 4130 .zoombox {position:relative;width:100%;overflow-x:scroll;-webkit-user-select:none;-moz-user-select:none;user-select:none;}\n\ 5023 .timeline {position:relative; 4131 .timeline {position:relative;font-size:14px;cursor:pointer;width:100%; overflow:hidden;background:linear-gradient(#cccccc, white);}\n\ 5024 .thread {position:absolute;he 4132 .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 4133 .thread.ps {border-radius:3px;background:linear-gradient(to top, #ccc, #eee);}\n\ 5026 .thread:hover {background:whi 4134 .thread:hover {background:white;border:1px solid red;'+hoverZ+'}\n\ 5027 .thread.sec,.thread.sec:hover 4135 .thread.sec,.thread.sec:hover {background:black;border:0;color:white;line-height:15px;font-size:10px;}\n\ 5028 .hover {background:white;bord 4136 .hover {background:white;border:1px solid red;'+hoverZ+'}\n\ 5029 .hover.sync {background:white 4137 .hover.sync {background:white;}\n\ 5030 .hover.bg,.hover.kth,.hover.s 4138 .hover.bg,.hover.kth,.hover.sync,.hover.ps {background:white;}\n\ 5031 .jiffie {position:absolute;po 4139 .jiffie {position:absolute;pointer-events: none;z-index:8;}\n\ 5032 .traceevent {position:absolut 4140 .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 4141 .traceevent:hover {color:white;font-weight:bold;border:1px solid white;}\n\ 5034 .phase {position:absolute;ove 4142 .phase {position:absolute;overflow:hidden;border:0px;text-align:center;}\n\ 5035 .phaselet {float:left;overflo 4143 .phaselet {float:left;overflow:hidden;border:0px;text-align:center;min-height:100px;font-size:24px;}\n\ 5036 .t {position:absolute;line-he 4144 .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 4145 .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 4146 .legend {position:relative; width:100%; height:40px; text-align:center;margin-bottom:20px}\n\ 5039 .legend .square {position:abs 4147 .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 4148 button {height:40px;width:200px;margin-bottom:20px;margin-top:20px;font-size:24px;}\n\ 5041 .btnfmt {position:relative;fl 4149 .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 4150 .devlist {position:'+devlistpos+';width:190px;}\n\ 5043 a:link {color:white;text-deco 4151 a:link {color:white;text-decoration:none;}\n\ 5044 a:visited {color:white;}\n\ 4152 a:visited {color:white;}\n\ 5045 a:hover {color:white;}\n\ 4153 a:hover {color:white;}\n\ 5046 a:active {color:white;}\n\ 4154 a:active {color:white;}\n\ 5047 .version {position:relative;f 4155 .version {position:relative;float:left;color:white;font-size:10px;line-height:30px;margin-left:10px;}\n\ 5048 #devicedetail {min-height:100 4156 #devicedetail {min-height:100px;box-shadow:5px 5px 20px black;}\n\ 5049 .tblock {position:absolute;he 4157 .tblock {position:absolute;height:100%;background:#ddd;}\n\ 5050 .tback {position:absolute;wid 4158 .tback {position:absolute;width:100%;background:linear-gradient(#ccc, #ddd);}\n\ 5051 .bg {z-index:1;}\n\ 4159 .bg {z-index:1;}\n\ 5052 '+extra+'\ 4160 '+extra+'\ 5053 </style>\n</head>\n<body>\n' 4161 </style>\n</head>\n<body>\n' 5054 hf.write(html_header) 4162 hf.write(html_header) 5055 4163 5056 # Function: addScriptCode 4164 # Function: addScriptCode 5057 # Description: 4165 # Description: 5058 # Adds the javascript code to the outp 4166 # Adds the javascript code to the output html 5059 # Arguments: 4167 # Arguments: 5060 # hf: the open html file pointer 4168 # hf: the open html file pointer 5061 # testruns: array of Data objects from 4169 # testruns: array of Data objects from parseKernelLog or parseTraceLog 5062 def addScriptCode(hf, testruns): 4170 def addScriptCode(hf, testruns): 5063 t0 = testruns[0].start * 1000 4171 t0 = testruns[0].start * 1000 5064 tMax = testruns[-1].end * 1000 4172 tMax = testruns[-1].end * 1000 5065 hf.write('<script type="text/javascri << 5066 # create an array in javascript memor 4173 # create an array in javascript memory with the device details 5067 detail = ' var devtable = [];\n' 4174 detail = ' var devtable = [];\n' 5068 for data in testruns: 4175 for data in testruns: 5069 topo = data.deviceTopology() 4176 topo = data.deviceTopology() 5070 detail += ' devtable[%d] 4177 detail += ' devtable[%d] = "%s";\n' % (data.testnumber, topo) 5071 detail += ' var bounds = [%f,%f]; 4178 detail += ' var bounds = [%f,%f];\n' % (t0, tMax) 5072 # add the code which will manipulate 4179 # add the code which will manipulate the data in the browser 5073 hf.write(detail); !! 4180 script_code = \ 5074 script_code = r""" var resolutio !! 4181 '<script type="text/javascript">\n'+detail+\ 5075 var dragval = [0, 0]; !! 4182 ' var resolution = -1;\n'\ 5076 function redrawTimescale(t0, tMax, tS !! 4183 ' var dragval = [0, 0];\n'\ 5077 var rline = '<div class="t" s !! 4184 ' function redrawTimescale(t0, tMax, tS) {\n'\ 5078 var tTotal = tMax - t0; !! 4185 ' var rline = \'<div class="t" style="left:0;border-left:1px solid black;border-right:0;">\';\n'\ 5079 var list = document.getElemen !! 4186 ' var tTotal = tMax - t0;\n'\ 5080 for (var i = 0; i < list.leng !! 4187 ' var list = document.getElementsByClassName("tblock");\n'\ 5081 var timescale = list[ !! 4188 ' for (var i = 0; i < list.length; i++) {\n'\ 5082 var m0 = t0 + (tTotal !! 4189 ' var timescale = list[i].getElementsByClassName("timescale")[0];\n'\ 5083 var mTotal = tTotal*p !! 4190 ' var m0 = t0 + (tTotal*parseFloat(list[i].style.left)/100);\n'\ 5084 var mMax = m0 + mTota !! 4191 ' var mTotal = tTotal*parseFloat(list[i].style.width)/100;\n'\ 5085 var html = ""; !! 4192 ' var mMax = m0 + mTotal;\n'\ 5086 var divTotal = Math.f !! 4193 ' var html = "";\n'\ 5087 if(divTotal > 1000) c !! 4194 ' var divTotal = Math.floor(mTotal/tS) + 1;\n'\ 5088 var divEdge = (mTotal !! 4195 ' if(divTotal > 1000) continue;\n'\ 5089 var pos = 0.0, val = !! 4196 ' var divEdge = (mTotal - tS*(divTotal-1))*100/mTotal;\n'\ 5090 for (var j = 0; j < d !! 4197 ' var pos = 0.0, val = 0.0;\n'\ 5091 var htmlline !! 4198 ' for (var j = 0; j < divTotal; j++) {\n'\ 5092 var mode = li !! 4199 ' var htmlline = "";\n'\ 5093 if(mode == "s !! 4200 ' var mode = list[i].id[5];\n'\ 5094 pos = !! 4201 ' if(mode == "s") {\n'\ 5095 val = !! 4202 ' pos = 100 - (((j)*tS*100)/mTotal) - divEdge;\n'\ 5096 if(j !! 4203 ' val = (j-divTotal+1)*tS;\n'\ 5097 !! 4204 ' if(j == divTotal - 1)\n'\ 5098 else !! 4205 ' htmlline = \'<div class="t" style="right:\'+pos+\'%"><cS>S→</cS></div>\';\n'\ 5099 !! 4206 ' else\n'\ 5100 } else { !! 4207 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\ 5101 pos = !! 4208 ' } else {\n'\ 5102 val = !! 4209 ' pos = 100 - (((j)*tS*100)/mTotal);\n'\ 5103 htmll !! 4210 ' val = (j)*tS;\n'\ 5104 if(j !! 4211 ' htmlline = \'<div class="t" style="right:\'+pos+\'%">\'+val+\'ms</div>\';\n'\ 5105 !! 4212 ' if(j == 0)\n'\ 5106 !! 4213 ' if(mode == "r")\n'\ 5107 !! 4214 ' htmlline = rline+"<cS>←R</cS></div>";\n'\ 5108 !! 4215 ' else\n'\ 5109 } !! 4216 ' htmlline = rline+"<cS>0ms</div>";\n'\ 5110 html += htmll !! 4217 ' }\n'\ 5111 } !! 4218 ' html += htmlline;\n'\ 5112 timescale.innerHTML = !! 4219 ' }\n'\ 5113 } !! 4220 ' timescale.innerHTML = html;\n'\ 5114 } !! 4221 ' }\n'\ 5115 function zoomTimeline() { !! 4222 ' }\n'\ 5116 var dmesg = document.getEleme !! 4223 ' function zoomTimeline() {\n'\ 5117 var zoombox = document.getEle !! 4224 ' var dmesg = document.getElementById("dmesg");\n'\ 5118 var left = zoombox.scrollLeft !! 4225 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 5119 var val = parseFloat(dmesg.st !! 4226 ' var left = zoombox.scrollLeft;\n'\ 5120 var newval = 100; !! 4227 ' var val = parseFloat(dmesg.style.width);\n'\ 5121 var sh = window.outerWidth / !! 4228 ' var newval = 100;\n'\ 5122 if(this.id == "zoomin") { !! 4229 ' var sh = window.outerWidth / 2;\n'\ 5123 newval = val * 1.2; !! 4230 ' if(this.id == "zoomin") {\n'\ 5124 if(newval > 910034) n !! 4231 ' newval = val * 1.2;\n'\ 5125 dmesg.style.width = n !! 4232 ' if(newval > 910034) newval = 910034;\n'\ 5126 zoombox.scrollLeft = !! 4233 ' dmesg.style.width = newval+"%";\n'\ 5127 } else if (this.id == "zoomou !! 4234 ' zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\ 5128 newval = val / 1.2; !! 4235 ' } else if (this.id == "zoomout") {\n'\ 5129 if(newval < 100) newv !! 4236 ' newval = val / 1.2;\n'\ 5130 dmesg.style.width = n !! 4237 ' if(newval < 100) newval = 100;\n'\ 5131 zoombox.scrollLeft = !! 4238 ' dmesg.style.width = newval+"%";\n'\ 5132 } else { !! 4239 ' zoombox.scrollLeft = ((left + sh) * newval / val) - sh;\n'\ 5133 zoombox.scrollLeft = !! 4240 ' } else {\n'\ 5134 dmesg.style.width = " !! 4241 ' zoombox.scrollLeft = 0;\n'\ 5135 } !! 4242 ' dmesg.style.width = "100%";\n'\ 5136 var tS = [10000, 5000, 2000, !! 4243 ' }\n'\ 5137 var t0 = bounds[0]; !! 4244 ' var tS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5, 2, 1];\n'\ 5138 var tMax = bounds[1]; !! 4245 ' var t0 = bounds[0];\n'\ 5139 var tTotal = tMax - t0; !! 4246 ' var tMax = bounds[1];\n'\ 5140 var wTotal = tTotal * 100.0 / !! 4247 ' var tTotal = tMax - t0;\n'\ 5141 var idx = 7*window.innerWidth !! 4248 ' var wTotal = tTotal * 100.0 / newval;\n'\ 5142 for(var i = 0; (i < tS.length !! 4249 ' var idx = 7*window.innerWidth/1100;\n'\ 5143 if(i >= tS.length) i = tS.len !! 4250 ' for(var i = 0; (i < tS.length)&&((wTotal / tS[i]) < idx); i++);\n'\ 5144 if(tS[i] == resolution) retur !! 4251 ' if(i >= tS.length) i = tS.length - 1;\n'\ 5145 resolution = tS[i]; !! 4252 ' if(tS[i] == resolution) return;\n'\ 5146 redrawTimescale(t0, tMax, tS[ !! 4253 ' resolution = tS[i];\n'\ 5147 } !! 4254 ' redrawTimescale(t0, tMax, tS[i]);\n'\ 5148 function deviceName(title) { !! 4255 ' }\n'\ 5149 var name = title.slice(0, tit !! 4256 ' function deviceName(title) {\n'\ 5150 return name; !! 4257 ' var name = title.slice(0, title.indexOf(" ("));\n'\ 5151 } !! 4258 ' return name;\n'\ 5152 function deviceHover() { !! 4259 ' }\n'\ 5153 var name = deviceName(this.ti !! 4260 ' function deviceHover() {\n'\ 5154 var dmesg = document.getEleme !! 4261 ' var name = deviceName(this.title);\n'\ 5155 var dev = dmesg.getElementsBy !! 4262 ' var dmesg = document.getElementById("dmesg");\n'\ 5156 var cpu = -1; !! 4263 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5157 if(name.match("CPU_ON\[[0-9]* !! 4264 ' var cpu = -1;\n'\ 5158 cpu = parseInt(name.s !! 4265 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ 5159 else if(name.match("CPU_OFF\[ !! 4266 ' cpu = parseInt(name.slice(7));\n'\ 5160 cpu = parseInt(name.s !! 4267 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ 5161 for (var i = 0; i < dev.lengt !! 4268 ' cpu = parseInt(name.slice(8));\n'\ 5162 dname = deviceName(de !! 4269 ' for (var i = 0; i < dev.length; i++) {\n'\ 5163 var cname = dev[i].cl !! 4270 ' dname = deviceName(dev[i].title);\n'\ 5164 if((cpu >= 0 && dname !! 4271 ' var cname = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\ 5165 (name == dnam !! 4272 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 5166 { !! 4273 ' (name == dname))\n'\ 5167 dev[i].classN !! 4274 ' {\n'\ 5168 } else { !! 4275 ' dev[i].className = "hover "+cname;\n'\ 5169 dev[i].classN !! 4276 ' } else {\n'\ 5170 } !! 4277 ' dev[i].className = cname;\n'\ 5171 } !! 4278 ' }\n'\ 5172 } !! 4279 ' }\n'\ 5173 function deviceUnhover() { !! 4280 ' }\n'\ 5174 var dmesg = document.getEleme !! 4281 ' function deviceUnhover() {\n'\ 5175 var dev = dmesg.getElementsBy !! 4282 ' var dmesg = document.getElementById("dmesg");\n'\ 5176 for (var i = 0; i < dev.lengt !! 4283 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5177 dev[i].className = de !! 4284 ' for (var i = 0; i < dev.length; i++) {\n'\ 5178 } !! 4285 ' dev[i].className = dev[i].className.slice(dev[i].className.indexOf("thread"));\n'\ 5179 } !! 4286 ' }\n'\ 5180 function deviceTitle(title, total, cp !! 4287 ' }\n'\ 5181 var prefix = "Total"; !! 4288 ' function deviceTitle(title, total, cpu) {\n'\ 5182 if(total.length > 3) { !! 4289 ' var prefix = "Total";\n'\ 5183 prefix = "Average"; !! 4290 ' if(total.length > 3) {\n'\ 5184 total[1] = (total[1]+ !! 4291 ' prefix = "Average";\n'\ 5185 total[2] = (total[2]+ !! 4292 ' total[1] = (total[1]+total[3])/2;\n'\ 5186 } !! 4293 ' total[2] = (total[2]+total[4])/2;\n'\ 5187 var devtitle = document.getEl !! 4294 ' }\n'\ 5188 var name = deviceName(title); !! 4295 ' var devtitle = document.getElementById("devicedetailtitle");\n'\ 5189 if(cpu >= 0) name = "CPU"+cpu !! 4296 ' var name = deviceName(title);\n'\ 5190 var driver = ""; !! 4297 ' if(cpu >= 0) name = "CPU"+cpu;\n'\ 5191 var tS = "<t2>(</t2>"; !! 4298 ' var driver = "";\n'\ 5192 var tR = "<t2>)</t2>"; !! 4299 ' var tS = "<t2>(</t2>";\n'\ 5193 if(total[1] > 0) !! 4300 ' var tR = "<t2>)</t2>";\n'\ 5194 tS = "<t2>("+prefix+" !! 4301 ' if(total[1] > 0)\n'\ 5195 if(total[2] > 0) !! 4302 ' tS = "<t2>("+prefix+" Suspend:</t2><t0> "+total[1].toFixed(3)+" ms</t0> ";\n'\ 5196 tR = " <t2>"+prefix+" !! 4303 ' if(total[2] > 0)\n'\ 5197 var s = title.indexOf("{"); !! 4304 ' tR = " <t2>"+prefix+" Resume:</t2><t0> "+total[2].toFixed(3)+" ms<t2>)</t2></t0>";\n'\ 5198 var e = title.indexOf("}"); !! 4305 ' var s = title.indexOf("{");\n'\ 5199 if((s >= 0) && (e >= 0)) !! 4306 ' var e = title.indexOf("}");\n'\ 5200 driver = title.slice(< !! 4307 ' if((s >= 0) && (e >= 0))\n'\ 5201 if(total[1] > 0 && total[2] > !! 4308 ' driver = title.slice(s+1, e) + " <t1>@</t1> ";\n'\ 5202 devtitle.innerHTML = !! 4309 ' if(total[1] > 0 && total[2] > 0)\n'\ 5203 else !! 4310 ' devtitle.innerHTML = "<t0>"+driver+name+"</t0> "+tS+tR;\n'\ 5204 devtitle.innerHTML = !! 4311 ' else\n'\ 5205 return name; !! 4312 ' devtitle.innerHTML = "<t0>"+title+"</t0>";\n'\ 5206 } !! 4313 ' return name;\n'\ 5207 function deviceDetail() { !! 4314 ' }\n'\ 5208 var devinfo = document.getEle !! 4315 ' function deviceDetail() {\n'\ 5209 devinfo.style.display = "bloc !! 4316 ' var devinfo = document.getElementById("devicedetail");\n'\ 5210 var name = deviceName(this.ti !! 4317 ' devinfo.style.display = "block";\n'\ 5211 var cpu = -1; !! 4318 ' var name = deviceName(this.title);\n'\ 5212 if(name.match("CPU_ON\[[0-9]* !! 4319 ' var cpu = -1;\n'\ 5213 cpu = parseInt(name.s !! 4320 ' if(name.match("CPU_ON\[[0-9]*\]"))\n'\ 5214 else if(name.match("CPU_OFF\[ !! 4321 ' cpu = parseInt(name.slice(7));\n'\ 5215 cpu = parseInt(name.s !! 4322 ' else if(name.match("CPU_OFF\[[0-9]*\]"))\n'\ 5216 var dmesg = document.getEleme !! 4323 ' cpu = parseInt(name.slice(8));\n'\ 5217 var dev = dmesg.getElementsBy !! 4324 ' var dmesg = document.getElementById("dmesg");\n'\ 5218 var idlist = []; !! 4325 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5219 var pdata = [[]]; !! 4326 ' var idlist = [];\n'\ 5220 if(document.getElementById("d !! 4327 ' var pdata = [[]];\n'\ 5221 pdata = [[], []]; !! 4328 ' if(document.getElementById("devicedetail1"))\n'\ 5222 var pd = pdata[0]; !! 4329 ' pdata = [[], []];\n'\ 5223 var total = [0.0, 0.0, 0.0]; !! 4330 ' var pd = pdata[0];\n'\ 5224 for (var i = 0; i < dev.lengt !! 4331 ' var total = [0.0, 0.0, 0.0];\n'\ 5225 dname = deviceName(de !! 4332 ' for (var i = 0; i < dev.length; i++) {\n'\ 5226 if((cpu >= 0 && dname !! 4333 ' dname = deviceName(dev[i].title);\n'\ 5227 (name == dnam !! 4334 ' if((cpu >= 0 && dname.match("CPU_O[NF]*\\\[*"+cpu+"\\\]")) ||\n'\ 5228 { !! 4335 ' (name == dname))\n'\ 5229 idlist[idlist !! 4336 ' {\n'\ 5230 var tidx = 1; !! 4337 ' idlist[idlist.length] = dev[i].id;\n'\ 5231 if(dev[i].id[ !! 4338 ' var tidx = 1;\n'\ 5232 pd = !! 4339 ' if(dev[i].id[0] == "a") {\n'\ 5233 } else { !! 4340 ' pd = pdata[0];\n'\ 5234 if(pd !! 4341 ' } else {\n'\ 5235 if(to !! 4342 ' if(pdata.length == 1) pdata[1] = [];\n'\ 5236 pd = !! 4343 ' if(total.length == 3) total[3]=total[4]=0.0;\n'\ 5237 tidx !! 4344 ' pd = pdata[1];\n'\ 5238 } !! 4345 ' tidx = 3;\n'\ 5239 var info = de !! 4346 ' }\n'\ 5240 var pname = i !! 4347 ' var info = dev[i].title.split(" ");\n'\ 5241 pd[pname] = p !! 4348 ' var pname = info[info.length-1];\n'\ 5242 total[0] += p !! 4349 ' pd[pname] = parseFloat(info[info.length-3].slice(1));\n'\ 5243 if(pname.inde !! 4350 ' total[0] += pd[pname];\n'\ 5244 total !! 4351 ' if(pname.indexOf("suspend") >= 0)\n'\ 5245 else !! 4352 ' total[tidx] += pd[pname];\n'\ 5246 total !! 4353 ' else\n'\ 5247 } !! 4354 ' total[tidx+1] += pd[pname];\n'\ 5248 } !! 4355 ' }\n'\ 5249 var devname = deviceTitle(thi !! 4356 ' }\n'\ 5250 var left = 0.0; !! 4357 ' var devname = deviceTitle(this.title, total, cpu);\n'\ 5251 for (var t = 0; t < pdata.len !! 4358 ' var left = 0.0;\n'\ 5252 pd = pdata[t]; !! 4359 ' for (var t = 0; t < pdata.length; t++) {\n'\ 5253 devinfo = document.ge !! 4360 ' pd = pdata[t];\n'\ 5254 var phases = devinfo. !! 4361 ' devinfo = document.getElementById("devicedetail"+t);\n'\ 5255 for (var i = 0; i < p !! 4362 ' var phases = devinfo.getElementsByClassName("phaselet");\n'\ 5256 if(phases[i]. !! 4363 ' for (var i = 0; i < phases.length; i++) {\n'\ 5257 var w !! 4364 ' if(phases[i].id in pd) {\n'\ 5258 var f !! 4365 ' var w = 100.0*pd[phases[i].id]/total[0];\n'\ 5259 if(w !! 4366 ' var fs = 32;\n'\ 5260 var f !! 4367 ' if(w < 8) fs = 4*w | 0;\n'\ 5261 phase !! 4368 ' var fs2 = fs*3/4;\n'\ 5262 phase !! 4369 ' phases[i].style.width = w+"%";\n'\ 5263 phase !! 4370 ' phases[i].style.left = left+"%";\n'\ 5264 left !! 4371 ' phases[i].title = phases[i].id+" "+pd[phases[i].id]+" ms";\n'\ 5265 var t !! 4372 ' left += w;\n'\ 5266 var p !! 4373 ' var time = "<t4 style=\\"font-size:"+fs+"px\\">"+pd[phases[i].id]+" ms<br></t4>";\n'\ 5267 phase !! 4374 ' var pname = "<t3 style=\\"font-size:"+fs2+"px\\">"+phases[i].id.replace(new RegExp("_", "g"), " ")+"</t3>";\n'\ 5268 } else { !! 4375 ' phases[i].innerHTML = time+pname;\n'\ 5269 phase !! 4376 ' } else {\n'\ 5270 phase !! 4377 ' phases[i].style.width = "0%";\n'\ 5271 } !! 4378 ' phases[i].style.left = left+"%";\n'\ 5272 } !! 4379 ' }\n'\ 5273 } !! 4380 ' }\n'\ 5274 if(typeof devstats !== 'undef !! 4381 ' }\n'\ 5275 callDetail(this.id, t !! 4382 ' if(typeof devstats !== \'undefined\')\n'\ 5276 var cglist = document.getElem !! 4383 ' callDetail(this.id, this.title);\n'\ 5277 if(!cglist) return; !! 4384 ' var cglist = document.getElementById("callgraphs");\n'\ 5278 var cg = cglist.getElementsBy !! 4385 ' if(!cglist) return;\n'\ 5279 if(cg.length < 10) return; !! 4386 ' var cg = cglist.getElementsByClassName("atop");\n'\ 5280 for (var i = 0; i < cg.length !! 4387 ' if(cg.length < 10) return;\n'\ 5281 cgid = cg[i].id.split !! 4388 ' for (var i = 0; i < cg.length; i++) {\n'\ 5282 if(idlist.indexOf(cgi !! 4389 ' cgid = cg[i].id.split("x")[0]\n'\ 5283 cg[i].style.d !! 4390 ' if(idlist.indexOf(cgid) >= 0) {\n'\ 5284 } else { !! 4391 ' cg[i].style.display = "block";\n'\ 5285 cg[i].style.d !! 4392 ' } else {\n'\ 5286 } !! 4393 ' cg[i].style.display = "none";\n'\ 5287 } !! 4394 ' }\n'\ 5288 } !! 4395 ' }\n'\ 5289 function callDetail(devid, devtitle) !! 4396 ' }\n'\ 5290 if(!(devid in devstats) || de !! 4397 ' function callDetail(devid, devtitle) {\n'\ 5291 return; !! 4398 ' if(!(devid in devstats) || devstats[devid].length < 1)\n'\ 5292 var list = devstats[devid]; !! 4399 ' return;\n'\ 5293 var tmp = devtitle.split(" ") !! 4400 ' var list = devstats[devid];\n'\ 5294 var name = tmp[0], phase = tm !! 4401 ' var tmp = devtitle.split(" ");\n'\ 5295 var dd = document.getElementB !! 4402 ' var name = tmp[0], phase = tmp[tmp.length-1];\n'\ 5296 var total = parseFloat(tmp[1] !! 4403 ' var dd = document.getElementById(phase);\n'\ 5297 var mlist = []; !! 4404 ' var total = parseFloat(tmp[1].slice(1));\n'\ 5298 var maxlen = 0; !! 4405 ' var mlist = [];\n'\ 5299 var info = [] !! 4406 ' var maxlen = 0;\n'\ 5300 for(var i in list) { !! 4407 ' var info = []\n'\ 5301 if(list[i][0] == "@") !! 4408 ' for(var i in list) {\n'\ 5302 info = list[i !! 4409 ' if(list[i][0] == "@") {\n'\ 5303 continue; !! 4410 ' info = list[i].split("|");\n'\ 5304 } !! 4411 ' continue;\n'\ 5305 var tmp = list[i].spl !! 4412 ' }\n'\ 5306 var t = parseFloat(tm !! 4413 ' var tmp = list[i].split("|");\n'\ 5307 var p = (t*100.0/tota !! 4414 ' var t = parseFloat(tmp[0]), f = tmp[1], c = parseInt(tmp[2]);\n'\ 5308 mlist[mlist.length] = !! 4415 ' var p = (t*100.0/total).toFixed(2);\n'\ 5309 if(f.length > maxlen) !! 4416 ' mlist[mlist.length] = [f, c, t.toFixed(2), p+"%"];\n'\ 5310 maxlen = f.le !! 4417 ' if(f.length > maxlen)\n'\ 5311 } !! 4418 ' maxlen = f.length;\n'\ 5312 var pad = 5; !! 4419 ' }\n'\ 5313 if(mlist.length == 0) pad = 3 !! 4420 ' var pad = 5;\n'\ 5314 var html = '<div style="paddi !! 4421 ' if(mlist.length == 0) pad = 30;\n'\ 5315 if(info.length > 2) !! 4422 ' var html = \'<div style="padding-top:\'+pad+\'px"><t3> <b>\'+name+\':</b>\';\n'\ 5316 html += " start=<b>"+ !! 4423 ' if(info.length > 2)\n'\ 5317 if(info.length > 3) !! 4424 ' html += " start=<b>"+info[1]+"</b>, end=<b>"+info[2]+"</b>";\n'\ 5318 html += ", length<i>( !! 4425 ' if(info.length > 3)\n'\ 5319 if(info.length > 4) !! 4426 ' html += ", length<i>(w/o overhead)</i>=<b>"+info[3]+" ms</b>";\n'\ 5320 html += ", return=<b> !! 4427 ' if(info.length > 4)\n'\ 5321 html += "</t3></div>"; !! 4428 ' html += ", return=<b>"+info[4]+"</b>";\n'\ 5322 if(mlist.length > 0) { !! 4429 ' html += "</t3></div>";\n'\ 5323 html += '<table class !! 4430 ' if(mlist.length > 0) {\n'\ 5324 for(var i in mlist) !! 4431 ' html += \'<table class=fstat style="padding-top:\'+(maxlen*5)+\'px;"><tr><th>Function</th>\';\n'\ 5325 html += "<td !! 4432 ' for(var i in mlist)\n'\ 5326 html += "</tr><tr><th !! 4433 ' html += "<td class=vt>"+mlist[i][0]+"</td>";\n'\ 5327 for(var i in mlist) !! 4434 ' html += "</tr><tr><th>Calls</th>";\n'\ 5328 html += "<td> !! 4435 ' for(var i in mlist)\n'\ 5329 html += "</tr><tr><th !! 4436 ' html += "<td>"+mlist[i][1]+"</td>";\n'\ 5330 for(var i in mlist) !! 4437 ' html += "</tr><tr><th>Time(ms)</th>";\n'\ 5331 html += "<td> !! 4438 ' for(var i in mlist)\n'\ 5332 html += "</tr><tr><th !! 4439 ' html += "<td>"+mlist[i][2]+"</td>";\n'\ 5333 for(var i in mlist) !! 4440 ' html += "</tr><tr><th>Percent</th>";\n'\ 5334 html += "<td> !! 4441 ' for(var i in mlist)\n'\ 5335 html += "</tr></table !! 4442 ' html += "<td>"+mlist[i][3]+"</td>";\n'\ 5336 } !! 4443 ' html += "</tr></table>";\n'\ 5337 dd.innerHTML = html; !! 4444 ' }\n'\ 5338 var height = (maxlen*5)+100; !! 4445 ' dd.innerHTML = html;\n'\ 5339 dd.style.height = height+"px" !! 4446 ' var height = (maxlen*5)+100;\n'\ 5340 document.getElementById("devi !! 4447 ' dd.style.height = height+"px";\n'\ 5341 } !! 4448 ' document.getElementById("devicedetail").style.height = height+"px";\n'\ 5342 function callSelect() { !! 4449 ' }\n'\ 5343 var cglist = document.getElem !! 4450 ' function callSelect() {\n'\ 5344 if(!cglist) return; !! 4451 ' var cglist = document.getElementById("callgraphs");\n'\ 5345 var cg = cglist.getElementsBy !! 4452 ' if(!cglist) return;\n'\ 5346 for (var i = 0; i < cg.length !! 4453 ' var cg = cglist.getElementsByClassName("atop");\n'\ 5347 if(this.id == cg[i].i !! 4454 ' for (var i = 0; i < cg.length; i++) {\n'\ 5348 cg[i].style.d !! 4455 ' if(this.id == cg[i].id) {\n'\ 5349 } else { !! 4456 ' cg[i].style.display = "block";\n'\ 5350 cg[i].style.d !! 4457 ' } else {\n'\ 5351 } !! 4458 ' cg[i].style.display = "none";\n'\ 5352 } !! 4459 ' }\n'\ 5353 } !! 4460 ' }\n'\ 5354 function devListWindow(e) { !! 4461 ' }\n'\ 5355 var win = window.open(); !! 4462 ' function devListWindow(e) {\n'\ 5356 var html = "<title>"+e.target !! 4463 ' var win = window.open();\n'\ 5357 "<style type=\"text/c !! 4464 ' var html = "<title>"+e.target.innerHTML+"</title>"+\n'\ 5358 " ul {list-style-ty !! 4465 ' "<style type=\\"text/css\\">"+\n'\ 5359 "</style>" !! 4466 ' " ul {list-style-type:circle;padding-left:10px;margin-left:10px;}"+\n'\ 5360 var dt = devtable[0]; !! 4467 ' "</style>"\n'\ 5361 if(e.target.id != "devlist1") !! 4468 ' var dt = devtable[0];\n'\ 5362 dt = devtable[1]; !! 4469 ' if(e.target.id != "devlist1")\n'\ 5363 win.document.write(html+dt); !! 4470 ' dt = devtable[1];\n'\ 5364 } !! 4471 ' win.document.write(html+dt);\n'\ 5365 function errWindow() { !! 4472 ' }\n'\ 5366 var range = this.id.split("_" !! 4473 ' function errWindow() {\n'\ 5367 var idx1 = parseInt(range[0]) !! 4474 ' var range = this.id.split("_");\n'\ 5368 var idx2 = parseInt(range[1]) !! 4475 ' var idx1 = parseInt(range[0]);\n'\ 5369 var win = window.open(); !! 4476 ' var idx2 = parseInt(range[1]);\n'\ 5370 var log = document.getElement !! 4477 ' var win = window.open();\n'\ 5371 var title = "<title>dmesg log !! 4478 ' var log = document.getElementById("dmesglog");\n'\ 5372 var text = log.innerHTML.spli !! 4479 ' var title = "<title>dmesg log</title>";\n'\ 5373 var html = ""; !! 4480 ' var text = log.innerHTML.split("\\n");\n'\ 5374 for(var i = 0; i < text.lengt !! 4481 ' var html = "";\n'\ 5375 if(i == idx1) { !! 4482 ' for(var i = 0; i < text.length; i++) {\n'\ 5376 html += "<e i !! 4483 ' if(i == idx1) {\n'\ 5377 } else if(i > idx1 && !! 4484 ' html += "<e id=target>"+text[i]+"</e>\\n";\n'\ 5378 html += "<e>" !! 4485 ' } else if(i > idx1 && i <= idx2) {\n'\ 5379 } else { !! 4486 ' html += "<e>"+text[i]+"</e>\\n";\n'\ 5380 html += text[ !! 4487 ' } else {\n'\ 5381 } !! 4488 ' html += text[i]+"\\n";\n'\ 5382 } !! 4489 ' }\n'\ 5383 win.document.write("<style>e{ !! 4490 ' }\n'\ 5384 win.location.hash = "#target" !! 4491 ' win.document.write("<style>e{color:red}</style>"+title+"<pre>"+html+"</pre>");\n'\ 5385 win.document.close(); !! 4492 ' win.location.hash = "#target";\n'\ 5386 } !! 4493 ' win.document.close();\n'\ 5387 function logWindow(e) { !! 4494 ' }\n'\ 5388 var name = e.target.id.slice( !! 4495 ' function logWindow(e) {\n'\ 5389 var win = window.open(); !! 4496 ' var name = e.target.id.slice(4);\n'\ 5390 var log = document.getElement !! 4497 ' var win = window.open();\n'\ 5391 var title = "<title>"+documen !! 4498 ' var log = document.getElementById(name+"log");\n'\ 5392 win.document.write(title+"<pr !! 4499 ' var title = "<title>"+document.title.split(" ")[0]+" "+name+" log</title>";\n'\ 5393 win.document.close(); !! 4500 ' win.document.write(title+"<pre>"+log.innerHTML+"</pre>");\n'\ 5394 } !! 4501 ' win.document.close();\n'\ 5395 function onMouseDown(e) { !! 4502 ' }\n'\ 5396 dragval[0] = e.clientX; !! 4503 ' function onMouseDown(e) {\n'\ 5397 dragval[1] = document.getElem !! 4504 ' dragval[0] = e.clientX;\n'\ 5398 document.onmousemove = onMous !! 4505 ' dragval[1] = document.getElementById("dmesgzoombox").scrollLeft;\n'\ 5399 } !! 4506 ' document.onmousemove = onMouseMove;\n'\ 5400 function onMouseMove(e) { !! 4507 ' }\n'\ 5401 var zoombox = document.getEle !! 4508 ' function onMouseMove(e) {\n'\ 5402 zoombox.scrollLeft = dragval[ !! 4509 ' var zoombox = document.getElementById("dmesgzoombox");\n'\ 5403 } !! 4510 ' zoombox.scrollLeft = dragval[1] + dragval[0] - e.clientX;\n'\ 5404 function onMouseUp(e) { !! 4511 ' }\n'\ 5405 document.onmousemove = null; !! 4512 ' function onMouseUp(e) {\n'\ 5406 } !! 4513 ' document.onmousemove = null;\n'\ 5407 function onKeyPress(e) { !! 4514 ' }\n'\ 5408 var c = e.charCode; !! 4515 ' function onKeyPress(e) {\n'\ 5409 if(c != 42 && c != 43 && c != !! 4516 ' var c = e.charCode;\n'\ 5410 var click = document.createEv !! 4517 ' if(c != 42 && c != 43 && c != 45) return;\n'\ 5411 click.initEvent("click", true !! 4518 ' var click = document.createEvent("Events");\n'\ 5412 if(c == 43) !! 4519 ' click.initEvent("click", true, false);\n'\ 5413 document.getElementBy !! 4520 ' if(c == 43) \n'\ 5414 else if(c == 45) !! 4521 ' document.getElementById("zoomin").dispatchEvent(click);\n'\ 5415 document.getElementBy !! 4522 ' else if(c == 45)\n'\ 5416 else if(c == 42) !! 4523 ' document.getElementById("zoomout").dispatchEvent(click);\n'\ 5417 document.getElementBy !! 4524 ' else if(c == 42)\n'\ 5418 } !! 4525 ' document.getElementById("zoomdef").dispatchEvent(click);\n'\ 5419 window.addEventListener("resize", fun !! 4526 ' }\n'\ 5420 window.addEventListener("load", funct !! 4527 ' window.addEventListener("resize", function () {zoomTimeline();});\n'\ 5421 var dmesg = document.getEleme !! 4528 ' window.addEventListener("load", function () {\n'\ 5422 dmesg.style.width = "100%" !! 4529 ' var dmesg = document.getElementById("dmesg");\n'\ 5423 dmesg.onmousedown = onMouseDo !! 4530 ' dmesg.style.width = "100%"\n'\ 5424 document.onmouseup = onMouseU !! 4531 ' dmesg.onmousedown = onMouseDown;\n'\ 5425 document.onkeypress = onKeyPr !! 4532 ' document.onmouseup = onMouseUp;\n'\ 5426 document.getElementById("zoom !! 4533 ' document.onkeypress = onKeyPress;\n'\ 5427 document.getElementById("zoom !! 4534 ' document.getElementById("zoomin").onclick = zoomTimeline;\n'\ 5428 document.getElementById("zoom !! 4535 ' document.getElementById("zoomout").onclick = zoomTimeline;\n'\ 5429 var list = document.getElemen !! 4536 ' document.getElementById("zoomdef").onclick = zoomTimeline;\n'\ 5430 for (var i = 0; i < list.leng !! 4537 ' var list = document.getElementsByClassName("err");\n'\ 5431 list[i].onclick = err !! 4538 ' for (var i = 0; i < list.length; i++)\n'\ 5432 var list = document.getElemen !! 4539 ' list[i].onclick = errWindow;\n'\ 5433 for (var i = 0; i < list.leng !! 4540 ' var list = document.getElementsByClassName("logbtn");\n'\ 5434 list[i].onclick = log !! 4541 ' for (var i = 0; i < list.length; i++)\n'\ 5435 list = document.getElementsBy !! 4542 ' list[i].onclick = logWindow;\n'\ 5436 for (var i = 0; i < list.leng !! 4543 ' list = document.getElementsByClassName("devlist");\n'\ 5437 list[i].onclick = dev !! 4544 ' for (var i = 0; i < list.length; i++)\n'\ 5438 var dev = dmesg.getElementsBy !! 4545 ' list[i].onclick = devListWindow;\n'\ 5439 for (var i = 0; i < dev.lengt !! 4546 ' var dev = dmesg.getElementsByClassName("thread");\n'\ 5440 dev[i].onclick = devi !! 4547 ' for (var i = 0; i < dev.length; i++) {\n'\ 5441 dev[i].onmouseover = !! 4548 ' dev[i].onclick = deviceDetail;\n'\ 5442 dev[i].onmouseout = d !! 4549 ' dev[i].onmouseover = deviceHover;\n'\ 5443 } !! 4550 ' dev[i].onmouseout = deviceUnhover;\n'\ 5444 var dev = dmesg.getElementsBy !! 4551 ' }\n'\ 5445 for (var i = 0; i < dev.lengt !! 4552 ' var dev = dmesg.getElementsByClassName("srccall");\n'\ 5446 dev[i].onclick = call !! 4553 ' for (var i = 0; i < dev.length; i++)\n'\ 5447 zoomTimeline(); !! 4554 ' dev[i].onclick = callSelect;\n'\ 5448 }); !! 4555 ' zoomTimeline();\n'\ 5449 </script> """ !! 4556 ' });\n'\ >> 4557 '</script>\n' 5450 hf.write(script_code); 4558 hf.write(script_code); 5451 4559 >> 4560 def setRuntimeSuspend(before=True): >> 4561 global sysvals >> 4562 sv = sysvals >> 4563 if sv.rs == 0: >> 4564 return >> 4565 if before: >> 4566 # runtime suspend disable or enable >> 4567 if sv.rs > 0: >> 4568 sv.rstgt, sv.rsval, sv.rsdir = 'on', 'auto', 'enabled' >> 4569 else: >> 4570 sv.rstgt, sv.rsval, sv.rsdir = 'auto', 'on', 'disabled' >> 4571 pprint('CONFIGURING RUNTIME SUSPEND...') >> 4572 sv.rslist = deviceInfo(sv.rstgt) >> 4573 for i in sv.rslist: >> 4574 sv.setVal(sv.rsval, i) >> 4575 pprint('runtime suspend %s on all devices (%d changed)' % (sv.rsdir, len(sv.rslist))) >> 4576 pprint('waiting 5 seconds...') >> 4577 time.sleep(5) >> 4578 else: >> 4579 # runtime suspend re-enable or re-disable >> 4580 for i in sv.rslist: >> 4581 sv.setVal(sv.rstgt, i) >> 4582 pprint('runtime suspend settings restored on %d devices' % len(sv.rslist)) >> 4583 5452 # Function: executeSuspend 4584 # Function: executeSuspend 5453 # Description: 4585 # Description: 5454 # Execute system suspend through the s 4586 # Execute system suspend through the sysfs interface, then copy the output 5455 # dmesg and ftrace files to the test o 4587 # dmesg and ftrace files to the test output directory. 5456 def executeSuspend(quiet=False): !! 4588 def executeSuspend(): 5457 sv, tp, pm = sysvals, sysvals.tpath, !! 4589 pm = ProcessMonitor() 5458 if sv.wifi: !! 4590 tp = sysvals.tpath 5459 wifi = sv.checkWifi() << 5460 sv.dlog('wifi check, connecte << 5461 testdata = [] 4591 testdata = [] >> 4592 battery = True if getBattery() else False 5462 # run these commands to prepare the s 4593 # run these commands to prepare the system for suspend 5463 if sv.display: !! 4594 if sysvals.display: 5464 if not quiet: !! 4595 pprint('SET DISPLAY TO %s' % sysvals.display.upper()) 5465 pprint('SET DISPLAY T !! 4596 displayControl(sysvals.display) 5466 ret = sv.displayControl(sv.di << 5467 sv.dlog('xset display %s, ret << 5468 time.sleep(1) 4597 time.sleep(1) 5469 if sv.sync: !! 4598 if sysvals.sync: 5470 if not quiet: !! 4599 pprint('SYNCING FILESYSTEMS') 5471 pprint('SYNCING FILES << 5472 sv.dlog('syncing filesystems' << 5473 call('sync', shell=True) 4600 call('sync', shell=True) 5474 sv.dlog('read dmesg') !! 4601 # mark the start point in the kernel ring buffer just as we start 5475 sv.initdmesg() !! 4602 sysvals.initdmesg() 5476 sv.dlog('cmdinfo before') !! 4603 # start ftrace 5477 sv.cmdinfo(True) !! 4604 if(sysvals.usecallgraph or sysvals.usetraceevents): 5478 sv.start(pm) !! 4605 pprint('START TRACING') >> 4606 sysvals.fsetVal('1', 'tracing_on') >> 4607 if sysvals.useprocmon: >> 4608 pm.start() 5479 # execute however many s/r runs reque 4609 # execute however many s/r runs requested 5480 for count in range(1,sv.execcount+1): !! 4610 for count in range(1,sysvals.execcount+1): 5481 # x2delay in between test run 4611 # x2delay in between test runs 5482 if(count > 1 and sv.x2delay > !! 4612 if(count > 1 and sysvals.x2delay > 0): 5483 sv.fsetVal('WAIT %d' !! 4613 sysvals.fsetVal('WAIT %d' % sysvals.x2delay, 'trace_marker') 5484 time.sleep(sv.x2delay !! 4614 time.sleep(sysvals.x2delay/1000.0) 5485 sv.fsetVal('WAIT END' !! 4615 sysvals.fsetVal('WAIT END', 'trace_marker') 5486 # start message 4616 # start message 5487 if sv.testcommand != '': !! 4617 if sysvals.testcommand != '': 5488 pprint('COMMAND START 4618 pprint('COMMAND START') 5489 else: 4619 else: 5490 if(sv.rtcwake): !! 4620 if(sysvals.rtcwake): 5491 pprint('SUSPE 4621 pprint('SUSPEND START') 5492 else: 4622 else: 5493 pprint('SUSPE 4623 pprint('SUSPEND START (press a key to resume)') >> 4624 bat1 = getBattery() if battery else False 5494 # set rtcwake 4625 # set rtcwake 5495 if(sv.rtcwake): !! 4626 if(sysvals.rtcwake): 5496 if not quiet: !! 4627 pprint('will issue an rtcwake in %d seconds' % sysvals.rtcwaketime) 5497 pprint('will !! 4628 sysvals.rtcWakeAlarmOn() 5498 sv.dlog('enable RTC w << 5499 sv.rtcWakeAlarmOn() << 5500 # start of suspend trace mark 4629 # start of suspend trace marker 5501 sv.fsetVal(datetime.now().str !! 4630 if(sysvals.usecallgraph or sysvals.usetraceevents): >> 4631 sysvals.fsetVal('SUSPEND START', 'trace_marker') 5502 # predelay delay 4632 # predelay delay 5503 if(count == 1 and sv.predelay !! 4633 if(count == 1 and sysvals.predelay > 0): 5504 sv.fsetVal('WAIT %d' !! 4634 sysvals.fsetVal('WAIT %d' % sysvals.predelay, 'trace_marker') 5505 time.sleep(sv.predela !! 4635 time.sleep(sysvals.predelay/1000.0) 5506 sv.fsetVal('WAIT END' !! 4636 sysvals.fsetVal('WAIT END', 'trace_marker') 5507 # initiate suspend or command 4637 # initiate suspend or command 5508 sv.dlog('system executing a s << 5509 tdata = {'error': ''} 4638 tdata = {'error': ''} 5510 if sv.testcommand != '': !! 4639 if sysvals.testcommand != '': 5511 res = call(sv.testcom !! 4640 res = call(sysvals.testcommand+' 2>&1', shell=True); 5512 if res != 0: 4641 if res != 0: 5513 tdata['error' 4642 tdata['error'] = 'cmd returned %d' % res 5514 else: 4643 else: 5515 s0ixready = sv.s0ixSu !! 4644 mode = sysvals.suspendmode 5516 mode = sv.suspendmode !! 4645 if sysvals.memmode and os.path.exists(sysvals.mempowerfile): 5517 if sv.memmode and os. << 5518 mode = 'mem' 4646 mode = 'mem' 5519 sv.testVal(sv !! 4647 pf = open(sysvals.mempowerfile, 'w') 5520 if sv.diskmode and os !! 4648 pf.write(sysvals.memmode) >> 4649 pf.close() >> 4650 if sysvals.diskmode and os.path.exists(sysvals.diskpowerfile): 5521 mode = 'disk' 4651 mode = 'disk' 5522 sv.testVal(sv !! 4652 pf = open(sysvals.diskpowerfile, 'w') 5523 if sv.acpidebug: !! 4653 pf.write(sysvals.diskmode) 5524 sv.testVal(sv !! 4654 pf.close() 5525 if ((mode == 'freeze' !! 4655 pf = open(sysvals.powerfile, 'w') 5526 and sv.haveTu !! 4656 pf.write(mode) 5527 # execution w !! 4657 # execution will pause here 5528 retval, turbo !! 4658 try: 5529 if retval != !! 4659 pf.close() 5530 tdata !! 4660 except Exception as e: 5531 if turbo: !! 4661 tdata['error'] = str(e) 5532 tdata !! 4662 if(sysvals.rtcwake): 5533 else: !! 4663 sysvals.rtcWakeAlarmOff() 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 4664 # postdelay delay 5550 if(count == sv.execcount and !! 4665 if(count == sysvals.execcount and sysvals.postdelay > 0): 5551 sv.fsetVal('WAIT %d' !! 4666 sysvals.fsetVal('WAIT %d' % sysvals.postdelay, 'trace_marker') 5552 time.sleep(sv.postdel !! 4667 time.sleep(sysvals.postdelay/1000.0) 5553 sv.fsetVal('WAIT END' !! 4668 sysvals.fsetVal('WAIT END', 'trace_marker') 5554 # return from suspend 4669 # return from suspend 5555 pprint('RESUME COMPLETE') 4670 pprint('RESUME COMPLETE') 5556 if(count < sv.execcount): !! 4671 if(sysvals.usecallgraph or sysvals.usetraceevents): 5557 sv.fsetVal(datetime.n !! 4672 sysvals.fsetVal('RESUME COMPLETE', 'trace_marker') 5558 elif(not sv.wifitrace): !! 4673 if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'): 5559 sv.fsetVal(datetime.n << 5560 sv.stop(pm) << 5561 if sv.wifi and wifi: << 5562 tdata['wifi'] = sv.po << 5563 sv.dlog('wifi check, << 5564 if(count == sv.execcount and << 5565 sv.fsetVal(datetime.n << 5566 sv.stop(pm) << 5567 if sv.netfix: << 5568 tdata['netfix'] = sv. << 5569 sv.dlog('netfix, %s' << 5570 if(sv.suspendmode == 'mem' or << 5571 sv.dlog('read the ACP << 5572 tdata['fw'] = getFPDT 4674 tdata['fw'] = getFPDT(False) >> 4675 bat2 = getBattery() if battery else False >> 4676 if battery and bat1 and bat2: >> 4677 tdata['bat'] = (bat1, bat2) 5573 testdata.append(tdata) 4678 testdata.append(tdata) 5574 sv.dlog('cmdinfo after') !! 4679 # stop ftrace 5575 cmdafter = sv.cmdinfo(False) !! 4680 if(sysvals.usecallgraph or sysvals.usetraceevents): >> 4681 if sysvals.useprocmon: >> 4682 pm.stop() >> 4683 sysvals.fsetVal('0', 'tracing_on') 5576 # grab a copy of the dmesg output 4684 # grab a copy of the dmesg output 5577 if not quiet: !! 4685 pprint('CAPTURING DMESG') 5578 pprint('CAPTURING DMESG') !! 4686 sysvals.getdmesg(testdata) 5579 sv.getdmesg(testdata) << 5580 # grab a copy of the ftrace output 4687 # grab a copy of the ftrace output 5581 if sv.useftrace: !! 4688 if(sysvals.usecallgraph or sysvals.usetraceevents): 5582 if not quiet: !! 4689 pprint('CAPTURING TRACE') 5583 pprint('CAPTURING TRA !! 4690 op = sysvals.writeDatafileHeader(sysvals.ftracefile, testdata) 5584 op = sv.writeDatafileHeader(s !! 4691 fp = open(tp+'trace', 'r') 5585 fp = open(tp+'trace', 'rb') !! 4692 for line in fp: 5586 op.write(ascii(fp.read())) !! 4693 op.write(line) 5587 op.close() 4694 op.close() 5588 sv.fsetVal('', 'trace') !! 4695 sysvals.fsetVal('', 'trace') 5589 sv.platforminfo(cmdafter) !! 4696 devProps() 5590 4697 5591 def readFile(file): 4698 def readFile(file): 5592 if os.path.islink(file): 4699 if os.path.islink(file): 5593 return os.readlink(file).spli 4700 return os.readlink(file).split('/')[-1] 5594 else: 4701 else: 5595 return sysvals.getVal(file).s 4702 return sysvals.getVal(file).strip() 5596 4703 5597 # Function: ms2nice 4704 # Function: ms2nice 5598 # Description: 4705 # Description: 5599 # Print out a very concise time string 4706 # Print out a very concise time string in minutes and seconds 5600 # Output: 4707 # Output: 5601 # The time string, e.g. "1901m16s" 4708 # The time string, e.g. "1901m16s" 5602 def ms2nice(val): 4709 def ms2nice(val): 5603 val = int(val) 4710 val = int(val) 5604 h = val // 3600000 !! 4711 h = val / 3600000 5605 m = (val // 60000) % 60 !! 4712 m = (val / 60000) % 60 5606 s = (val // 1000) % 60 !! 4713 s = (val / 1000) % 60 5607 if h > 0: 4714 if h > 0: 5608 return '%d:%02d:%02d' % (h, m 4715 return '%d:%02d:%02d' % (h, m, s) 5609 if m > 0: 4716 if m > 0: 5610 return '%02d:%02d' % (m, s) 4717 return '%02d:%02d' % (m, s) 5611 return '%ds' % s 4718 return '%ds' % s 5612 4719 5613 def yesno(val): 4720 def yesno(val): 5614 list = {'enabled':'A', 'disabled':'S' 4721 list = {'enabled':'A', 'disabled':'S', 'auto':'E', 'on':'D', 5615 'active':'A', 'suspended':'S' 4722 'active':'A', 'suspended':'S', 'suspending':'S'} 5616 if val not in list: 4723 if val not in list: 5617 return ' ' 4724 return ' ' 5618 return list[val] 4725 return list[val] 5619 4726 5620 # Function: deviceInfo 4727 # Function: deviceInfo 5621 # Description: 4728 # Description: 5622 # Detect all the USB hosts and devices 4729 # Detect all the USB hosts and devices currently connected and add 5623 # a list of USB device names to sysval 4730 # a list of USB device names to sysvals for better timeline readability 5624 def deviceInfo(output=''): 4731 def deviceInfo(output=''): 5625 if not output: 4732 if not output: 5626 pprint('LEGEND\n'\ 4733 pprint('LEGEND\n'\ 5627 '---------------------------- 4734 '---------------------------------------------------------------------------------------------\n'\ 5628 ' A = async/sync PM queue (A 4735 ' A = async/sync PM queue (A/S) C = runtime active children\n'\ 5629 ' R = runtime suspend enable 4736 ' R = runtime suspend enabled/disabled (E/D) rACTIVE = runtime active (min/sec)\n'\ 5630 ' S = runtime status active/ 4737 ' S = runtime status active/suspended (A/S) rSUSPEND = runtime suspend (min/sec)\n'\ 5631 ' U = runtime usage count\n' 4738 ' U = runtime usage count\n'\ 5632 '---------------------------- 4739 '---------------------------------------------------------------------------------------------\n'\ 5633 'DEVICE N 4740 'DEVICE NAME A R S U C rACTIVE rSUSPEND\n'\ 5634 '---------------------------- 4741 '---------------------------------------------------------------------------------------------') 5635 4742 5636 res = [] 4743 res = [] 5637 tgtval = 'runtime_status' 4744 tgtval = 'runtime_status' 5638 lines = dict() 4745 lines = dict() 5639 for dirname, dirnames, filenames in o 4746 for dirname, dirnames, filenames in os.walk('/sys/devices'): 5640 if(not re.match(r'.*/power', !! 4747 if(not re.match('.*/power', dirname) or 5641 'control' not in file 4748 'control' not in filenames or 5642 tgtval not in filenam 4749 tgtval not in filenames): 5643 continue 4750 continue 5644 name = '' 4751 name = '' 5645 dirname = dirname[:-6] 4752 dirname = dirname[:-6] 5646 device = dirname.split('/')[- 4753 device = dirname.split('/')[-1] 5647 power = dict() 4754 power = dict() 5648 power[tgtval] = readFile('%s/ 4755 power[tgtval] = readFile('%s/power/%s' % (dirname, tgtval)) 5649 # only list devices which sup 4756 # only list devices which support runtime suspend 5650 if power[tgtval] not in ['act 4757 if power[tgtval] not in ['active', 'suspended', 'suspending']: 5651 continue 4758 continue 5652 for i in ['product', 'driver' 4759 for i in ['product', 'driver', 'subsystem']: 5653 file = '%s/%s' % (dir 4760 file = '%s/%s' % (dirname, i) 5654 if os.path.exists(fil 4761 if os.path.exists(file): 5655 name = readFi 4762 name = readFile(file) 5656 break 4763 break 5657 for i in ['async', 'control', 4764 for i in ['async', 'control', 'runtime_status', 'runtime_usage', 5658 'runtime_active_kids' 4765 'runtime_active_kids', 'runtime_active_time', 5659 'runtime_suspended_ti 4766 'runtime_suspended_time']: 5660 if i in filenames: 4767 if i in filenames: 5661 power[i] = re 4768 power[i] = readFile('%s/power/%s' % (dirname, i)) 5662 if output: 4769 if output: 5663 if power['control'] = 4770 if power['control'] == output: 5664 res.append('% 4771 res.append('%s/power/control' % dirname) 5665 continue 4772 continue 5666 lines[dirname] = '%-26s %-26s 4773 lines[dirname] = '%-26s %-26s %1s %1s %1s %1s %1s %10s %10s' % \ 5667 (device[:26], name[:2 4774 (device[:26], name[:26], 5668 yesno(power['async']) 4775 yesno(power['async']), \ 5669 yesno(power['control' 4776 yesno(power['control']), \ 5670 yesno(power['runtime_ 4777 yesno(power['runtime_status']), \ 5671 power['runtime_usage' 4778 power['runtime_usage'], \ 5672 power['runtime_active 4779 power['runtime_active_kids'], \ 5673 ms2nice(power['runtim 4780 ms2nice(power['runtime_active_time']), \ 5674 ms2nice(power['runtim 4781 ms2nice(power['runtime_suspended_time'])) 5675 for i in sorted(lines): 4782 for i in sorted(lines): 5676 print(lines[i]) !! 4783 print lines[i] 5677 return res 4784 return res 5678 4785 >> 4786 # Function: devProps >> 4787 # Description: >> 4788 # Retrieve a list of properties for all devices in the trace log >> 4789 def devProps(data=0): >> 4790 props = dict() >> 4791 >> 4792 if data: >> 4793 idx = data.index(': ') + 2 >> 4794 if idx >= len(data): >> 4795 return >> 4796 devlist = data[idx:].split(';') >> 4797 for dev in devlist: >> 4798 f = dev.split(',') >> 4799 if len(f) < 3: >> 4800 continue >> 4801 dev = f[0] >> 4802 props[dev] = DevProps() >> 4803 props[dev].altname = f[1] >> 4804 if int(f[2]): >> 4805 props[dev].async = True >> 4806 else: >> 4807 props[dev].async = False >> 4808 sysvals.devprops = props >> 4809 if sysvals.suspendmode == 'command' and 'testcommandstring' in props: >> 4810 sysvals.testcommand = props['testcommandstring'].altname >> 4811 return >> 4812 >> 4813 if(os.path.exists(sysvals.ftracefile) == False): >> 4814 doError('%s does not exist' % sysvals.ftracefile) >> 4815 >> 4816 # first get the list of devices we need properties for >> 4817 msghead = 'Additional data added by AnalyzeSuspend' >> 4818 alreadystamped = False >> 4819 tp = TestProps() >> 4820 tf = sysvals.openlog(sysvals.ftracefile, 'r') >> 4821 for line in tf: >> 4822 if msghead in line: >> 4823 alreadystamped = True >> 4824 continue >> 4825 # determine the trace data type (required for further parsing) >> 4826 m = re.match(tp.tracertypefmt, line) >> 4827 if(m): >> 4828 tp.setTracerType(m.group('t')) >> 4829 continue >> 4830 # parse only valid lines, if this is not one move on >> 4831 m = re.match(tp.ftrace_line_fmt, line) >> 4832 if(not m or 'device_pm_callback_start' not in line): >> 4833 continue >> 4834 m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg')); >> 4835 if(not m): >> 4836 continue >> 4837 dev = m.group('d') >> 4838 if dev not in props: >> 4839 props[dev] = DevProps() >> 4840 tf.close() >> 4841 >> 4842 if not alreadystamped and sysvals.suspendmode == 'command': >> 4843 out = '#\n# '+msghead+'\n# Device Properties: ' >> 4844 out += 'testcommandstring,%s,0;' % (sysvals.testcommand) >> 4845 with sysvals.openlog(sysvals.ftracefile, 'a') as fp: >> 4846 fp.write(out+'\n') >> 4847 sysvals.devprops = props >> 4848 return >> 4849 >> 4850 # now get the syspath for each of our target devices >> 4851 for dirname, dirnames, filenames in os.walk('/sys/devices'): >> 4852 if(re.match('.*/power', dirname) and 'async' in filenames): >> 4853 dev = dirname.split('/')[-2] >> 4854 if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)): >> 4855 props[dev].syspath = dirname[:-6] >> 4856 >> 4857 # now fill in the properties for our target devices >> 4858 for dev in props: >> 4859 dirname = props[dev].syspath >> 4860 if not dirname or not os.path.exists(dirname): >> 4861 continue >> 4862 with open(dirname+'/power/async') as fp: >> 4863 text = fp.read() >> 4864 props[dev].async = False >> 4865 if 'enabled' in text: >> 4866 props[dev].async = True >> 4867 fields = os.listdir(dirname) >> 4868 if 'product' in fields: >> 4869 with open(dirname+'/product') as fp: >> 4870 props[dev].altname = fp.read() >> 4871 elif 'name' in fields: >> 4872 with open(dirname+'/name') as fp: >> 4873 props[dev].altname = fp.read() >> 4874 elif 'model' in fields: >> 4875 with open(dirname+'/model') as fp: >> 4876 props[dev].altname = fp.read() >> 4877 elif 'description' in fields: >> 4878 with open(dirname+'/description') as fp: >> 4879 props[dev].altname = fp.read() >> 4880 elif 'id' in fields: >> 4881 with open(dirname+'/id') as fp: >> 4882 props[dev].altname = fp.read() >> 4883 elif 'idVendor' in fields and 'idProduct' in fields: >> 4884 idv, idp = '', '' >> 4885 with open(dirname+'/idVendor') as fp: >> 4886 idv = fp.read().strip() >> 4887 with open(dirname+'/idProduct') as fp: >> 4888 idp = fp.read().strip() >> 4889 props[dev].altname = '%s:%s' % (idv, idp) >> 4890 >> 4891 if props[dev].altname: >> 4892 out = props[dev].altname.strip().replace('\n', ' ') >> 4893 out = out.replace(',', ' ') >> 4894 out = out.replace(';', ' ') >> 4895 props[dev].altname = out >> 4896 >> 4897 # and now write the data to the ftrace file >> 4898 if not alreadystamped: >> 4899 out = '#\n# '+msghead+'\n# Device Properties: ' >> 4900 for dev in sorted(props): >> 4901 out += props[dev].out(dev) >> 4902 with sysvals.openlog(sysvals.ftracefile, 'a') as fp: >> 4903 fp.write(out+'\n') >> 4904 >> 4905 sysvals.devprops = props >> 4906 5679 # Function: getModes 4907 # Function: getModes 5680 # Description: 4908 # Description: 5681 # Determine the supported power modes 4909 # Determine the supported power modes on this system 5682 # Output: 4910 # Output: 5683 # A string list of the available modes 4911 # A string list of the available modes 5684 def getModes(): 4912 def getModes(): 5685 modes = [] 4913 modes = [] 5686 if(os.path.exists(sysvals.powerfile)) 4914 if(os.path.exists(sysvals.powerfile)): 5687 fp = open(sysvals.powerfile, 4915 fp = open(sysvals.powerfile, 'r') 5688 modes = fp.read().split() !! 4916 modes = string.split(fp.read()) 5689 fp.close() 4917 fp.close() 5690 if(os.path.exists(sysvals.mempowerfil 4918 if(os.path.exists(sysvals.mempowerfile)): 5691 deep = False 4919 deep = False 5692 fp = open(sysvals.mempowerfil 4920 fp = open(sysvals.mempowerfile, 'r') 5693 for m in fp.read().split(): !! 4921 for m in string.split(fp.read()): 5694 memmode = m.strip('[] 4922 memmode = m.strip('[]') 5695 if memmode == 'deep': 4923 if memmode == 'deep': 5696 deep = True 4924 deep = True 5697 else: 4925 else: 5698 modes.append( 4926 modes.append('mem-%s' % memmode) 5699 fp.close() 4927 fp.close() 5700 if 'mem' in modes and not dee 4928 if 'mem' in modes and not deep: 5701 modes.remove('mem') 4929 modes.remove('mem') 5702 if('disk' in modes and os.path.exists 4930 if('disk' in modes and os.path.exists(sysvals.diskpowerfile)): 5703 fp = open(sysvals.diskpowerfi 4931 fp = open(sysvals.diskpowerfile, 'r') 5704 for m in fp.read().split(): !! 4932 for m in string.split(fp.read()): 5705 modes.append('disk-%s 4933 modes.append('disk-%s' % m.strip('[]')) 5706 fp.close() 4934 fp.close() 5707 return modes 4935 return modes 5708 4936 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 4937 # Function: dmidecode 5744 # Description: 4938 # Description: 5745 # Read the bios tables and pull out sy 4939 # Read the bios tables and pull out system info 5746 # Arguments: 4940 # Arguments: 5747 # mempath: /dev/mem or custom mem path 4941 # mempath: /dev/mem or custom mem path 5748 # fatal: True to exit on error, False 4942 # fatal: True to exit on error, False to return empty dict 5749 # Output: 4943 # Output: 5750 # A dict object with all available key 4944 # A dict object with all available key/values 5751 def dmidecode(mempath, fatal=False): 4945 def dmidecode(mempath, fatal=False): 5752 out = dict() 4946 out = dict() 5753 if(not (os.path.exists(mempath) and o << 5754 return dmidecode_backup(out, << 5755 4947 5756 # the list of values to retrieve, wit 4948 # the list of values to retrieve, with hardcoded (type, idx) 5757 info = { 4949 info = { 5758 'bios-vendor': (0, 4), 4950 'bios-vendor': (0, 4), 5759 'bios-version': (0, 5), 4951 'bios-version': (0, 5), 5760 'bios-release-date': (0, 8), 4952 'bios-release-date': (0, 8), 5761 'system-manufacturer': (1, 4) 4953 'system-manufacturer': (1, 4), 5762 'system-product-name': (1, 5) 4954 'system-product-name': (1, 5), 5763 'system-version': (1, 6), 4955 'system-version': (1, 6), 5764 'system-serial-number': (1, 7 4956 'system-serial-number': (1, 7), 5765 'baseboard-manufacturer': (2, 4957 'baseboard-manufacturer': (2, 4), 5766 'baseboard-product-name': (2, 4958 'baseboard-product-name': (2, 5), 5767 'baseboard-version': (2, 6), 4959 'baseboard-version': (2, 6), 5768 'baseboard-serial-number': (2 4960 'baseboard-serial-number': (2, 7), 5769 'chassis-manufacturer': (3, 4 4961 'chassis-manufacturer': (3, 4), >> 4962 'chassis-type': (3, 5), 5770 'chassis-version': (3, 6), 4963 'chassis-version': (3, 6), 5771 'chassis-serial-number': (3, 4964 'chassis-serial-number': (3, 7), 5772 'processor-manufacturer': (4, 4965 'processor-manufacturer': (4, 7), 5773 'processor-version': (4, 16), 4966 'processor-version': (4, 16), 5774 } 4967 } >> 4968 if(not os.path.exists(mempath)): >> 4969 if(fatal): >> 4970 doError('file does not exist: %s' % mempath) >> 4971 return out >> 4972 if(not os.access(mempath, os.R_OK)): >> 4973 if(fatal): >> 4974 doError('file is not readable: %s' % mempath) >> 4975 return out 5775 4976 5776 # by default use legacy scan, but try 4977 # by default use legacy scan, but try to use EFI first 5777 memaddr, memsize = 0xf0000, 0x10000 !! 4978 memaddr = 0xf0000 >> 4979 memsize = 0x10000 5778 for ep in ['/sys/firmware/efi/systab' 4980 for ep in ['/sys/firmware/efi/systab', '/proc/efi/systab']: 5779 if not os.path.exists(ep) or 4981 if not os.path.exists(ep) or not os.access(ep, os.R_OK): 5780 continue 4982 continue 5781 fp = open(ep, 'r') 4983 fp = open(ep, 'r') 5782 buf = fp.read() 4984 buf = fp.read() 5783 fp.close() 4985 fp.close() 5784 i = buf.find('SMBIOS=') 4986 i = buf.find('SMBIOS=') 5785 if i >= 0: 4987 if i >= 0: 5786 try: 4988 try: 5787 memaddr = int 4989 memaddr = int(buf[i+7:], 16) 5788 memsize = 0x2 4990 memsize = 0x20 5789 except: 4991 except: 5790 continue 4992 continue 5791 4993 5792 # read in the memory for scanning 4994 # read in the memory for scanning >> 4995 fp = open(mempath, 'rb') 5793 try: 4996 try: 5794 fp = open(mempath, 'rb') << 5795 fp.seek(memaddr) 4997 fp.seek(memaddr) 5796 buf = fp.read(memsize) 4998 buf = fp.read(memsize) 5797 except: 4999 except: 5798 return dmidecode_backup(out, !! 5000 if(fatal): >> 5001 doError('DMI table is unreachable, sorry') >> 5002 else: >> 5003 return out 5799 fp.close() 5004 fp.close() 5800 5005 5801 # search for either an SM table or DM 5006 # search for either an SM table or DMI table 5802 i = base = length = num = 0 5007 i = base = length = num = 0 5803 while(i < memsize): 5008 while(i < memsize): 5804 if buf[i:i+4] == b'_SM_' and !! 5009 if buf[i:i+4] == '_SM_' and i < memsize - 16: 5805 length = struct.unpac 5010 length = struct.unpack('H', buf[i+22:i+24])[0] 5806 base, num = struct.un 5011 base, num = struct.unpack('IH', buf[i+24:i+30]) 5807 break 5012 break 5808 elif buf[i:i+5] == b'_DMI_': !! 5013 elif buf[i:i+5] == '_DMI_': 5809 length = struct.unpac 5014 length = struct.unpack('H', buf[i+6:i+8])[0] 5810 base, num = struct.un 5015 base, num = struct.unpack('IH', buf[i+8:i+14]) 5811 break 5016 break 5812 i += 16 5017 i += 16 5813 if base == 0 and length == 0 and num 5018 if base == 0 and length == 0 and num == 0: 5814 return dmidecode_backup(out, !! 5019 if(fatal): >> 5020 doError('Neither SMBIOS nor DMI were found') >> 5021 else: >> 5022 return out 5815 5023 5816 # read in the SM or DMI table 5024 # read in the SM or DMI table >> 5025 fp = open(mempath, 'rb') 5817 try: 5026 try: 5818 fp = open(mempath, 'rb') << 5819 fp.seek(base) 5027 fp.seek(base) 5820 buf = fp.read(length) 5028 buf = fp.read(length) 5821 except: 5029 except: 5822 return dmidecode_backup(out, !! 5030 if(fatal): >> 5031 doError('DMI table is unreachable, sorry') >> 5032 else: >> 5033 return out 5823 fp.close() 5034 fp.close() 5824 5035 5825 # scan the table for the values we wa 5036 # scan the table for the values we want 5826 count = i = 0 5037 count = i = 0 5827 while(count < num and i <= len(buf) - 5038 while(count < num and i <= len(buf) - 4): 5828 type, size, handle = struct.u 5039 type, size, handle = struct.unpack('BBH', buf[i:i+4]) 5829 n = i + size 5040 n = i + size 5830 while n < len(buf) - 1: 5041 while n < len(buf) - 1: 5831 if 0 == struct.unpack 5042 if 0 == struct.unpack('H', buf[n:n+2])[0]: 5832 break 5043 break 5833 n += 1 5044 n += 1 5834 data = buf[i+size:n+2].split( !! 5045 data = buf[i+size:n+2].split('\0') 5835 for name in info: 5046 for name in info: 5836 itype, idxadr = info[ 5047 itype, idxadr = info[name] 5837 if itype == type: 5048 if itype == type: 5838 idx = struct. !! 5049 idx = struct.unpack('B', buf[i+idxadr])[0] 5839 if idx > 0 an 5050 if idx > 0 and idx < len(data) - 1: 5840 s = d !! 5051 s = data[idx-1].strip() 5841 if s. !! 5052 if s and s.lower() != 'to be filled by o.e.m.': 5842 !! 5053 out[name] = data[idx-1] 5843 i = n + 2 5054 i = n + 2 5844 count += 1 5055 count += 1 5845 return out 5056 return out 5846 5057 >> 5058 def getBattery(): >> 5059 p, charge, bat = '/sys/class/power_supply', 0, {} >> 5060 if not os.path.exists(p): >> 5061 return False >> 5062 for d in os.listdir(p): >> 5063 type = sysvals.getVal(os.path.join(p, d, 'type')).strip().lower() >> 5064 if type != 'battery': >> 5065 continue >> 5066 for v in ['status', 'energy_now', 'capacity_now']: >> 5067 bat[v] = sysvals.getVal(os.path.join(p, d, v)).strip().lower() >> 5068 break >> 5069 if 'status' not in bat: >> 5070 return False >> 5071 ac = False if 'discharging' in bat['status'] else True >> 5072 for v in ['energy_now', 'capacity_now']: >> 5073 if v in bat and bat[v]: >> 5074 charge = int(bat[v]) >> 5075 return (ac, charge) >> 5076 >> 5077 def displayControl(cmd): >> 5078 xset, ret = 'xset -d :0.0 {0}', 0 >> 5079 if sysvals.sudouser: >> 5080 xset = 'sudo -u %s %s' % (sysvals.sudouser, xset) >> 5081 if cmd == 'init': >> 5082 ret = call(xset.format('dpms 0 0 0'), shell=True) >> 5083 if not ret: >> 5084 ret = call(xset.format('s off'), shell=True) >> 5085 elif cmd == 'reset': >> 5086 ret = call(xset.format('s reset'), shell=True) >> 5087 elif cmd in ['on', 'off', 'standby', 'suspend']: >> 5088 b4 = displayControl('stat') >> 5089 ret = call(xset.format('dpms force %s' % cmd), shell=True) >> 5090 if not ret: >> 5091 curr = displayControl('stat') >> 5092 sysvals.vprint('Display Switched: %s -> %s' % (b4, curr)) >> 5093 if curr != cmd: >> 5094 sysvals.vprint('WARNING: Display failed to change to %s' % cmd) >> 5095 if ret: >> 5096 sysvals.vprint('WARNING: Display failed to change to %s with xset' % cmd) >> 5097 return ret >> 5098 elif cmd == 'stat': >> 5099 fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout >> 5100 ret = 'unknown' >> 5101 for line in fp: >> 5102 m = re.match('[\s]*Monitor is (?P<m>.*)', line) >> 5103 if(m and len(m.group('m')) >= 2): >> 5104 out = m.group('m').lower() >> 5105 ret = out[3:] if out[0:2] == 'in' else out >> 5106 break >> 5107 fp.close() >> 5108 return ret >> 5109 5847 # Function: getFPDT 5110 # Function: getFPDT 5848 # Description: 5111 # Description: 5849 # Read the acpi bios tables and pull o 5112 # Read the acpi bios tables and pull out FPDT, the firmware data 5850 # Arguments: 5113 # Arguments: 5851 # output: True to output the info to s 5114 # output: True to output the info to stdout, False otherwise 5852 def getFPDT(output): 5115 def getFPDT(output): 5853 rectype = {} 5116 rectype = {} 5854 rectype[0] = 'Firmware Basic Boot Per 5117 rectype[0] = 'Firmware Basic Boot Performance Record' 5855 rectype[1] = 'S3 Performance Table Re 5118 rectype[1] = 'S3 Performance Table Record' 5856 prectype = {} 5119 prectype = {} 5857 prectype[0] = 'Basic S3 Resume Perfor 5120 prectype[0] = 'Basic S3 Resume Performance Record' 5858 prectype[1] = 'Basic S3 Suspend Perfo 5121 prectype[1] = 'Basic S3 Suspend Performance Record' 5859 5122 5860 sysvals.rootCheck(True) 5123 sysvals.rootCheck(True) 5861 if(not os.path.exists(sysvals.fpdtpat 5124 if(not os.path.exists(sysvals.fpdtpath)): 5862 if(output): 5125 if(output): 5863 doError('file does no 5126 doError('file does not exist: %s' % sysvals.fpdtpath) 5864 return False 5127 return False 5865 if(not os.access(sysvals.fpdtpath, os 5128 if(not os.access(sysvals.fpdtpath, os.R_OK)): 5866 if(output): 5129 if(output): 5867 doError('file is not 5130 doError('file is not readable: %s' % sysvals.fpdtpath) 5868 return False 5131 return False 5869 if(not os.path.exists(sysvals.mempath 5132 if(not os.path.exists(sysvals.mempath)): 5870 if(output): 5133 if(output): 5871 doError('file does no 5134 doError('file does not exist: %s' % sysvals.mempath) 5872 return False 5135 return False 5873 if(not os.access(sysvals.mempath, os. 5136 if(not os.access(sysvals.mempath, os.R_OK)): 5874 if(output): 5137 if(output): 5875 doError('file is not 5138 doError('file is not readable: %s' % sysvals.mempath) 5876 return False 5139 return False 5877 5140 5878 fp = open(sysvals.fpdtpath, 'rb') 5141 fp = open(sysvals.fpdtpath, 'rb') 5879 buf = fp.read() 5142 buf = fp.read() 5880 fp.close() 5143 fp.close() 5881 5144 5882 if(len(buf) < 36): 5145 if(len(buf) < 36): 5883 if(output): 5146 if(output): 5884 doError('Invalid FPDT 5147 doError('Invalid FPDT table data, should '+\ 5885 'be at least 5148 'be at least 36 bytes') 5886 return False 5149 return False 5887 5150 5888 table = struct.unpack('4sIBB6s8sI4sI' 5151 table = struct.unpack('4sIBB6s8sI4sI', buf[0:36]) 5889 if(output): 5152 if(output): 5890 pprint('\n'\ 5153 pprint('\n'\ 5891 'Firmware Performance Data Ta 5154 'Firmware Performance Data Table (%s)\n'\ 5892 ' Signature 5155 ' Signature : %s\n'\ 5893 ' Table Length 5156 ' Table Length : %u\n'\ 5894 ' Revision 5157 ' Revision : %u\n'\ 5895 ' Checksum 5158 ' Checksum : 0x%x\n'\ 5896 ' OEM ID 5159 ' OEM ID : %s\n'\ 5897 ' OEM Table ID 5160 ' OEM Table ID : %s\n'\ 5898 ' OEM Revision 5161 ' OEM Revision : %u\n'\ 5899 ' Creator ID 5162 ' Creator ID : %s\n'\ 5900 ' Creator Revision 5163 ' Creator Revision : 0x%x\n'\ 5901 '' % (ascii(table[0]), ascii( !! 5164 '' % (table[0], table[0], table[1], table[2], table[3], 5902 table[3], ascii(table !! 5165 table[4], table[5], table[6], table[7], table[8])) 5903 ascii(table[7]), tabl << 5904 5166 5905 if(table[0] != b'FPDT'): !! 5167 if(table[0] != 'FPDT'): 5906 if(output): 5168 if(output): 5907 doError('Invalid FPDT 5169 doError('Invalid FPDT table') 5908 return False 5170 return False 5909 if(len(buf) <= 36): 5171 if(len(buf) <= 36): 5910 return False 5172 return False 5911 i = 0 5173 i = 0 5912 fwData = [0, 0] 5174 fwData = [0, 0] 5913 records = buf[36:] 5175 records = buf[36:] 5914 try: !! 5176 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)): 5177 while(i < len(records)): 5920 header = struct.unpack('HBB', 5178 header = struct.unpack('HBB', records[i:i+4]) 5921 if(header[0] not in rectype): 5179 if(header[0] not in rectype): 5922 i += header[1] 5180 i += header[1] 5923 continue 5181 continue 5924 if(header[1] != 16): 5182 if(header[1] != 16): 5925 i += header[1] 5183 i += header[1] 5926 continue 5184 continue 5927 addr = struct.unpack('Q', rec 5185 addr = struct.unpack('Q', records[i+8:i+16])[0] 5928 try: 5186 try: 5929 fp.seek(addr) 5187 fp.seek(addr) 5930 first = fp.read(8) 5188 first = fp.read(8) 5931 except: 5189 except: 5932 if(output): 5190 if(output): 5933 pprint('Bad a 5191 pprint('Bad address 0x%x in %s' % (addr, sysvals.mempath)) 5934 return [0, 0] 5192 return [0, 0] 5935 rechead = struct.unpack('4sI' 5193 rechead = struct.unpack('4sI', first) 5936 recdata = fp.read(rechead[1]- 5194 recdata = fp.read(rechead[1]-8) 5937 if(rechead[0] == b'FBPT'): !! 5195 if(rechead[0] == 'FBPT'): 5938 record = struct.unpac !! 5196 record = struct.unpack('HBBIQQQQQ', recdata) 5939 if(output): 5197 if(output): 5940 pprint('%s (% 5198 pprint('%s (%s)\n'\ 5941 ' 5199 ' Reset END : %u ns\n'\ 5942 ' OS Loader 5200 ' OS Loader LoadImage Start : %u ns\n'\ 5943 ' OS Loader S 5201 ' OS Loader StartImage Start : %u ns\n'\ 5944 ' ExitBoo 5202 ' ExitBootServices Entry : %u ns\n'\ 5945 ' ExitBo 5203 ' ExitBootServices Exit : %u ns'\ 5946 '' % (rectype !! 5204 '' % (rectype[header[0]], rechead[0], record[4], record[5], 5947 recor 5205 record[6], record[7], record[8])) 5948 elif(rechead[0] == b'S3PT'): !! 5206 elif(rechead[0] == 'S3PT'): 5949 if(output): 5207 if(output): 5950 pprint('%s (% !! 5208 pprint('%s (%s)' % (rectype[header[0]], rechead[0])) 5951 j = 0 5209 j = 0 5952 while(j < len(recdata 5210 while(j < len(recdata)): 5953 prechead = st 5211 prechead = struct.unpack('HBB', recdata[j:j+4]) 5954 if(prechead[0 5212 if(prechead[0] not in prectype): 5955 conti 5213 continue 5956 if(prechead[0 5214 if(prechead[0] == 0): 5957 recor 5215 record = struct.unpack('IIQQ', recdata[j:j+prechead[1]]) 5958 fwDat 5216 fwData[1] = record[2] 5959 if(ou 5217 if(output): 5960 5218 pprint(' %s\n'\ 5961 5219 ' Resume Count : %u\n'\ 5962 5220 ' FullResume : %u ns\n'\ 5963 5221 ' AverageResume : %u ns'\ 5964 5222 '' % (prectype[prechead[0]], record[1], 5965 5223 record[2], record[3])) 5966 elif(prechead 5224 elif(prechead[0] == 1): 5967 recor 5225 record = struct.unpack('QQ', recdata[j+4:j+prechead[1]]) 5968 fwDat 5226 fwData[0] = record[1] - record[0] 5969 if(ou 5227 if(output): 5970 5228 pprint(' %s\n'\ 5971 5229 ' SuspendStart : %u ns\n'\ 5972 5230 ' SuspendEnd : %u ns\n'\ 5973 5231 ' SuspendTime : %u ns'\ 5974 5232 '' % (prectype[prechead[0]], record[0], 5975 5233 record[1], fwData[0])) 5976 5234 5977 j += prechead 5235 j += prechead[1] 5978 if(output): 5236 if(output): 5979 pprint('') 5237 pprint('') 5980 i += header[1] 5238 i += header[1] 5981 fp.close() 5239 fp.close() 5982 return fwData 5240 return fwData 5983 5241 5984 # Function: statusCheck 5242 # Function: statusCheck 5985 # Description: 5243 # Description: 5986 # Verify that the requested command an 5244 # Verify that the requested command and options will work, and 5987 # print the results to the terminal 5245 # print the results to the terminal 5988 # Output: 5246 # Output: 5989 # True if the test will work, False if 5247 # True if the test will work, False if not 5990 def statusCheck(probecheck=False): 5248 def statusCheck(probecheck=False): 5991 status = '' 5249 status = '' 5992 5250 5993 pprint('Checking this system (%s)...' 5251 pprint('Checking this system (%s)...' % platform.node()) 5994 5252 5995 # check we have root access 5253 # check we have root access 5996 res = sysvals.colorText('NO (No featu 5254 res = sysvals.colorText('NO (No features of this tool will work!)') 5997 if(sysvals.rootCheck(False)): 5255 if(sysvals.rootCheck(False)): 5998 res = 'YES' 5256 res = 'YES' 5999 pprint(' have root access: %s' % r 5257 pprint(' have root access: %s' % res) 6000 if(res != 'YES'): 5258 if(res != 'YES'): 6001 pprint(' Try running this 5259 pprint(' Try running this script with sudo') 6002 return 'missing root access' 5260 return 'missing root access' 6003 5261 6004 # check sysfs is mounted 5262 # check sysfs is mounted 6005 res = sysvals.colorText('NO (No featu 5263 res = sysvals.colorText('NO (No features of this tool will work!)') 6006 if(os.path.exists(sysvals.powerfile)) 5264 if(os.path.exists(sysvals.powerfile)): 6007 res = 'YES' 5265 res = 'YES' 6008 pprint(' is sysfs mounted: %s' % r 5266 pprint(' is sysfs mounted: %s' % res) 6009 if(res != 'YES'): 5267 if(res != 'YES'): 6010 return 'sysfs is missing' 5268 return 'sysfs is missing' 6011 5269 6012 # check target mode is a valid mode 5270 # check target mode is a valid mode 6013 if sysvals.suspendmode != 'command': 5271 if sysvals.suspendmode != 'command': 6014 res = sysvals.colorText('NO') 5272 res = sysvals.colorText('NO') 6015 modes = getModes() 5273 modes = getModes() 6016 if(sysvals.suspendmode in mod 5274 if(sysvals.suspendmode in modes): 6017 res = 'YES' 5275 res = 'YES' 6018 else: 5276 else: 6019 status = '%s mode is 5277 status = '%s mode is not supported' % sysvals.suspendmode 6020 pprint(' is "%s" a valid p 5278 pprint(' is "%s" a valid power mode: %s' % (sysvals.suspendmode, res)) 6021 if(res == 'NO'): 5279 if(res == 'NO'): 6022 pprint(' valid p 5280 pprint(' valid power modes are: %s' % modes) 6023 pprint(' please 5281 pprint(' please choose one with -m') 6024 5282 6025 # check if ftrace is available 5283 # check if ftrace is available 6026 if sysvals.useftrace: !! 5284 res = sysvals.colorText('NO') 6027 res = sysvals.colorText('NO') !! 5285 ftgood = sysvals.verifyFtrace() 6028 sysvals.useftrace = sysvals.v !! 5286 if(ftgood): 6029 efmt = '"{0}" uses ftrace, an !! 5287 res = 'YES' 6030 if sysvals.useftrace: !! 5288 elif(sysvals.usecallgraph): 6031 res = 'YES' !! 5289 status = 'ftrace is not properly supported' 6032 elif sysvals.usecallgraph: !! 5290 pprint(' 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 5291 6040 # check if kprobes are available 5292 # check if kprobes are available 6041 if sysvals.usekprobes: !! 5293 res = sysvals.colorText('NO') 6042 res = sysvals.colorText('NO') !! 5294 sysvals.usekprobes = sysvals.verifyKprobes() 6043 sysvals.usekprobes = sysvals. !! 5295 if(sysvals.usekprobes): 6044 if(sysvals.usekprobes): !! 5296 res = 'YES' 6045 res = 'YES' !! 5297 else: 6046 else: !! 5298 sysvals.usedevsrc = False 6047 sysvals.usedevsrc = F !! 5299 pprint(' are kprobes supported: %s' % res) 6048 pprint(' are kprobes suppo << 6049 5300 6050 # what data source are we using 5301 # what data source are we using 6051 res = 'DMESG (very limited, ftrace is !! 5302 res = 'DMESG' 6052 if sysvals.useftrace: !! 5303 if(ftgood): 6053 sysvals.usetraceevents = True 5304 sysvals.usetraceevents = True 6054 for e in sysvals.traceevents: 5305 for e in sysvals.traceevents: 6055 if not os.path.exists 5306 if not os.path.exists(sysvals.epath+e): 6056 sysvals.usetr 5307 sysvals.usetraceevents = False 6057 if(sysvals.usetraceevents): 5308 if(sysvals.usetraceevents): 6058 res = 'FTRACE (all tr 5309 res = 'FTRACE (all trace events found)' 6059 pprint(' timeline data source: %s' 5310 pprint(' timeline data source: %s' % res) 6060 5311 6061 # check if rtcwake 5312 # check if rtcwake 6062 res = sysvals.colorText('NO') 5313 res = sysvals.colorText('NO') 6063 if(sysvals.rtcpath != ''): 5314 if(sysvals.rtcpath != ''): 6064 res = 'YES' 5315 res = 'YES' 6065 elif(sysvals.rtcwake): 5316 elif(sysvals.rtcwake): 6066 status = 'rtcwake is not prop 5317 status = 'rtcwake is not properly supported' 6067 pprint(' is rtcwake supported: %s' 5318 pprint(' is rtcwake supported: %s' % res) 6068 5319 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 << 6080 if not probecheck: 5320 if not probecheck: 6081 return status 5321 return status 6082 5322 6083 # verify kprobes 5323 # verify kprobes 6084 if sysvals.usekprobes: 5324 if sysvals.usekprobes: 6085 for name in sysvals.tracefunc 5325 for name in sysvals.tracefuncs: 6086 sysvals.defaultKprobe 5326 sysvals.defaultKprobe(name, sysvals.tracefuncs[name]) 6087 if sysvals.usedevsrc: 5327 if sysvals.usedevsrc: 6088 for name in sysvals.d 5328 for name in sysvals.dev_tracefuncs: 6089 sysvals.defau 5329 sysvals.defaultKprobe(name, sysvals.dev_tracefuncs[name]) 6090 sysvals.addKprobes(True) 5330 sysvals.addKprobes(True) 6091 5331 6092 return status 5332 return status 6093 5333 6094 # Function: doError 5334 # Function: doError 6095 # Description: 5335 # Description: 6096 # generic error function for catastrph 5336 # generic error function for catastrphic failures 6097 # Arguments: 5337 # Arguments: 6098 # msg: the error message to print 5338 # msg: the error message to print 6099 # help: True if printHelp should be ca 5339 # help: True if printHelp should be called after, False otherwise 6100 def doError(msg, help=False): 5340 def doError(msg, help=False): 6101 if(help == True): 5341 if(help == True): 6102 printHelp() 5342 printHelp() 6103 pprint('ERROR: %s\n' % msg) 5343 pprint('ERROR: %s\n' % msg) 6104 sysvals.outputResult({'error':msg}) 5344 sysvals.outputResult({'error':msg}) 6105 sys.exit(1) 5345 sys.exit(1) 6106 5346 6107 # Function: getArgInt 5347 # Function: getArgInt 6108 # Description: 5348 # Description: 6109 # pull out an integer argument from th 5349 # pull out an integer argument from the command line with checks 6110 def getArgInt(name, args, min, max, main=True 5350 def getArgInt(name, args, min, max, main=True): 6111 if main: 5351 if main: 6112 try: 5352 try: 6113 arg = next(args) !! 5353 arg = args.next() 6114 except: 5354 except: 6115 doError(name+': no ar 5355 doError(name+': no argument supplied', True) 6116 else: 5356 else: 6117 arg = args 5357 arg = args 6118 try: 5358 try: 6119 val = int(arg) 5359 val = int(arg) 6120 except: 5360 except: 6121 doError(name+': non-integer v 5361 doError(name+': non-integer value given', True) 6122 if(val < min or val > max): 5362 if(val < min or val > max): 6123 doError(name+': value should 5363 doError(name+': value should be between %d and %d' % (min, max), True) 6124 return val 5364 return val 6125 5365 6126 # Function: getArgFloat 5366 # Function: getArgFloat 6127 # Description: 5367 # Description: 6128 # pull out a float argument from the c 5368 # pull out a float argument from the command line with checks 6129 def getArgFloat(name, args, min, max, main=Tr 5369 def getArgFloat(name, args, min, max, main=True): 6130 if main: 5370 if main: 6131 try: 5371 try: 6132 arg = next(args) !! 5372 arg = args.next() 6133 except: 5373 except: 6134 doError(name+': no ar 5374 doError(name+': no argument supplied', True) 6135 else: 5375 else: 6136 arg = args 5376 arg = args 6137 try: 5377 try: 6138 val = float(arg) 5378 val = float(arg) 6139 except: 5379 except: 6140 doError(name+': non-numerical 5380 doError(name+': non-numerical value given', True) 6141 if(val < min or val > max): 5381 if(val < min or val > max): 6142 doError(name+': value should 5382 doError(name+': value should be between %f and %f' % (min, max), True) 6143 return val 5383 return val 6144 5384 6145 def processData(live=False, quiet=False): !! 5385 def processData(live=False): 6146 if not quiet: !! 5386 pprint('PROCESSING DATA') 6147 pprint('PROCESSING: %s' % sys << 6148 sysvals.vprint('usetraceevents=%s, us << 6149 (sysvals.usetraceevents, sysv << 6150 error = '' 5387 error = '' 6151 if(sysvals.usetraceevents): 5388 if(sysvals.usetraceevents): 6152 testruns, error = parseTraceL 5389 testruns, error = parseTraceLog(live) 6153 if sysvals.dmesgfile: 5390 if sysvals.dmesgfile: 6154 for data in testruns: 5391 for data in testruns: 6155 data.extractE 5392 data.extractErrorInfo() 6156 else: 5393 else: 6157 testruns = loadKernelLog() 5394 testruns = loadKernelLog() 6158 for data in testruns: 5395 for data in testruns: 6159 parseKernelLog(data) 5396 parseKernelLog(data) 6160 if(sysvals.ftracefile and (sy 5397 if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)): 6161 appendIncompleteTrace 5398 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 5399 sysvals.vprint('Command:\n %s' % sysvals.cmdline) 6172 for data in testruns: 5400 for data in testruns: 6173 if data.turbostat: !! 5401 if data.battery: 6174 idx, s = 0, 'Turbosta !! 5402 a1, c1, a2, c2 = data.battery 6175 for val in data.turbo !! 5403 s = 'Battery:\n Before - AC: %s, Charge: %d\n After - AC: %s, Charge: %d' % \ 6176 idx += len(va !! 5404 (a1, int(c1), a2, int(c2)) 6177 if idx >= 80: << 6178 idx = << 6179 s += << 6180 s += val + ' << 6181 sysvals.vprint(s) 5405 sysvals.vprint(s) 6182 data.printDetails() 5406 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: 5407 if sysvals.cgdump: 6190 for data in testruns: 5408 for data in testruns: 6191 data.debugPrint() 5409 data.debugPrint() 6192 sys.exit(0) 5410 sys.exit(0) 6193 if len(testruns) < 1: 5411 if len(testruns) < 1: 6194 pprint('ERROR: Not enough tes 5412 pprint('ERROR: Not enough test data to build a timeline') 6195 return (testruns, {'error': ' 5413 return (testruns, {'error': 'timeline generation failed'}) 6196 sysvals.vprint('Creating the html tim 5414 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile) 6197 createHTML(testruns, error) 5415 createHTML(testruns, error) 6198 if not quiet: !! 5416 pprint('DONE') 6199 pprint('DONE: %s' % sys << 6200 data = testruns[0] 5417 data = testruns[0] 6201 stamp = data.stamp 5418 stamp = data.stamp 6202 stamp['suspend'], stamp['resume'] = d 5419 stamp['suspend'], stamp['resume'] = data.getTimeValues() 6203 if data.fwValid: 5420 if data.fwValid: 6204 stamp['fwsuspend'], stamp['fw 5421 stamp['fwsuspend'], stamp['fwresume'] = data.fwSuspend, data.fwResume 6205 if error: 5422 if error: 6206 stamp['error'] = error 5423 stamp['error'] = error 6207 return (testruns, stamp) 5424 return (testruns, stamp) 6208 5425 6209 # Function: rerunTest 5426 # Function: rerunTest 6210 # Description: 5427 # Description: 6211 # generate an output from an existing 5428 # generate an output from an existing set of ftrace/dmesg logs 6212 def rerunTest(htmlfile=''): !! 5429 def rerunTest(): 6213 if sysvals.ftracefile: 5430 if sysvals.ftracefile: 6214 doesTraceLogHaveTraceEvents() 5431 doesTraceLogHaveTraceEvents() 6215 if not sysvals.dmesgfile and not sysv 5432 if not sysvals.dmesgfile and not sysvals.usetraceevents: 6216 doError('recreating this html 5433 doError('recreating this html output requires a dmesg file') 6217 if htmlfile: !! 5434 sysvals.setOutputFile() 6218 sysvals.htmlfile = htmlfile << 6219 else: << 6220 sysvals.setOutputFile() << 6221 if os.path.exists(sysvals.htmlfile): 5435 if os.path.exists(sysvals.htmlfile): 6222 if not os.path.isfile(sysvals 5436 if not os.path.isfile(sysvals.htmlfile): 6223 doError('a directory 5437 doError('a directory already exists with this name: %s' % sysvals.htmlfile) 6224 elif not os.access(sysvals.ht 5438 elif not os.access(sysvals.htmlfile, os.W_OK): 6225 doError('missing perm 5439 doError('missing permission to write to %s' % sysvals.htmlfile) 6226 testruns, stamp = processData() !! 5440 testruns, stamp = processData(False) 6227 sysvals.resetlog() !! 5441 sysvals.logmsg = '' 6228 return stamp 5442 return stamp 6229 5443 6230 # Function: runTest 5444 # Function: runTest 6231 # Description: 5445 # Description: 6232 # execute a suspend/resume, gather the 5446 # execute a suspend/resume, gather the logs, and generate the output 6233 def runTest(n=0, quiet=False): !! 5447 def runTest(n=0): 6234 # prepare for the test 5448 # prepare for the test >> 5449 sysvals.initFtrace() 6235 sysvals.initTestOutput('suspend') 5450 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 5451 6251 # execute the test 5452 # execute the test 6252 executeSuspend(quiet) !! 5453 executeSuspend() 6253 sysvals.cleanupFtrace() 5454 sysvals.cleanupFtrace() 6254 if sysvals.skiphtml: 5455 if sysvals.skiphtml: 6255 sysvals.outputResult({}, n) << 6256 sysvals.sudoUserchown(sysvals 5456 sysvals.sudoUserchown(sysvals.testdir) 6257 return 5457 return 6258 testruns, stamp = processData(True, q !! 5458 testruns, stamp = processData(True) 6259 for data in testruns: 5459 for data in testruns: 6260 del data 5460 del data 6261 sysvals.sudoUserchown(sysvals.testdir 5461 sysvals.sudoUserchown(sysvals.testdir) 6262 sysvals.outputResult(stamp, n) 5462 sysvals.outputResult(stamp, n) 6263 if 'error' in stamp: 5463 if 'error' in stamp: 6264 return 2 5464 return 2 6265 return 0 5465 return 0 6266 5466 6267 def find_in_html(html, start, end, firstonly= 5467 def find_in_html(html, start, end, firstonly=True): 6268 cnt, out, list = len(html), [], [] !! 5468 n, out = 0, [] 6269 if firstonly: !! 5469 while n < len(html): 6270 m = re.search(start, html) !! 5470 m = re.search(start, html[n:]) 6271 if m: !! 5471 if not m: 6272 list.append(m) !! 5472 break 6273 else: !! 5473 i = m.end() 6274 list = re.finditer(start, htm !! 5474 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: 5475 if not m: 6280 break 5476 break 6281 e = s + m.start() !! 5477 j = m.start() 6282 str = html[s:e] !! 5478 str = html[n+i:n+i+j] 6283 if end == 'ms': 5479 if end == 'ms': 6284 num = re.search(r'[-+ 5480 num = re.search(r'[-+]?\d*\.\d+|\d+', str) 6285 str = num.group() if 5481 str = num.group() if num else 'NaN' 6286 if firstonly: 5482 if firstonly: 6287 return str 5483 return str 6288 out.append(str) 5484 out.append(str) >> 5485 n += i+j 6289 if firstonly: 5486 if firstonly: 6290 return '' 5487 return '' 6291 return out 5488 return out 6292 5489 6293 def data_from_html(file, outpath, issues, ful !! 5490 def data_from_html(file, outpath, devlist=False): 6294 try: !! 5491 html = open(file, 'r').read() 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 5492 suspend = find_in_html(html, 'Kernel Suspend', 'ms') 6301 resume = find_in_html(html, 'Kernel R 5493 resume = find_in_html(html, 'Kernel Resume', 'ms') 6302 sysinfo = find_in_html(html, '<div cl << 6303 line = find_in_html(html, '<div class 5494 line = find_in_html(html, '<div class="stamp">', '</div>') 6304 stmp = line.split() 5495 stmp = line.split() 6305 if not suspend or not resume or len(s 5496 if not suspend or not resume or len(stmp) != 8: 6306 return False 5497 return False 6307 try: 5498 try: 6308 dt = datetime.strptime(' '.jo 5499 dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p') 6309 except: 5500 except: 6310 return False 5501 return False 6311 sysvals.hostname = stmp[0] << 6312 tstr = dt.strftime('%Y/%m/%d %H:%M:%S 5502 tstr = dt.strftime('%Y/%m/%d %H:%M:%S') 6313 error = find_in_html(html, '<table cl 5503 error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>') 6314 if error: 5504 if error: 6315 m = re.match(r'[a-z0-9]* fail !! 5505 m = re.match('[a-z]* failed in (?P<p>[a-z0-9_]*) phase', error) 6316 if m: 5506 if m: 6317 result = 'fail in %s' 5507 result = 'fail in %s' % m.group('p') 6318 else: 5508 else: 6319 result = 'fail' 5509 result = 'fail' 6320 else: 5510 else: 6321 result = 'pass' 5511 result = 'pass' 6322 # extract error info !! 5512 ilist = [] 6323 tp, ilist = False, [] !! 5513 e = find_in_html(html, 'class="err"[\w=":;\.%\- ]*>', '→</div>', False) 6324 extra = dict() !! 5514 for i in list(set(e)): 6325 log = find_in_html(html, '<div id="dm !! 5515 ilist.append('%sx%d' % (i, e.count(i)) if e.count(i) > 1 else i) 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 5516 low = find_in_html(html, 'freeze time: <b>', ' ms</b>') 6357 for lowstr in ['waking', '+']: !! 5517 if low and '|' in low: 6358 if not low: !! 5518 ilist.append('FREEZEx%d' % len(low.split('|'))) 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() 5519 devices = dict() 6382 for line in html.split('\n'): 5520 for line in html.split('\n'): 6383 m = re.match(r' *<div id=\"[a !! 5521 m = re.match(' *<div id=\"[a,0-9]*\" *title=\"(?P<title>.*)\" class=\"thread.*', line) 6384 if not m or 'thread kth' in l 5522 if not m or 'thread kth' in line or 'thread sec' in line: 6385 continue 5523 continue 6386 m = re.match(r'(?P<n>.*) \((? !! 5524 m = re.match('(?P<n>.*) \((?P<t>[0-9,\.]*) ms\) (?P<p>.*)', m.group('title')) 6387 if not m: 5525 if not m: 6388 continue 5526 continue 6389 name, time, phase = m.group(' 5527 name, time, phase = m.group('n'), m.group('t'), m.group('p') 6390 if name == 'async_synchronize << 6391 continue << 6392 if ' async' in name or ' sync 5528 if ' async' in name or ' sync' in name: 6393 name = ' '.join(name. 5529 name = ' '.join(name.split(' ')[:-1]) 6394 if phase.startswith('suspend' !! 5530 d = phase.split('_')[0] 6395 d = 'suspend' << 6396 elif phase.startswith('resume << 6397 d = 'resume' << 6398 else: << 6399 continue << 6400 if d not in devices: 5531 if d not in devices: 6401 devices[d] = dict() 5532 devices[d] = dict() 6402 if name not in devices[d]: 5533 if name not in devices[d]: 6403 devices[d][name] = 0. 5534 devices[d][name] = 0.0 6404 devices[d][name] += float(tim 5535 devices[d][name] += float(time) 6405 # create worst device info !! 5536 worst = {'suspend': {'name':'', 'time': 0.0}, 6406 worst = dict() !! 5537 'resume': {'name':'', 'time': 0.0}} 6407 for d in ['suspend', 'resume']: !! 5538 for d in devices: 6408 worst[d] = {'name':'', 'time' !! 5539 if d not in worst: 6409 dev = devices[d] if d in devi !! 5540 worst[d] = dict() 6410 if dev and len(dev.keys()) > !! 5541 dev = devices[d] 6411 n = sorted(dev, key=l !! 5542 if len(dev.keys()) > 0: >> 5543 n = sorted(dev, key=dev.get, reverse=True)[0] 6412 worst[d]['name'], wor 5544 worst[d]['name'], worst[d]['time'] = n, dev[n] 6413 data = { 5545 data = { 6414 'mode': stmp[2], 5546 'mode': stmp[2], 6415 'host': stmp[0], 5547 'host': stmp[0], 6416 'kernel': stmp[1], 5548 'kernel': stmp[1], 6417 'sysinfo': sysinfo, << 6418 'time': tstr, 5549 'time': tstr, 6419 'result': result, 5550 'result': result, 6420 'issues': ' '.join(ilist), 5551 'issues': ' '.join(ilist), 6421 'suspend': suspend, 5552 'suspend': suspend, 6422 'resume': resume, 5553 'resume': resume, 6423 'devlist': devices, << 6424 'sus_worst': worst['suspend'] 5554 'sus_worst': worst['suspend']['name'], 6425 'sus_worsttime': worst['suspe 5555 'sus_worsttime': worst['suspend']['time'], 6426 'res_worst': worst['resume'][ 5556 'res_worst': worst['resume']['name'], 6427 'res_worsttime': worst['resum 5557 'res_worsttime': worst['resume']['time'], 6428 'url': sysvals.htmlfile, !! 5558 'url': os.path.relpath(file, outpath), 6429 } 5559 } 6430 for key in extra: !! 5560 if devlist: 6431 data[key] = extra[key] !! 5561 data['devlist'] = devices 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 5562 return data 6440 5563 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 5564 # Function: runSummary 6460 # Description: 5565 # Description: 6461 # create a summary of tests in a sub-d 5566 # create a summary of tests in a sub-directory 6462 def runSummary(subdir, local=True, genhtml=Fa 5567 def runSummary(subdir, local=True, genhtml=False): 6463 inpath = os.path.abspath(subdir) 5568 inpath = os.path.abspath(subdir) 6464 outpath = os.path.abspath('.') if loc 5569 outpath = os.path.abspath('.') if local else inpath 6465 pprint('Generating a summary of folde !! 5570 pprint('Generating a summary of folder "%s"' % inpath) 6466 if genhtml: 5571 if genhtml: 6467 genHtml(subdir) !! 5572 for dirname, dirnames, filenames in os.walk(subdir): 6468 target, issues, testruns = '', [], [] !! 5573 sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = '' >> 5574 for filename in filenames: >> 5575 if(re.match('.*_dmesg.txt', filename)): >> 5576 sysvals.dmesgfile = os.path.join(dirname, filename) >> 5577 elif(re.match('.*_ftrace.txt', filename)): >> 5578 sysvals.ftracefile = os.path.join(dirname, filename) >> 5579 sysvals.setOutputFile() >> 5580 if sysvals.ftracefile and sysvals.htmlfile and \ >> 5581 not os.path.exists(sysvals.htmlfile): >> 5582 pprint('FTRACE: %s' % sysvals.ftracefile) >> 5583 if sysvals.dmesgfile: >> 5584 pprint('DMESG : %s' % sysvals.dmesgfile) >> 5585 rerunTest() >> 5586 testruns = [] 6469 desc = {'host':[],'mode':[],'kernel': 5587 desc = {'host':[],'mode':[],'kernel':[]} 6470 for dirname, dirnames, filenames in o 5588 for dirname, dirnames, filenames in os.walk(subdir): 6471 for filename in filenames: 5589 for filename in filenames: 6472 if(not re.match(r'.*. !! 5590 if(not re.match('.*.html', filename)): 6473 continue 5591 continue 6474 data = data_from_html !! 5592 data = data_from_html(os.path.join(dirname, filename), outpath) 6475 if(not data): 5593 if(not data): 6476 continue 5594 continue 6477 if 'target' in data: << 6478 target = data << 6479 testruns.append(data) 5595 testruns.append(data) 6480 for key in desc: 5596 for key in desc: 6481 if data[key] 5597 if data[key] not in desc[key]: 6482 desc[ 5598 desc[key].append(data[key]) 6483 pprint('Summary files:') !! 5599 outfile = os.path.join(outpath, 'summary.html') >> 5600 pprint('Summary file: %s' % outfile) 6484 if len(desc['host']) == len(desc['mod 5601 if len(desc['host']) == len(desc['mode']) == len(desc['kernel']) == 1: 6485 title = '%s %s %s' % (desc['h 5602 title = '%s %s %s' % (desc['host'][0], desc['kernel'][0], desc['mode'][0]) 6486 if target: << 6487 title += ' %s' % targ << 6488 else: 5603 else: 6489 title = inpath 5604 title = inpath 6490 createHTMLSummarySimple(testruns, os. !! 5605 createHTMLSummarySimple(testruns, outfile, title) 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 5606 6497 # Function: checkArgBool 5607 # Function: checkArgBool 6498 # Description: 5608 # Description: 6499 # check if a boolean string value is t 5609 # check if a boolean string value is true or false 6500 def checkArgBool(name, value): 5610 def checkArgBool(name, value): 6501 if value in switchvalues: 5611 if value in switchvalues: 6502 if value in switchoff: 5612 if value in switchoff: 6503 return False 5613 return False 6504 return True 5614 return True 6505 doError('invalid boolean --> (%s: %s) 5615 doError('invalid boolean --> (%s: %s), use "true/false" or "1/0"' % (name, value), True) 6506 return False 5616 return False 6507 5617 6508 # Function: configFromFile 5618 # Function: configFromFile 6509 # Description: 5619 # Description: 6510 # Configure the script via the info in 5620 # Configure the script via the info in a config file 6511 def configFromFile(file): 5621 def configFromFile(file): 6512 Config = configparser.ConfigParser() !! 5622 Config = ConfigParser.ConfigParser() 6513 5623 6514 Config.read(file) 5624 Config.read(file) 6515 sections = Config.sections() 5625 sections = Config.sections() 6516 overridekprobes = False 5626 overridekprobes = False 6517 overridedevkprobes = False 5627 overridedevkprobes = False 6518 if 'Settings' in sections: 5628 if 'Settings' in sections: 6519 for opt in Config.options('Se 5629 for opt in Config.options('Settings'): 6520 value = Config.get('S 5630 value = Config.get('Settings', opt).lower() 6521 option = opt.lower() 5631 option = opt.lower() 6522 if(option == 'verbose 5632 if(option == 'verbose'): 6523 sysvals.verbo 5633 sysvals.verbose = checkArgBool(option, value) 6524 elif(option == 'addlo 5634 elif(option == 'addlogs'): 6525 sysvals.dmesg 5635 sysvals.dmesglog = sysvals.ftracelog = checkArgBool(option, value) 6526 elif(option == 'dev') 5636 elif(option == 'dev'): 6527 sysvals.usede 5637 sysvals.usedevsrc = checkArgBool(option, value) 6528 elif(option == 'proc' 5638 elif(option == 'proc'): 6529 sysvals.usepr 5639 sysvals.useprocmon = checkArgBool(option, value) 6530 elif(option == 'x2'): 5640 elif(option == 'x2'): 6531 if checkArgBo 5641 if checkArgBool(option, value): 6532 sysva 5642 sysvals.execcount = 2 6533 elif(option == 'callg 5643 elif(option == 'callgraph'): 6534 sysvals.useca 5644 sysvals.usecallgraph = checkArgBool(option, value) 6535 elif(option == 'overr 5645 elif(option == 'override-timeline-functions'): 6536 overridekprob 5646 overridekprobes = checkArgBool(option, value) 6537 elif(option == 'overr 5647 elif(option == 'override-dev-timeline-functions'): 6538 overridedevkp 5648 overridedevkprobes = checkArgBool(option, value) 6539 elif(option == 'skiph 5649 elif(option == 'skiphtml'): 6540 sysvals.skiph 5650 sysvals.skiphtml = checkArgBool(option, value) 6541 elif(option == 'sync' 5651 elif(option == 'sync'): 6542 sysvals.sync 5652 sysvals.sync = checkArgBool(option, value) 6543 elif(option == 'rs' o 5653 elif(option == 'rs' or option == 'runtimesuspend'): 6544 if value in s 5654 if value in switchvalues: 6545 if va 5655 if value in switchoff: 6546 5656 sysvals.rs = -1 6547 else: 5657 else: 6548 5658 sysvals.rs = 1 6549 else: 5659 else: 6550 doErr 5660 doError('invalid value --> (%s: %s), use "enable/disable"' % (option, value), True) 6551 elif(option == 'displ 5661 elif(option == 'display'): 6552 disopt = ['on 5662 disopt = ['on', 'off', 'standby', 'suspend'] 6553 if value not 5663 if value not in disopt: 6554 doErr 5664 doError('invalid value --> (%s: %s), use %s' % (option, value, disopt), True) 6555 sysvals.displ 5665 sysvals.display = value 6556 elif(option == 'gzip' 5666 elif(option == 'gzip'): 6557 sysvals.gzip 5667 sysvals.gzip = checkArgBool(option, value) 6558 elif(option == 'cgfil 5668 elif(option == 'cgfilter'): 6559 sysvals.setCa 5669 sysvals.setCallgraphFilter(value) 6560 elif(option == 'cgski 5670 elif(option == 'cgskip'): 6561 if value in s 5671 if value in switchoff: 6562 sysva 5672 sysvals.cgskip = '' 6563 else: 5673 else: 6564 sysva 5674 sysvals.cgskip = sysvals.configFile(val) 6565 if(no 5675 if(not sysvals.cgskip): 6566 5676 doError('%s does not exist' % sysvals.cgskip) 6567 elif(option == 'cgtes 5677 elif(option == 'cgtest'): 6568 sysvals.cgtes 5678 sysvals.cgtest = getArgInt('cgtest', value, 0, 1, False) 6569 elif(option == 'cgpha 5679 elif(option == 'cgphase'): 6570 d = Data(0) 5680 d = Data(0) 6571 if value not !! 5681 if value not in d.sortedPhases(): 6572 doErr 5682 doError('invalid phase --> (%s: %s), valid phases are %s'\ 6573 !! 5683 % (option, value, d.sortedPhases()), True) 6574 sysvals.cgpha 5684 sysvals.cgphase = value 6575 elif(option == 'fadd' 5685 elif(option == 'fadd'): 6576 file = sysval 5686 file = sysvals.configFile(value) 6577 if(not file): 5687 if(not file): 6578 doErr 5688 doError('%s does not exist' % value) 6579 sysvals.addFt 5689 sysvals.addFtraceFilterFunctions(file) 6580 elif(option == 'resul 5690 elif(option == 'result'): 6581 sysvals.resul 5691 sysvals.result = value 6582 elif(option == 'multi 5692 elif(option == 'multi'): 6583 nums = value. 5693 nums = value.split() 6584 if len(nums) 5694 if len(nums) != 2: 6585 doErr 5695 doError('multi requires 2 integers (exec_count and delay)', True) 6586 sysvals.multi !! 5696 sysvals.multitest['run'] = True >> 5697 sysvals.multitest['count'] = getArgInt('multi: n d (exec count)', nums[0], 2, 1000000, False) >> 5698 sysvals.multitest['delay'] = getArgInt('multi: n d (delay between tests)', nums[1], 0, 3600, False) 6587 elif(option == 'devic 5699 elif(option == 'devicefilter'): 6588 sysvals.setDe 5700 sysvals.setDeviceFilter(value) 6589 elif(option == 'expan 5701 elif(option == 'expandcg'): 6590 sysvals.cgexp 5702 sysvals.cgexp = checkArgBool(option, value) 6591 elif(option == 'srgap 5703 elif(option == 'srgap'): 6592 if checkArgBo 5704 if checkArgBool(option, value): 6593 sysva 5705 sysvals.srgap = 5 6594 elif(option == 'mode' 5706 elif(option == 'mode'): 6595 sysvals.suspe 5707 sysvals.suspendmode = value 6596 elif(option == 'comma 5708 elif(option == 'command' or option == 'cmd'): 6597 sysvals.testc 5709 sysvals.testcommand = value 6598 elif(option == 'x2del 5710 elif(option == 'x2delay'): 6599 sysvals.x2del 5711 sysvals.x2delay = getArgInt('x2delay', value, 0, 60000, False) 6600 elif(option == 'prede 5712 elif(option == 'predelay'): 6601 sysvals.prede 5713 sysvals.predelay = getArgInt('predelay', value, 0, 60000, False) 6602 elif(option == 'postd 5714 elif(option == 'postdelay'): 6603 sysvals.postd 5715 sysvals.postdelay = getArgInt('postdelay', value, 0, 60000, False) 6604 elif(option == 'maxde 5716 elif(option == 'maxdepth'): 6605 sysvals.max_g 5717 sysvals.max_graph_depth = getArgInt('maxdepth', value, 0, 1000, False) 6606 elif(option == 'rtcwa 5718 elif(option == 'rtcwake'): 6607 if value in s 5719 if value in switchoff: 6608 sysva 5720 sysvals.rtcwake = False 6609 else: 5721 else: 6610 sysva 5722 sysvals.rtcwake = True 6611 sysva 5723 sysvals.rtcwaketime = getArgInt('rtcwake', value, 0, 3600, False) 6612 elif(option == 'timep 5724 elif(option == 'timeprec'): 6613 sysvals.setPr 5725 sysvals.setPrecision(getArgInt('timeprec', value, 0, 6, False)) 6614 elif(option == 'minde 5726 elif(option == 'mindev'): 6615 sysvals.minde 5727 sysvals.mindevlen = getArgFloat('mindev', value, 0.0, 10000.0, False) 6616 elif(option == 'calll 5728 elif(option == 'callloop-maxgap'): 6617 sysvals.calll 5729 sysvals.callloopmaxgap = getArgFloat('callloop-maxgap', value, 0.0, 1.0, False) 6618 elif(option == 'calll 5730 elif(option == 'callloop-maxlen'): 6619 sysvals.calll 5731 sysvals.callloopmaxgap = getArgFloat('callloop-maxlen', value, 0.0, 1.0, False) 6620 elif(option == 'mincg 5732 elif(option == 'mincg'): 6621 sysvals.mincg 5733 sysvals.mincglen = getArgFloat('mincg', value, 0.0, 10000.0, False) 6622 elif(option == 'bufsi 5734 elif(option == 'bufsize'): 6623 sysvals.bufsi 5735 sysvals.bufsize = getArgInt('bufsize', value, 1, 1024*1024*8, False) 6624 elif(option == 'outpu 5736 elif(option == 'output-dir'): 6625 sysvals.outdi 5737 sysvals.outdir = sysvals.setOutputFolder(value) 6626 5738 6627 if sysvals.suspendmode == 'command' a 5739 if sysvals.suspendmode == 'command' and not sysvals.testcommand: 6628 doError('No command supplied 5740 doError('No command supplied for mode "command"') 6629 5741 6630 # compatibility errors 5742 # compatibility errors 6631 if sysvals.usedevsrc and sysvals.usec 5743 if sysvals.usedevsrc and sysvals.usecallgraph: 6632 doError('-dev is not compatib 5744 doError('-dev is not compatible with -f') 6633 if sysvals.usecallgraph and sysvals.u 5745 if sysvals.usecallgraph and sysvals.useprocmon: 6634 doError('-proc is not compati 5746 doError('-proc is not compatible with -f') 6635 5747 6636 if overridekprobes: 5748 if overridekprobes: 6637 sysvals.tracefuncs = dict() 5749 sysvals.tracefuncs = dict() 6638 if overridedevkprobes: 5750 if overridedevkprobes: 6639 sysvals.dev_tracefuncs = dict 5751 sysvals.dev_tracefuncs = dict() 6640 5752 6641 kprobes = dict() 5753 kprobes = dict() 6642 kprobesec = 'dev_timeline_functions_' 5754 kprobesec = 'dev_timeline_functions_'+platform.machine() 6643 if kprobesec in sections: 5755 if kprobesec in sections: 6644 for name in Config.options(kp 5756 for name in Config.options(kprobesec): 6645 text = Config.get(kpr 5757 text = Config.get(kprobesec, name) 6646 kprobes[name] = (text 5758 kprobes[name] = (text, True) 6647 kprobesec = 'timeline_functions_'+pla 5759 kprobesec = 'timeline_functions_'+platform.machine() 6648 if kprobesec in sections: 5760 if kprobesec in sections: 6649 for name in Config.options(kp 5761 for name in Config.options(kprobesec): 6650 if name in kprobes: 5762 if name in kprobes: 6651 doError('Dupl 5763 doError('Duplicate timeline function found "%s"' % (name)) 6652 text = Config.get(kpr 5764 text = Config.get(kprobesec, name) 6653 kprobes[name] = (text 5765 kprobes[name] = (text, False) 6654 5766 6655 for name in kprobes: 5767 for name in kprobes: 6656 function = name 5768 function = name 6657 format = name 5769 format = name 6658 color = '' 5770 color = '' 6659 args = dict() 5771 args = dict() 6660 text, dev = kprobes[name] 5772 text, dev = kprobes[name] 6661 data = text.split() 5773 data = text.split() 6662 i = 0 5774 i = 0 6663 for val in data: 5775 for val in data: 6664 # bracketted strings 5776 # bracketted strings are special formatting, read them separately 6665 if val[0] == '[' and 5777 if val[0] == '[' and val[-1] == ']': 6666 for prop in v 5778 for prop in val[1:-1].split(','): 6667 p = p 5779 p = prop.split('=') 6668 if p[ 5780 if p[0] == 'color': 6669 5781 try: 6670 5782 color = int(p[1], 16) 6671 5783 color = '#'+p[1] 6672 5784 except: 6673 5785 color = p[1] 6674 continue 5786 continue 6675 # first real arg shou 5787 # first real arg should be the format string 6676 if i == 0: 5788 if i == 0: 6677 format = val 5789 format = val 6678 # all other args are 5790 # all other args are actual function args 6679 else: 5791 else: 6680 d = val.split 5792 d = val.split('=') 6681 args[d[0]] = 5793 args[d[0]] = d[1] 6682 i += 1 5794 i += 1 6683 if not function or not format 5795 if not function or not format: 6684 doError('Invalid kpro 5796 doError('Invalid kprobe: %s' % name) 6685 for arg in re.findall('{(?P<n 5797 for arg in re.findall('{(?P<n>[a-z,A-Z,0-9]*)}', format): 6686 if arg not in args: 5798 if arg not in args: 6687 doError('Kpro 5799 doError('Kprobe "%s" is missing argument "%s"' % (name, arg)) 6688 if (dev and name in sysvals.d 5800 if (dev and name in sysvals.dev_tracefuncs) or (not dev and name in sysvals.tracefuncs): 6689 doError('Duplicate ti 5801 doError('Duplicate timeline function found "%s"' % (name)) 6690 5802 6691 kp = { 5803 kp = { 6692 'name': name, 5804 'name': name, 6693 'func': function, 5805 'func': function, 6694 'format': format, 5806 'format': format, 6695 sysvals.archargs: arg 5807 sysvals.archargs: args 6696 } 5808 } 6697 if color: 5809 if color: 6698 kp['color'] = color 5810 kp['color'] = color 6699 if dev: 5811 if dev: 6700 sysvals.dev_tracefunc 5812 sysvals.dev_tracefuncs[name] = kp 6701 else: 5813 else: 6702 sysvals.tracefuncs[na 5814 sysvals.tracefuncs[name] = kp 6703 5815 6704 # Function: printHelp 5816 # Function: printHelp 6705 # Description: 5817 # Description: 6706 # print out the help text 5818 # print out the help text 6707 def printHelp(): 5819 def printHelp(): 6708 pprint('\n%s v%s\n'\ 5820 pprint('\n%s v%s\n'\ 6709 'Usage: sudo sleepgraph <options> <co 5821 'Usage: sudo sleepgraph <options> <commands>\n'\ 6710 '\n'\ 5822 '\n'\ 6711 'Description:\n'\ 5823 'Description:\n'\ 6712 ' This tool is designed to assist ke 5824 ' This tool is designed to assist kernel and OS developers in optimizing\n'\ 6713 ' their linux stack\'s suspend/resum 5825 ' their linux stack\'s suspend/resume time. Using a kernel image built\n'\ 6714 ' with a few extra options enabled, 5826 ' with a few extra options enabled, the tool will execute a suspend and\n'\ 6715 ' capture dmesg and ftrace data unti 5827 ' capture dmesg and ftrace data until resume is complete. This data is\n'\ 6716 ' transformed into a device timeline 5828 ' transformed into a device timeline and an optional callgraph to give\n'\ 6717 ' a detailed view of which devices/s 5829 ' a detailed view of which devices/subsystems are taking the most\n'\ 6718 ' time in suspend/resume.\n'\ 5830 ' time in suspend/resume.\n'\ 6719 '\n'\ 5831 '\n'\ 6720 ' If no specific command is given, t 5832 ' If no specific command is given, the default behavior is to initiate\n'\ 6721 ' a suspend/resume and capture the d 5833 ' a suspend/resume and capture the dmesg/ftrace output as an html timeline.\n'\ 6722 '\n'\ 5834 '\n'\ 6723 ' Generates output files in subdirec 5835 ' Generates output files in subdirectory: suspend-yymmdd-HHMMSS\n'\ 6724 ' HTML output: < 5836 ' HTML output: <hostname>_<mode>.html\n'\ 6725 ' raw dmesg output: < 5837 ' raw dmesg output: <hostname>_<mode>_dmesg.txt\n'\ 6726 ' raw ftrace output: < 5838 ' raw ftrace output: <hostname>_<mode>_ftrace.txt\n'\ 6727 '\n'\ 5839 '\n'\ 6728 'Options:\n'\ 5840 'Options:\n'\ 6729 ' -h Print this help text 5841 ' -h Print this help text\n'\ 6730 ' -v Print the current to 5842 ' -v Print the current tool version\n'\ 6731 ' -config fn Pull arguments and c 5843 ' -config fn Pull arguments and config options from file fn\n'\ 6732 ' -verbose Print extra informat 5844 ' -verbose Print extra information during execution and analysis\n'\ 6733 ' -m mode Mode to initiate for 5845 ' -m mode Mode to initiate for suspend (default: %s)\n'\ 6734 ' -o name Overrides the output 5846 ' -o name Overrides the output subdirectory name when running a new test\n'\ 6735 ' default: suspend-{da 5847 ' default: suspend-{date}-{time}\n'\ 6736 ' -rtcwake t Wakeup t seconds aft 5848 ' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\ 6737 ' -addlogs Add the dmesg and ft 5849 ' -addlogs Add the dmesg and ftrace logs to the html output\n'\ 6738 ' -noturbostat Dont use turbostat i << 6739 ' -srgap Add a visible gap in 5850 ' -srgap Add a visible gap in the timeline between sus/res (default: disabled)\n'\ 6740 ' -skiphtml Run the test and cap 5851 ' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\ 6741 ' -result fn Export a results tab 5852 ' -result fn Export a results table to a text file for parsing.\n'\ 6742 ' -wifi If a wifi connection << 6743 ' -wifitrace Trace kernel executi << 6744 ' -netfix Use netfix to reset << 6745 ' [testprep]\n'\ 5853 ' [testprep]\n'\ 6746 ' -sync Sync the filesystems 5854 ' -sync Sync the filesystems before starting the test\n'\ 6747 ' -rs on/off Enable/disable runti 5855 ' -rs on/off Enable/disable runtime suspend for all devices, restore all after test\n'\ 6748 ' -display m Change the display m 5856 ' -display m Change the display mode to m for the test (on/off/standby/suspend)\n'\ 6749 ' [advanced]\n'\ 5857 ' [advanced]\n'\ 6750 ' -gzip Gzip the trace and d 5858 ' -gzip Gzip the trace and dmesg logs to save space\n'\ 6751 ' -cmd {s} Run the timeline ove 5859 ' -cmd {s} Run the timeline over a custom command, e.g. "sync -d"\n'\ 6752 ' -proc Add usermode process 5860 ' -proc Add usermode process info into the timeline (default: disabled)\n'\ 6753 ' -dev Add kernel function 5861 ' -dev Add kernel function calls and threads to the timeline (default: disabled)\n'\ 6754 ' -x2 Run two suspend/resu 5862 ' -x2 Run two suspend/resumes back to back (default: disabled)\n'\ 6755 ' -x2delay t Include t ms delay b 5863 ' -x2delay t Include t ms delay between multiple test runs (default: 0 ms)\n'\ 6756 ' -predelay t Include t ms delay b 5864 ' -predelay t Include t ms delay before 1st suspend (default: 0 ms)\n'\ 6757 ' -postdelay t Include t ms delay a 5865 ' -postdelay t Include t ms delay after last resume (default: 0 ms)\n'\ 6758 ' -mindev ms Discard all device b 5866 ' -mindev ms Discard all device blocks shorter than ms milliseconds (e.g. 0.001 for us)\n'\ 6759 ' -multi n d Execute <n> consecut !! 5867 ' -multi n d Execute <n> consecutive tests at <d> seconds intervals. The outputs will\n'\ 6760 ' by a "d", "h", or "m !! 5868 ' be created in a new subdirectory with a summary page.\n'\ 6761 ' The outputs will be << 6762 ' -maxfail n Abort a -multi run a << 6763 ' [debug]\n'\ 5869 ' [debug]\n'\ 6764 ' -f Use ftrace to create 5870 ' -f Use ftrace to create device callgraphs (default: disabled)\n'\ 6765 ' -ftop Use ftrace on the to << 6766 ' -maxdepth N limit the callgraph 5871 ' -maxdepth N limit the callgraph data to N call levels (default: 0=all)\n'\ 6767 ' -expandcg pre-expand the callg 5872 ' -expandcg pre-expand the callgraph data in the html output (default: disabled)\n'\ 6768 ' -fadd file Add functions to be 5873 ' -fadd file Add functions to be graphed in the timeline from a list in a text file\n'\ 6769 ' -filter "d1,d2,..." Filter out al 5874 ' -filter "d1,d2,..." Filter out all but this comma-delimited list of device names\n'\ 6770 ' -mincg ms Discard all callgrap 5875 ' -mincg ms Discard all callgraphs shorter than ms milliseconds (e.g. 0.001 for us)\n'\ 6771 ' -cgphase P Only show callgraph 5876 ' -cgphase P Only show callgraph data for phase P (e.g. suspend_late)\n'\ 6772 ' -cgtest N Only show callgraph 5877 ' -cgtest N Only show callgraph data for test N (e.g. 0 or 1 in an x2 run)\n'\ 6773 ' -timeprec N Number of significan 5878 ' -timeprec N Number of significant digits in timestamps (0:S, [3:ms], 6:us)\n'\ 6774 ' -cgfilter S Filter the callgraph 5879 ' -cgfilter S Filter the callgraph output in the timeline\n'\ 6775 ' -cgskip file Callgraph functions 5880 ' -cgskip file Callgraph functions to skip, off to disable (default: cgskip.txt)\n'\ 6776 ' -bufsize N Set trace buffer siz 5881 ' -bufsize N Set trace buffer size to N kilo-bytes (default: all of free memory)\n'\ 6777 ' -devdump Print out all the ra 5882 ' -devdump Print out all the raw device data for each phase\n'\ 6778 ' -cgdump Print out all the ra 5883 ' -cgdump Print out all the raw callgraph data\n'\ 6779 '\n'\ 5884 '\n'\ 6780 'Other commands:\n'\ 5885 'Other commands:\n'\ 6781 ' -modes List available suspe 5886 ' -modes List available suspend modes\n'\ 6782 ' -status Test to see if the s 5887 ' -status Test to see if the system is enabled to run this tool\n'\ 6783 ' -fpdt Print out the conten 5888 ' -fpdt Print out the contents of the ACPI Firmware Performance Data Table\n'\ 6784 ' -wificheck Print out wifi conne !! 5889 ' -battery Print out battery info (if available)\n'\ 6785 ' -x<mode> Test xset by togglin 5890 ' -x<mode> Test xset by toggling the given mode (on/off/standby/suspend)\n'\ 6786 ' -sysinfo Print out system inf 5891 ' -sysinfo Print out system info extracted from BIOS\n'\ 6787 ' -devinfo Print out the pm set 5892 ' -devinfo Print out the pm settings of all devices which support runtime suspend\n'\ 6788 ' -cmdinfo Print out all the pl << 6789 ' -flist Print the list of fu 5893 ' -flist Print the list of functions currently being captured in ftrace\n'\ 6790 ' -flistall Print all functions 5894 ' -flistall Print all functions capable of being captured in ftrace\n'\ 6791 ' -summary dir Create a summary of 5895 ' -summary dir Create a summary of tests in this dir [-genhtml builds missing html]\n'\ 6792 ' [redo]\n'\ 5896 ' [redo]\n'\ 6793 ' -ftrace ftracefile Create HTML o 5897 ' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)\n'\ 6794 ' -dmesg dmesgfile Create HTML o 5898 ' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)\n'\ 6795 '' % (sysvals.title, sysvals.version, !! 5899 '' % (sysvals.title, sysvals.version, sysvals.suspendmode)) 6796 return True 5900 return True 6797 5901 6798 # ----------------- MAIN -------------------- 5902 # ----------------- MAIN -------------------- 6799 # exec start (skipped if script is loaded as 5903 # exec start (skipped if script is loaded as library) 6800 if __name__ == '__main__': 5904 if __name__ == '__main__': 6801 genhtml = False 5905 genhtml = False 6802 cmd = '' 5906 cmd = '' 6803 simplecmds = ['-sysinfo', '-modes', ' 5907 simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall', 6804 '-devinfo', '-status', '-xon' !! 5908 '-devinfo', '-status', '-battery', '-xon', '-xoff', '-xstandby', 6805 '-xinit', '-xreset', '-xstat' !! 5909 '-xsuspend', '-xinit', '-xreset', '-xstat'] 6806 if '-f' in sys.argv: 5910 if '-f' in sys.argv: 6807 sysvals.cgskip = sysvals.conf 5911 sysvals.cgskip = sysvals.configFile('cgskip.txt') 6808 # loop through the command line argum 5912 # loop through the command line arguments 6809 args = iter(sys.argv[1:]) 5913 args = iter(sys.argv[1:]) 6810 for arg in args: 5914 for arg in args: 6811 if(arg == '-m'): 5915 if(arg == '-m'): 6812 try: 5916 try: 6813 val = next(ar !! 5917 val = args.next() 6814 except: 5918 except: 6815 doError('No m 5919 doError('No mode supplied', True) 6816 if val == 'command' a 5920 if val == 'command' and not sysvals.testcommand: 6817 doError('No c 5921 doError('No command supplied for mode "command"', True) 6818 sysvals.suspendmode = 5922 sysvals.suspendmode = val 6819 elif(arg in simplecmds): 5923 elif(arg in simplecmds): 6820 cmd = arg[1:] 5924 cmd = arg[1:] 6821 elif(arg == '-h'): 5925 elif(arg == '-h'): 6822 printHelp() 5926 printHelp() 6823 sys.exit(0) 5927 sys.exit(0) 6824 elif(arg == '-v'): 5928 elif(arg == '-v'): 6825 pprint("Version %s" % 5929 pprint("Version %s" % sysvals.version) 6826 sys.exit(0) 5930 sys.exit(0) 6827 elif(arg == '-debugtiming'): << 6828 debugtiming = True << 6829 elif(arg == '-x2'): 5931 elif(arg == '-x2'): 6830 sysvals.execcount = 2 5932 sysvals.execcount = 2 6831 elif(arg == '-x2delay'): 5933 elif(arg == '-x2delay'): 6832 sysvals.x2delay = get 5934 sysvals.x2delay = getArgInt('-x2delay', args, 0, 60000) 6833 elif(arg == '-predelay'): 5935 elif(arg == '-predelay'): 6834 sysvals.predelay = ge 5936 sysvals.predelay = getArgInt('-predelay', args, 0, 60000) 6835 elif(arg == '-postdelay'): 5937 elif(arg == '-postdelay'): 6836 sysvals.postdelay = g 5938 sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000) 6837 elif(arg == '-f'): 5939 elif(arg == '-f'): 6838 sysvals.usecallgraph 5940 sysvals.usecallgraph = True 6839 elif(arg == '-ftop'): << 6840 sysvals.usecallgraph << 6841 sysvals.ftop = True << 6842 sysvals.usekprobes = << 6843 elif(arg == '-skiphtml'): 5941 elif(arg == '-skiphtml'): 6844 sysvals.skiphtml = Tr 5942 sysvals.skiphtml = True 6845 elif(arg == '-cgdump'): 5943 elif(arg == '-cgdump'): 6846 sysvals.cgdump = True 5944 sysvals.cgdump = True 6847 elif(arg == '-devdump'): 5945 elif(arg == '-devdump'): 6848 sysvals.devdump = Tru 5946 sysvals.devdump = True 6849 elif(arg == '-genhtml'): 5947 elif(arg == '-genhtml'): 6850 genhtml = True 5948 genhtml = True 6851 elif(arg == '-addlogs'): 5949 elif(arg == '-addlogs'): 6852 sysvals.dmesglog = sy 5950 sysvals.dmesglog = sysvals.ftracelog = True 6853 elif(arg == '-nologs'): << 6854 sysvals.dmesglog = sy << 6855 elif(arg == '-addlogdmesg'): 5951 elif(arg == '-addlogdmesg'): 6856 sysvals.dmesglog = Tr 5952 sysvals.dmesglog = True 6857 elif(arg == '-addlogftrace'): 5953 elif(arg == '-addlogftrace'): 6858 sysvals.ftracelog = T 5954 sysvals.ftracelog = True 6859 elif(arg == '-noturbostat'): << 6860 sysvals.tstat = False << 6861 elif(arg == '-verbose'): 5955 elif(arg == '-verbose'): 6862 sysvals.verbose = Tru 5956 sysvals.verbose = True 6863 elif(arg == '-proc'): 5957 elif(arg == '-proc'): 6864 sysvals.useprocmon = 5958 sysvals.useprocmon = True 6865 elif(arg == '-dev'): 5959 elif(arg == '-dev'): 6866 sysvals.usedevsrc = T 5960 sysvals.usedevsrc = True 6867 elif(arg == '-sync'): 5961 elif(arg == '-sync'): 6868 sysvals.sync = True 5962 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'): 5963 elif(arg == '-gzip'): 6876 sysvals.gzip = True 5964 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'): 5965 elif(arg == '-rs'): 6888 try: 5966 try: 6889 val = next(ar !! 5967 val = args.next() 6890 except: 5968 except: 6891 doError('-rs 5969 doError('-rs requires "enable" or "disable"', True) 6892 if val.lower() in swi 5970 if val.lower() in switchvalues: 6893 if val.lower( 5971 if val.lower() in switchoff: 6894 sysva 5972 sysvals.rs = -1 6895 else: 5973 else: 6896 sysva 5974 sysvals.rs = 1 6897 else: 5975 else: 6898 doError('inva 5976 doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True) 6899 elif(arg == '-display'): 5977 elif(arg == '-display'): 6900 try: 5978 try: 6901 val = next(ar !! 5979 val = args.next() 6902 except: 5980 except: 6903 doError('-dis 5981 doError('-display requires an mode value', True) 6904 disopt = ['on', 'off' 5982 disopt = ['on', 'off', 'standby', 'suspend'] 6905 if val.lower() not in 5983 if val.lower() not in disopt: 6906 doError('vali 5984 doError('valid display mode values are %s' % disopt, True) 6907 sysvals.display = val 5985 sysvals.display = val.lower() 6908 elif(arg == '-maxdepth'): 5986 elif(arg == '-maxdepth'): 6909 sysvals.max_graph_dep 5987 sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000) 6910 elif(arg == '-rtcwake'): 5988 elif(arg == '-rtcwake'): 6911 try: 5989 try: 6912 val = next(ar !! 5990 val = args.next() 6913 except: 5991 except: 6914 doError('No r 5992 doError('No rtcwake time supplied', True) 6915 if val.lower() in swi 5993 if val.lower() in switchoff: 6916 sysvals.rtcwa 5994 sysvals.rtcwake = False 6917 else: 5995 else: 6918 sysvals.rtcwa 5996 sysvals.rtcwake = True 6919 sysvals.rtcwa 5997 sysvals.rtcwaketime = getArgInt('-rtcwake', val, 0, 3600, False) 6920 elif(arg == '-timeprec'): 5998 elif(arg == '-timeprec'): 6921 sysvals.setPrecision( 5999 sysvals.setPrecision(getArgInt('-timeprec', args, 0, 6)) 6922 elif(arg == '-mindev'): 6000 elif(arg == '-mindev'): 6923 sysvals.mindevlen = g 6001 sysvals.mindevlen = getArgFloat('-mindev', args, 0.0, 10000.0) 6924 elif(arg == '-mincg'): 6002 elif(arg == '-mincg'): 6925 sysvals.mincglen = ge 6003 sysvals.mincglen = getArgFloat('-mincg', args, 0.0, 10000.0) 6926 elif(arg == '-bufsize'): 6004 elif(arg == '-bufsize'): 6927 sysvals.bufsize = get 6005 sysvals.bufsize = getArgInt('-bufsize', args, 1, 1024*1024*8) 6928 elif(arg == '-cgtest'): 6006 elif(arg == '-cgtest'): 6929 sysvals.cgtest = getA 6007 sysvals.cgtest = getArgInt('-cgtest', args, 0, 1) 6930 elif(arg == '-cgphase'): 6008 elif(arg == '-cgphase'): 6931 try: 6009 try: 6932 val = next(ar !! 6010 val = args.next() 6933 except: 6011 except: 6934 doError('No p 6012 doError('No phase name supplied', True) 6935 d = Data(0) 6013 d = Data(0) 6936 if val not in d.phase 6014 if val not in d.phasedef: 6937 doError('inva 6015 doError('invalid phase --> (%s: %s), valid phases are %s'\ 6938 % (ar 6016 % (arg, val, d.phasedef.keys()), True) 6939 sysvals.cgphase = val 6017 sysvals.cgphase = val 6940 elif(arg == '-cgfilter'): 6018 elif(arg == '-cgfilter'): 6941 try: 6019 try: 6942 val = next(ar !! 6020 val = args.next() 6943 except: 6021 except: 6944 doError('No c 6022 doError('No callgraph functions supplied', True) 6945 sysvals.setCallgraphF 6023 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'): 6024 elif(arg == '-cgskip'): 6953 try: 6025 try: 6954 val = next(ar !! 6026 val = args.next() 6955 except: 6027 except: 6956 doError('No f 6028 doError('No file supplied', True) 6957 if val.lower() in swi 6029 if val.lower() in switchoff: 6958 sysvals.cgski 6030 sysvals.cgskip = '' 6959 else: 6031 else: 6960 sysvals.cgski 6032 sysvals.cgskip = sysvals.configFile(val) 6961 if(not sysval 6033 if(not sysvals.cgskip): 6962 doErr 6034 doError('%s does not exist' % sysvals.cgskip) 6963 elif(arg == '-callloop-maxgap 6035 elif(arg == '-callloop-maxgap'): 6964 sysvals.callloopmaxga 6036 sysvals.callloopmaxgap = getArgFloat('-callloop-maxgap', args, 0.0, 1.0) 6965 elif(arg == '-callloop-maxlen 6037 elif(arg == '-callloop-maxlen'): 6966 sysvals.callloopmaxle 6038 sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0) 6967 elif(arg == '-cmd'): 6039 elif(arg == '-cmd'): 6968 try: 6040 try: 6969 val = next(ar !! 6041 val = args.next() 6970 except: 6042 except: 6971 doError('No c 6043 doError('No command string supplied', True) 6972 sysvals.testcommand = 6044 sysvals.testcommand = val 6973 sysvals.suspendmode = 6045 sysvals.suspendmode = 'command' 6974 elif(arg == '-expandcg'): 6046 elif(arg == '-expandcg'): 6975 sysvals.cgexp = True 6047 sysvals.cgexp = True 6976 elif(arg == '-srgap'): 6048 elif(arg == '-srgap'): 6977 sysvals.srgap = 5 6049 sysvals.srgap = 5 6978 elif(arg == '-maxfail'): << 6979 sysvals.maxfail = get << 6980 elif(arg == '-multi'): 6050 elif(arg == '-multi'): 6981 try: !! 6051 sysvals.multitest['run'] = True 6982 c, d = next(a !! 6052 sysvals.multitest['count'] = getArgInt('-multi n d (exec count)', args, 2, 1000000) 6983 except: !! 6053 sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600) 6984 doError('-mul << 6985 sysvals.multiinit(c, << 6986 elif(arg == '-o'): 6054 elif(arg == '-o'): 6987 try: 6055 try: 6988 val = next(ar !! 6056 val = args.next() 6989 except: 6057 except: 6990 doError('No s 6058 doError('No subdirectory name supplied', True) 6991 sysvals.outdir = sysv 6059 sysvals.outdir = sysvals.setOutputFolder(val) 6992 elif(arg == '-config'): 6060 elif(arg == '-config'): 6993 try: 6061 try: 6994 val = next(ar !! 6062 val = args.next() 6995 except: 6063 except: 6996 doError('No t 6064 doError('No text file supplied', True) 6997 file = sysvals.config 6065 file = sysvals.configFile(val) 6998 if(not file): 6066 if(not file): 6999 doError('%s d 6067 doError('%s does not exist' % val) 7000 configFromFile(file) 6068 configFromFile(file) 7001 elif(arg == '-fadd'): 6069 elif(arg == '-fadd'): 7002 try: 6070 try: 7003 val = next(ar !! 6071 val = args.next() 7004 except: 6072 except: 7005 doError('No t 6073 doError('No text file supplied', True) 7006 file = sysvals.config 6074 file = sysvals.configFile(val) 7007 if(not file): 6075 if(not file): 7008 doError('%s d 6076 doError('%s does not exist' % val) 7009 sysvals.addFtraceFilt 6077 sysvals.addFtraceFilterFunctions(file) 7010 elif(arg == '-dmesg'): 6078 elif(arg == '-dmesg'): 7011 try: 6079 try: 7012 val = next(ar !! 6080 val = args.next() 7013 except: 6081 except: 7014 doError('No d 6082 doError('No dmesg file supplied', True) 7015 sysvals.notestrun = T 6083 sysvals.notestrun = True 7016 sysvals.dmesgfile = v 6084 sysvals.dmesgfile = val 7017 if(os.path.exists(sys 6085 if(os.path.exists(sysvals.dmesgfile) == False): 7018 doError('%s d 6086 doError('%s does not exist' % sysvals.dmesgfile) 7019 elif(arg == '-ftrace'): 6087 elif(arg == '-ftrace'): 7020 try: 6088 try: 7021 val = next(ar !! 6089 val = args.next() 7022 except: 6090 except: 7023 doError('No f 6091 doError('No ftrace file supplied', True) 7024 sysvals.notestrun = T 6092 sysvals.notestrun = True 7025 sysvals.ftracefile = 6093 sysvals.ftracefile = val 7026 if(os.path.exists(sys 6094 if(os.path.exists(sysvals.ftracefile) == False): 7027 doError('%s d 6095 doError('%s does not exist' % sysvals.ftracefile) 7028 elif(arg == '-summary'): 6096 elif(arg == '-summary'): 7029 try: 6097 try: 7030 val = next(ar !! 6098 val = args.next() 7031 except: 6099 except: 7032 doError('No d 6100 doError('No directory supplied', True) 7033 cmd = 'summary' 6101 cmd = 'summary' 7034 sysvals.outdir = val 6102 sysvals.outdir = val 7035 sysvals.notestrun = T 6103 sysvals.notestrun = True 7036 if(os.path.isdir(val) 6104 if(os.path.isdir(val) == False): 7037 doError('%s i 6105 doError('%s is not accesible' % val) 7038 elif(arg == '-filter'): 6106 elif(arg == '-filter'): 7039 try: 6107 try: 7040 val = next(ar !! 6108 val = args.next() 7041 except: 6109 except: 7042 doError('No d 6110 doError('No devnames supplied', True) 7043 sysvals.setDeviceFilt 6111 sysvals.setDeviceFilter(val) 7044 elif(arg == '-result'): 6112 elif(arg == '-result'): 7045 try: 6113 try: 7046 val = next(ar !! 6114 val = args.next() 7047 except: 6115 except: 7048 doError('No r 6116 doError('No result file supplied', True) 7049 sysvals.result = val 6117 sysvals.result = val 7050 sysvals.signalHandler 6118 sysvals.signalHandlerInit() 7051 else: 6119 else: 7052 doError('Invalid argu 6120 doError('Invalid argument: '+arg, True) 7053 6121 7054 # compatibility errors 6122 # compatibility errors 7055 if(sysvals.usecallgraph and sysvals.u 6123 if(sysvals.usecallgraph and sysvals.usedevsrc): 7056 doError('-dev is not compatib 6124 doError('-dev is not compatible with -f') 7057 if(sysvals.usecallgraph and sysvals.u 6125 if(sysvals.usecallgraph and sysvals.useprocmon): 7058 doError('-proc is not compati 6126 doError('-proc is not compatible with -f') 7059 6127 7060 if sysvals.usecallgraph and sysvals.c 6128 if sysvals.usecallgraph and sysvals.cgskip: 7061 sysvals.vprint('Using cgskip 6129 sysvals.vprint('Using cgskip file: %s' % sysvals.cgskip) 7062 sysvals.setCallgraphBlacklist 6130 sysvals.setCallgraphBlacklist(sysvals.cgskip) 7063 6131 7064 # callgraph size cannot exceed device 6132 # callgraph size cannot exceed device size 7065 if sysvals.mincglen < sysvals.mindevl 6133 if sysvals.mincglen < sysvals.mindevlen: 7066 sysvals.mincglen = sysvals.mi 6134 sysvals.mincglen = sysvals.mindevlen 7067 6135 7068 # remove existing buffers before calc 6136 # remove existing buffers before calculating memory 7069 if(sysvals.usecallgraph or sysvals.us 6137 if(sysvals.usecallgraph or sysvals.usedevsrc): 7070 sysvals.fsetVal('16', 'buffer 6138 sysvals.fsetVal('16', 'buffer_size_kb') 7071 sysvals.cpuInfo() 6139 sysvals.cpuInfo() 7072 6140 7073 # just run a utility command and exit 6141 # just run a utility command and exit 7074 if(cmd != ''): 6142 if(cmd != ''): 7075 ret = 0 6143 ret = 0 7076 if(cmd == 'status'): 6144 if(cmd == 'status'): 7077 if not statusCheck(Tr 6145 if not statusCheck(True): 7078 ret = 1 6146 ret = 1 7079 elif(cmd == 'fpdt'): 6147 elif(cmd == 'fpdt'): 7080 if not getFPDT(True): 6148 if not getFPDT(True): 7081 ret = 1 6149 ret = 1 >> 6150 elif(cmd == 'battery'): >> 6151 out = getBattery() >> 6152 if out: >> 6153 pprint('AC Connect : %s\nBattery Charge: %d' % out) >> 6154 else: >> 6155 pprint('no battery found') >> 6156 ret = 1 7082 elif(cmd == 'sysinfo'): 6157 elif(cmd == 'sysinfo'): 7083 sysvals.printSystemIn 6158 sysvals.printSystemInfo(True) 7084 elif(cmd == 'devinfo'): 6159 elif(cmd == 'devinfo'): 7085 deviceInfo() 6160 deviceInfo() 7086 elif(cmd == 'modes'): 6161 elif(cmd == 'modes'): 7087 pprint(getModes()) !! 6162 print getModes() 7088 elif(cmd == 'flist'): 6163 elif(cmd == 'flist'): 7089 sysvals.getFtraceFilt 6164 sysvals.getFtraceFilterFunctions(True) 7090 elif(cmd == 'flistall'): 6165 elif(cmd == 'flistall'): 7091 sysvals.getFtraceFilt 6166 sysvals.getFtraceFilterFunctions(False) 7092 elif(cmd == 'summary'): 6167 elif(cmd == 'summary'): 7093 runSummary(sysvals.ou 6168 runSummary(sysvals.outdir, True, genhtml) 7094 elif(cmd in ['xon', 'xoff', ' 6169 elif(cmd in ['xon', 'xoff', 'xstandby', 'xsuspend', 'xinit', 'xreset']): 7095 sysvals.verbose = Tru 6170 sysvals.verbose = True 7096 ret = sysvals.display !! 6171 ret = displayControl(cmd[1:]) 7097 elif(cmd == 'xstat'): 6172 elif(cmd == 'xstat'): 7098 pprint('Display Statu !! 6173 pprint('Display Status: %s' % displayControl('stat').upper()) 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) 6174 sys.exit(ret) 7109 6175 7110 # if instructed, re-analyze existing 6176 # if instructed, re-analyze existing data files 7111 if(sysvals.notestrun): 6177 if(sysvals.notestrun): 7112 stamp = rerunTest(sysvals.out !! 6178 stamp = rerunTest() 7113 sysvals.outputResult(stamp) 6179 sysvals.outputResult(stamp) 7114 sys.exit(0) 6180 sys.exit(0) 7115 6181 7116 # verify that we can run a test 6182 # verify that we can run a test 7117 error = statusCheck() 6183 error = statusCheck() 7118 if(error): 6184 if(error): 7119 doError(error) 6185 doError(error) 7120 6186 7121 # extract mem/disk extra modes and co 6187 # extract mem/disk extra modes and convert 7122 mode = sysvals.suspendmode 6188 mode = sysvals.suspendmode 7123 if mode.startswith('mem'): 6189 if mode.startswith('mem'): 7124 memmode = mode.split('-', 1)[ 6190 memmode = mode.split('-', 1)[-1] if '-' in mode else 'deep' 7125 if memmode == 'shallow': 6191 if memmode == 'shallow': 7126 mode = 'standby' 6192 mode = 'standby' 7127 elif memmode == 's2idle': 6193 elif memmode == 's2idle': 7128 mode = 'freeze' 6194 mode = 'freeze' 7129 else: 6195 else: 7130 mode = 'mem' 6196 mode = 'mem' 7131 sysvals.memmode = memmode 6197 sysvals.memmode = memmode 7132 sysvals.suspendmode = mode 6198 sysvals.suspendmode = mode 7133 if mode.startswith('disk-'): 6199 if mode.startswith('disk-'): 7134 sysvals.diskmode = mode.split 6200 sysvals.diskmode = mode.split('-', 1)[-1] 7135 sysvals.suspendmode = 'disk' 6201 sysvals.suspendmode = 'disk' >> 6202 7136 sysvals.systemInfo(dmidecode(sysvals. 6203 sysvals.systemInfo(dmidecode(sysvals.mempath)) 7137 6204 7138 failcnt, ret = 0, 0 !! 6205 setRuntimeSuspend(True) >> 6206 if sysvals.display: >> 6207 displayControl('init') >> 6208 ret = 0 7139 if sysvals.multitest['run']: 6209 if sysvals.multitest['run']: 7140 # run multiple tests in a sep 6210 # run multiple tests in a separate subdirectory 7141 if not sysvals.outdir: 6211 if not sysvals.outdir: 7142 if 'time' in sysvals. !! 6212 s = 'suspend-x%d' % sysvals.multitest['count'] 7143 s = '-%dm' % !! 6213 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. 6214 if not os.path.isdir(sysvals.outdir): 7148 os.makedirs(sysvals.o !! 6215 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 6216 for i in range(sysvals.multitest['count']): 7154 sysvals.multistat(Tru !! 6217 if(i != 0): 7155 if i != 0 and sysvals << 7156 pprint('Waiti 6218 pprint('Waiting %d seconds...' % (sysvals.multitest['delay'])) 7157 time.sleep(sy 6219 time.sleep(sysvals.multitest['delay']) >> 6220 pprint('TEST (%d/%d) START' % (i+1, sysvals.multitest['count'])) 7158 fmt = 'suspend-%y%m%d 6221 fmt = 'suspend-%y%m%d-%H%M%S' 7159 sysvals.testdir = os. 6222 sysvals.testdir = os.path.join(sysvals.outdir, datetime.now().strftime(fmt)) 7160 ret = runTest(i+1, no !! 6223 ret = runTest(i+1) 7161 failcnt = 0 if not re !! 6224 pprint('TEST (%d/%d) COMPLETE' % (i+1, sysvals.multitest['count'])) 7162 if sysvals.maxfail > !! 6225 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: 6226 if not sysvals.skiphtml: 7170 runSummary(sysvals.ou 6227 runSummary(sysvals.outdir, False, False) 7171 sysvals.sudoUserchown(sysvals 6228 sysvals.sudoUserchown(sysvals.outdir) 7172 else: 6229 else: 7173 if sysvals.outdir: 6230 if sysvals.outdir: 7174 sysvals.testdir = sys 6231 sysvals.testdir = sysvals.outdir 7175 # run the test in the current 6232 # run the test in the current directory 7176 ret = runTest() 6233 ret = runTest() 7177 << 7178 # reset to default values after testi << 7179 if sysvals.display: 6234 if sysvals.display: 7180 sysvals.displayControl('reset !! 6235 displayControl('reset') 7181 if sysvals.rs != 0: !! 6236 setRuntimeSuspend(False) 7182 sysvals.setRuntimeSuspend(Fal << 7183 sys.exit(ret) 6237 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.