12e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 22e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang# Use of this source code is governed by a BSD-style license that can be 32e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang# found in the LICENSE file. 42e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 52e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangimport hashlib, logging, multiprocessing, os, re, time 62e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangfrom autotest_lib.client.bin import test, utils 72e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangfrom autotest_lib.client.common_lib import error 82e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangfrom autotest_lib.client.cros import sys_power 92e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 102e6ecda978a5d086c76ca014531ea781fd3d75aeMichael SpangSUSPEND_BURN_SECONDS = 10 112e6ecda978a5d086c76ca014531ea781fd3d75aeMichael SpangRESUME_BURN_SECONDS = 5 122e6ecda978a5d086c76ca014531ea781fd3d75aeMichael SpangMIN_CPU_USAGE = .95 132e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 142e6ecda978a5d086c76ca014531ea781fd3d75aeMichael SpangPROC_STAT_CPU_FIELDS = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 152e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 'softirq', 'steal', 'guest', 'guest_nice'] 162e6ecda978a5d086c76ca014531ea781fd3d75aeMichael SpangPROC_STAT_CPU_IDLE_FIELDS = ['idle', 'iowait'] 172e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 18ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny ChiuSYSFS_CPUQUIET_ENABLE = '/sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable' 192e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 202e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangdef cpu_stress(): 212e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang sha512_hash = open('/dev/urandom', 'r').read(64) 222e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang while True: 232e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang sha512_hash = hashlib.sha512(sha512_hash).digest() 242e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 252e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 262e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangdef get_system_times(): 272e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang proc_stat = utils.read_file('/proc/stat') 282e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang for line in proc_stat.split('\n'): 292e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang if line.startswith('cpu '): 302e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang times = line[4:].strip().split(' ') 312e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang times = [int(jiffies) for jiffies in times] 322e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang return dict(zip(PROC_STAT_CPU_FIELDS, times)) 332e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 342e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 352e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangdef get_avg_cpu_usage(pre_times, post_times): 362e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang diff_times = {} 372e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 382e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang for field in PROC_STAT_CPU_FIELDS: 392e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang diff_times[field] = post_times[field] - pre_times[field] 402e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 412e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang idle_time = sum(diff_times[field] for field in PROC_STAT_CPU_IDLE_FIELDS) 422e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang total_time = sum(diff_times[field] for field in PROC_STAT_CPU_FIELDS) 432e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 442e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang return float(total_time - idle_time) / total_time 452e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 462e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 472e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangdef sleep_and_measure_cpu(sleep_seconds): 482e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang pre_times = get_system_times() 492e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang time.sleep(sleep_seconds) 502e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang post_times = get_system_times() 512e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 522e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang avg_cpu_usage = get_avg_cpu_usage(pre_times, post_times) 532e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.info('average CPU utilization, last %ds: %s%%', 542e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang sleep_seconds, avg_cpu_usage * 100.) 552e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang return avg_cpu_usage 562e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 572e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 582e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spangclass power_HotCPUSuspend(test.test): 592e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang """Suspend the system with 100% CPU usage.""" 602e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 612e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang version = 1 622e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 63ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu def initialize(self): 64ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu # Store the setting if the system has CPUQuiet feature 65ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu if os.path.exists(SYSFS_CPUQUIET_ENABLE): 66ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu self.is_cpuquiet_enabled = utils.read_file(SYSFS_CPUQUIET_ENABLE) 67ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu utils.write_one_line(SYSFS_CPUQUIET_ENABLE, '0') 68ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu 692e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang def run_once(self): 702e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # create processs pool with enough workers to spin all CPUs 712e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang cpus = multiprocessing.cpu_count() 722e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.info('found %d cpus', cpus) 732e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang workers = max(16, cpus * 2) 742e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang pool = multiprocessing.Pool(workers) 752e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 762e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang try: 772e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # fill all CPUs with a spinning task 782e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.info('starting %d workers', workers) 792e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang results = [pool.apply_async(cpu_stress) for _ in xrange(workers)] 802e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 812e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # wait for things to settle 822e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.info('spinning for %d seconds', SUSPEND_BURN_SECONDS) 832e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang if sleep_and_measure_cpu(SUSPEND_BURN_SECONDS) < MIN_CPU_USAGE: 842e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # There should be no idle time accounted while we're spinning. 852e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang raise error.TestError('unexpected CPU idle time while spinning') 862e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 872e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # go to suspend 880537d52c7b85e9454336449f2bc9efae5a4983a4Julius Werner sys_power.kernel_suspend(10) 892e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 902e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # keep spinning after userland resumes 912e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.info('spinning for %d more seconds', RESUME_BURN_SECONDS) 922e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang if sleep_and_measure_cpu(RESUME_BURN_SECONDS) < MIN_CPU_USAGE: 932e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # There should be no idle time accounted while we're spinning. 942e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang raise error.TestError('unexpected CPU idle time after resume') 952e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 962e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # check workers: if computation completed, something is wrong 972e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang for result in results: 982e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang if result.ready(): 992e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.error('worker finished: %s', result.get()) 1002e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang raise error.TestError('worker terminated!') 1012e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang 1022e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang finally: 1032e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang # kill off the workers 1042e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang logging.info('killing %d workers', workers) 1052e6ecda978a5d086c76ca014531ea781fd3d75aeMichael Spang pool.terminate() 106ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu 107ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu def cleanup(self): 108ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu # Restore the original setting if system has CPUQuiet feature 109ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu if os.path.exists(SYSFS_CPUQUIET_ENABLE): 110ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu utils.open_write_close( 111ffd6a4b3f6c934f04392a53b53d5595a23b658dbPenny Chiu SYSFS_CPUQUIET_ENABLE, self.is_cpuquiet_enabled) 112