site_utils.py revision bf67617f8f4cc06f0b63fae3c60f3cc1d228c40b
1#pylint: disable-msg=C0111 2 3# Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7import logging, os, platform, re, signal, tempfile, time, uuid 8from autotest_lib.client.common_lib import error 9from autotest_lib.client.common_lib import utils 10from autotest_lib.client.bin import base_utils 11 12class TimeoutError(error.TestError): 13 """Error raised when we time out when waiting on a condition.""" 14 pass 15 16 17class Crossystem(object): 18 """A wrapper for the crossystem utility.""" 19 20 def __init__(self, client): 21 self.cros_system_data = {} 22 self._client = client 23 24 def init(self): 25 self.cros_system_data = {} 26 (_, fname) = tempfile.mkstemp() 27 f = open(fname, 'w') 28 self._client.run('crossystem', stdout_tee=f) 29 f.close() 30 text = utils.read_file(fname) 31 for line in text.splitlines(): 32 assignment_string = line.split('#')[0] 33 if not assignment_string.count('='): 34 continue 35 (name, value) = assignment_string.split('=', 1) 36 self.cros_system_data[name.strip()] = value.strip() 37 os.remove(fname) 38 39 def __getattr__(self, name): 40 """ 41 Retrieve a crosssystem attribute. 42 43 The call crossystemobject.name() will return the crossystem reported 44 string. 45 """ 46 return lambda : self.cros_system_data[name] 47 48 49def get_oldest_pid_by_name(name): 50 """ 51 Return the oldest pid of a process whose name perfectly matches |name|. 52 53 name is an egrep expression, which will be matched against the entire name 54 of processes on the system. For example: 55 56 get_oldest_pid_by_name('chrome') 57 58 on a system running 59 8600 ? 00:00:04 chrome 60 8601 ? 00:00:00 chrome 61 8602 ? 00:00:00 chrome-sandbox 62 63 would return 8600, as that's the oldest process that matches. 64 chrome-sandbox would not be matched. 65 66 Arguments: 67 name: egrep expression to match. Will be anchored at the beginning and 68 end of the match string. 69 70 Returns: 71 pid as an integer, or None if one cannot be found. 72 73 Raises: 74 ValueError if pgrep returns something odd. 75 """ 76 str_pid = utils.system_output( 77 'pgrep -o ^%s$' % name, ignore_status=True).rstrip() 78 if str_pid: 79 return int(str_pid) 80 81 82def get_oldest_by_name(name): 83 """Return pid and command line of oldest process whose name matches |name|. 84 85 @param name: egrep expression to match desired process name. 86 @return: A tuple of (pid, command_line) of the oldest process whose name 87 matches |name|. 88 89 """ 90 pid = get_oldest_pid_by_name(name) 91 if pid: 92 command_line = utils.system_output('ps -p %i -o command=' % pid, 93 ignore_status=True).rstrip() 94 return (pid, command_line) 95 96 97def get_chrome_remote_debugging_port(): 98 """Returns remote debugging port for Chrome. 99 100 Parse chrome process's command line argument to get the remote debugging 101 port. 102 """ 103 pid, command = get_oldest_by_name('chrome') 104 matches = re.search('--remote-debugging-port=([0-9]+)', command) 105 if matches: 106 return int(matches.group(1)) 107 108 109def get_process_list(name, command_line=None): 110 """ 111 Return the list of pid for matching process |name command_line|. 112 113 on a system running 114 31475 ? 0:06 /opt/google/chrome/chrome --allow-webui-compositing - 115 31478 ? 0:00 /opt/google/chrome/chrome-sandbox /opt/google/chrome/ 116 31485 ? 0:00 /opt/google/chrome/chrome --type=zygote --log-level=1 117 31532 ? 1:05 /opt/google/chrome/chrome --type=renderer 118 119 get_process_list('chrome') 120 would return ['31475', '31485', '31532'] 121 122 get_process_list('chrome', '--type=renderer') 123 would return ['31532'] 124 125 Arguments: 126 name: process name to search for. If command_line is provided, name is 127 matched against full command line. If command_line is not provided, 128 name is only matched against the process name. 129 command line: when command line is passed, the full process command line 130 is used for matching. 131 132 Returns: 133 list of PIDs of the matching processes. 134 135 """ 136 # TODO(rohitbm) crbug.com/268861 137 flag = '-x' if not command_line else '-f' 138 name = '\'%s.*%s\'' % (name, command_line) if command_line else name 139 str_pid = utils.system_output( 140 'pgrep %s %s' % (flag, name), ignore_status=True).rstrip() 141 return str_pid 142 143 144def nuke_process_by_name(name, with_prejudice=False): 145 try: 146 pid = get_oldest_pid_by_name(name) 147 except Exception as e: 148 logging.error(e) 149 return 150 if pid is None: 151 raise error.AutoservPidAlreadyDeadError( 152 'No process matching %s.' % name) 153 if with_prejudice: 154 utils.nuke_pid(pid, [signal.SIGKILL]) 155 else: 156 utils.nuke_pid(pid) 157 158 159def poll_for_condition( 160 condition, exception=None, timeout=10, sleep_interval=0.1, desc=None): 161 """Poll until a condition becomes true. 162 163 Arguments: 164 condition: function taking no args and returning bool 165 exception: exception to throw if condition doesn't become true 166 timeout: maximum number of seconds to wait 167 sleep_interval: time to sleep between polls 168 desc: description of default TimeoutError used if 'exception' is None 169 170 Returns: 171 The true value that caused the poll loop to terminate. 172 173 Raises: 174 'exception' arg if supplied; site_utils.TimeoutError otherwise 175 """ 176 start_time = time.time() 177 while True: 178 value = condition() 179 if value: 180 return value 181 if time.time() + sleep_interval - start_time > timeout: 182 if exception: 183 logging.error(exception) 184 raise exception 185 186 if desc: 187 desc = 'Timed out waiting for condition: %s' % desc 188 else: 189 desc = 'Timed out waiting for unnamed condition' 190 logging.error(desc) 191 raise TimeoutError, desc 192 193 time.sleep(sleep_interval) 194 195 196def save_vm_state(checkpoint): 197 """Saves the current state of the virtual machine. 198 199 This function is a NOOP if the test is not running under a virtual machine 200 with the USB serial port redirected. 201 202 Arguments: 203 checkpoint - Name used to identify this state 204 205 Returns: 206 None 207 """ 208 # The QEMU monitor has been redirected to the guest serial port located at 209 # /dev/ttyUSB0. To save the state of the VM, we just send the 'savevm' 210 # command to the serial port. 211 proc = platform.processor() 212 if 'QEMU' in proc and os.path.exists('/dev/ttyUSB0'): 213 logging.info('Saving VM state "%s"', checkpoint) 214 serial = open('/dev/ttyUSB0', 'w') 215 serial.write("savevm %s\r\n" % checkpoint) 216 logging.info('Done saving VM state "%s"', checkpoint) 217 218 219def check_raw_dmesg(dmesg, message_level, whitelist): 220 """Checks dmesg for unexpected warnings. 221 222 This function parses dmesg for message with message_level <= message_level 223 which do not appear in the whitelist. 224 225 Arguments: 226 dmesg - string containing raw dmesg buffer 227 message_level - minimum message priority to check 228 whitelist - messages to ignore 229 230 Returns: 231 List of unexpected warnings 232 """ 233 whitelist_re = re.compile(r'(%s)' % '|'.join(whitelist)) 234 unexpected = [] 235 for line in dmesg.splitlines(): 236 if int(line[1]) <= message_level: 237 stripped_line = line.split('] ', 1)[1] 238 if whitelist_re.search(stripped_line): 239 continue 240 unexpected.append(stripped_line) 241 return unexpected 242 243def verify_mesg_set(mesg, regex, whitelist): 244 """Verifies that the exact set of messages are present in a text. 245 246 This function finds all strings in the text matching a certain regex, and 247 then verifies that all expected strings are present in the set, and no 248 unexpected strings are there. 249 250 Arguments: 251 mesg - the mutiline text to be scanned 252 regex - regular expression to match 253 whitelist - messages to find in the output, a list of strings 254 (potentially regexes) to look for in the filtered output. All these 255 strings must be there, and no other strings should be present in the 256 filtered output. 257 258 Returns: 259 string of inconsistent findings (i.e. an empty string on success). 260 """ 261 262 rv = [] 263 264 missing_strings = [] 265 present_strings = [] 266 for line in mesg.splitlines(): 267 if not re.search(r'%s' % regex, line): 268 continue 269 present_strings.append(line.split('] ', 1)[1]) 270 271 for string in whitelist: 272 for present_string in list(present_strings): 273 if re.search(r'^%s$' % string, present_string): 274 present_strings.remove(present_string) 275 break 276 else: 277 missing_strings.append(string) 278 279 if present_strings: 280 rv.append('unexpected strings:') 281 rv.extend(present_strings) 282 if missing_strings: 283 rv.append('missing strings:') 284 rv.extend(missing_strings) 285 286 return '\n'.join(rv) 287 288 289def target_is_pie(): 290 """Returns whether the toolchain produces a PIE (position independent 291 executable) by default. 292 293 Arguments: 294 None 295 296 Returns: 297 True if the target toolchain produces a PIE by default. 298 False otherwise. 299 """ 300 301 302 command = 'echo | ${CC} -E -dD -P - | grep -i pie' 303 result = utils.system_output(command, retain_output=True, 304 ignore_status=True) 305 if re.search('#define __PIE__', result): 306 return True 307 else: 308 return False 309 310def target_is_x86(): 311 """Returns whether the toolchain produces an x86 object 312 313 Arguments: 314 None 315 316 Returns: 317 True if the target toolchain produces an x86 object 318 False otherwise. 319 """ 320 321 322 command = 'echo | ${CC} -E -dD -P - | grep -i 86' 323 result = utils.system_output(command, retain_output=True, 324 ignore_status=True) 325 if re.search('__i386__', result) or re.search('__x86_64__', result): 326 return True 327 else: 328 return False 329 330def mounts(): 331 ret = [] 332 for line in file('/proc/mounts'): 333 m = re.match(r'(?P<src>\S+) (?P<dest>\S+) (?P<type>\S+) (?P<opts>\S+).*', line) 334 if m: 335 ret.append(m.groupdict()) 336 return ret 337 338def is_mountpoint(path): 339 return path in [ m['dest'] for m in mounts() ] 340 341def require_mountpoint(path): 342 """ 343 Raises an exception if path is not a mountpoint. 344 """ 345 if not is_mountpoint(path): 346 raise error.TestFail('Path not mounted: "%s"' % path) 347 348def random_username(): 349 return str(uuid.uuid4()) + '@example.com' 350 351 352def parse_cmd_output(command, run_method=utils.run): 353 """Runs a command on a host object to retrieve host attributes. 354 355 The command should output to stdout in the format of: 356 <key> = <value> # <optional_comment> 357 358 359 @param command: Command to execute on the host. 360 @param run_method: Function to use to execute the command. Defaults to 361 utils.run so that the command will be executed locally. 362 Can be replace with a host.run call so that it will 363 execute on a DUT or external machine. Method must accept 364 a command argument, stdout_tee and stderr_tee args and 365 return a result object with a string attribute stdout 366 which will be parsed. 367 368 @returns a dictionary mapping host attributes to their values. 369 """ 370 result = {} 371 # Suppresses stdout so that the files are not printed to the logs. 372 cmd_result = run_method(command, stdout_tee=None, stderr_tee=None) 373 for line in cmd_result.stdout.splitlines(): 374 # Lines are of the format "<key> = <value> # <comment>" 375 key_value = re.match('^\s*(?P<key>[^ ]+)\s*=\s*(?P<value>[^ ]+)' 376 '(?:\s*#.*)?$', line) 377 if key_value: 378 result[key_value.group('key')] = key_value.group('value') 379 return result 380 381 382def set_from_keyval_output(out, delimiter=' '): 383 """Parse delimiter-separated key-val output into a set of tuples. 384 385 Output is expected to be multiline text output from a command. 386 Stuffs the key-vals into tuples in a set to be later compared. 387 388 e.g. deactivated 0 389 disableForceClear 0 390 ==> set(('deactivated', '0'), ('disableForceClear', '0')) 391 392 @param out: multiple lines of space-separated key-val pairs. 393 @param delimiter: character that separates key from val. Usually a 394 space but may be '=' or something else. 395 @return set of key-val tuples. 396 """ 397 results = set() 398 kv_match_re = re.compile('([^ ]+)%s(.*)' % delimiter) 399 for linecr in out.splitlines(): 400 match = kv_match_re.match(linecr.strip()) 401 if match: 402 results.add((match.group(1), match.group(2))) 403 return results 404 405 406def get_cpu_usage(): 407 """Returns machine's CPU usage. 408 409 This function uses /proc/stat to identify CPU usage. 410 Returns: 411 A dictionary with 'user', 'nice', 'system' and 'idle' values. 412 Sample dictionary: 413 { 414 'user': 254544, 415 'nice': 9, 416 'system': 254768, 417 'idle': 2859878, 418 } 419 """ 420 proc_stat = open('/proc/stat') 421 cpu_usage_str = proc_stat.readline().split() 422 proc_stat.close() 423 return { 424 'user': int(cpu_usage_str[1]), 425 'nice': int(cpu_usage_str[2]), 426 'system': int(cpu_usage_str[3]), 427 'idle': int(cpu_usage_str[4]) 428 } 429 430 431def compute_active_cpu_time(cpu_usage_start, cpu_usage_end): 432 """Computes the fraction of CPU time spent non-idling. 433 434 This function should be invoked using before/after values from calls to 435 get_cpu_usage(). 436 """ 437 time_active_end = (cpu_usage_end['user'] + cpu_usage_end['nice'] + 438 cpu_usage_end['system']) 439 time_active_start = (cpu_usage_start['user'] + cpu_usage_start['nice'] + 440 cpu_usage_start['system']) 441 total_time_end = (cpu_usage_end['user'] + cpu_usage_end['nice'] + 442 cpu_usage_end['system'] + cpu_usage_end['idle']) 443 total_time_start = (cpu_usage_start['user'] + cpu_usage_start['nice'] + 444 cpu_usage_start['system'] + cpu_usage_start['idle']) 445 return ((float(time_active_end) - time_active_start) / 446 (total_time_end - total_time_start)) 447 448 449def is_pgo_mode(): 450 return 'USE_PGO' in os.environ 451 452 453def wait_for_idle_cpu(timeout, utilization): 454 """Waits for the CPU to become idle (< utilization). 455 456 Args: 457 timeout: The longest time in seconds to wait before throwing an error. 458 utilization: The CPU usage below which the system should be considered 459 idle (between 0 and 1.0 independent of cores/hyperthreads). 460 """ 461 time_passed = 0.0 462 fraction_active_time = 1.0 463 sleep_time = 1 464 logging.info('Starting to wait up to %.1fs for idle CPU...', timeout) 465 while fraction_active_time >= utilization: 466 cpu_usage_start = get_cpu_usage() 467 # Split timeout interval into not too many chunks to limit log spew. 468 # Start at 1 second, increase exponentially 469 time.sleep(sleep_time) 470 time_passed += sleep_time 471 sleep_time = min(16.0, 2.0 * sleep_time) 472 cpu_usage_end = get_cpu_usage() 473 fraction_active_time = \ 474 compute_active_cpu_time(cpu_usage_start, cpu_usage_end) 475 logging.info('After waiting %.1fs CPU utilization is %.3f.', 476 time_passed, fraction_active_time) 477 if time_passed > timeout: 478 logging.warning('CPU did not become idle.') 479 log_process_activity() 480 # crosbug.com/37389 481 if is_pgo_mode(): 482 logging.info('Still continuing because we are in PGO mode.') 483 return True 484 485 return False 486 logging.info('Wait for idle CPU took %.1fs (utilization = %.3f).', 487 time_passed, fraction_active_time) 488 return True 489 490 491def log_process_activity(): 492 """Logs the output of top. 493 494 Useful to debug performance tests and to find runaway processes. 495 """ 496 logging.info('Logging current process activity using top.') 497 cmd = 'top -b -n1 -c' 498 output = utils.run(cmd) 499 logging.info(output) 500 501 502def wait_for_cool_machine(): 503 # TODO(ihf): Implement this. The concept of a cool machine is very 504 # architecture specific. We either need a good heuristic or a table of 505 # board specific temperatures. 506 time.sleep(1.0) 507 return True 508 509 510# System paths for machine performance state. 511_CPUINFO = '/proc/cpuinfo' 512_KERNEL_MAX = '/sys/devices/system/cpu/kernel_max' 513_MEMINFO = '/proc/meminfo' 514_TEMP_SENSOR_RE = 'Reading temperature...([0-9]*)' 515 516 517def _get_line_from_file(path, line): 518 """ 519 line can be an integer or 520 line can be a string that matches the beginning of the line 521 """ 522 f = open(path) 523 if (isinstance(line, int)): 524 l = f.readline() 525 for _ in range(0, line): 526 l = f.readline() 527 return l 528 else: 529 for l in f: 530 if l.startswith(line): 531 return l 532 return None 533 534 535def _get_match_from_file(path, line, prefix, postfix): 536 """ 537 Matches line in path and returns string between first prefix and postfix. 538 """ 539 match = _get_line_from_file(path, line) 540 # Strip everything from front of line including prefix. 541 if prefix: 542 match = re.split(prefix, match)[1] 543 # Strip everything from back of string including first occurence of postfix. 544 if postfix: 545 match = re.split(postfix, match)[0] 546 return match 547 548 549def _get_float_from_file(path, line, prefix, postfix): 550 match = _get_match_from_file(path, line, prefix, postfix) 551 return float(match) 552 553 554def _get_int_from_file(path, line, prefix, postfix): 555 match = _get_match_from_file(path, line, prefix, postfix) 556 return int(match) 557 558 559def _get_hex_from_file(path, line, prefix, postfix): 560 match = _get_match_from_file(path, line, prefix, postfix) 561 return int(match, 16) 562 563 564def _get_hwmon_paths(file_pattern): 565 """ 566 Returns a list of paths to the temperature sensors. 567 """ 568 # Some systems like daisy_spring only have the virtual hwmon. 569 # And other systems like rambi only have coretemp.0. See crbug.com/360249. 570 # /sys/class/hwmon/hwmon*/ 571 # /sys/devices/virtual/hwmon/hwmon*/ 572 # /sys/devices/platform/coretemp.0/ 573 cmd = 'find /sys/ -name "' + file_pattern + '"' 574 paths = utils.run(cmd, verbose=False).stdout.splitlines() 575 return paths 576 577 578def get_temperature_critical(): 579 """ 580 Returns temperature at which we will see some throttling in the system. 581 """ 582 min_temperature = 1000.0 583 paths = _get_hwmon_paths('temp*_crit') 584 for path in paths: 585 temperature = _get_float_from_file(path, 0, None, None) * 0.001 586 # Today typical for Intel is 98'C to 105'C while ARM is 85'C. Clamp to 587 # the lowest known value. 588 if ((min_temperature < 60.0) or min_temperature > 150.0): 589 min_temperature = 85.0 590 591 min_temperature = min(temperature, min_temperature) 592 return min_temperature 593 594 595def get_temperature_input_max(): 596 """ 597 Returns the maximum currently observed temperature. 598 """ 599 max_temperature = -1000.0 600 paths = _get_hwmon_paths('temp*_input') 601 for path in paths: 602 temperature = _get_float_from_file(path, 0, None, None) * 0.001 603 max_temperature = max(temperature, max_temperature) 604 # Sanity check for real world values. 605 assert ((max_temperature > 10.0) and 606 (max_temperature < 150.0)), 'Unreasonable temperature.' 607 return max_temperature 608 609 610def get_ec_temperatures(): 611 """ 612 Uses ectool to return a list of all sensor temperatures in Celsius. 613 """ 614 temperatures = [] 615 # TODO(ihf): On all ARM boards I tested 'ectool temps all' returns 200K 616 # for all sensors. Remove this check once crbug.com/358342 is fixed. 617 if 'arm' in utils.get_arch(): 618 return temperatures 619 try: 620 full_cmd = 'ectool temps all' 621 lines = utils.run(full_cmd, verbose=False).stdout.splitlines() 622 for line in lines: 623 temperature = int(line.split(': ')[1]) - 273 624 temperatures.append(temperature) 625 except Exception: 626 logging.warn('Unable to read temperature sensors using ectool.') 627 for temperature in temperatures: 628 # Sanity check for real world values. 629 assert ((temperature > 10.0) and 630 (temperature < 150.0)), 'Unreasonable temperature.' 631 return temperatures 632 633 634def get_cpu_cache_size(): 635 """ 636 Returns the last level CPU cache size in kBytes. 637 """ 638 cache_size = _get_int_from_file(_CPUINFO, 'cache size', ': ', ' KB') 639 # Sanity check. 640 assert cache_size >= 64, 'Unreasonably small cache.' 641 return cache_size 642 643 644def get_cpu_model_frequency(): 645 """ 646 Returns the model frequency from the CPU model name on Intel only. This 647 might be redundant with get_cpu_max_frequency. Unit is Hz. 648 """ 649 frequency = _get_float_from_file(_CPUINFO, 'model name', ' @ ', 'GHz') 650 return 1.e9 * frequency 651 652 653def get_cpu_max_frequency(): 654 """ 655 Returns the largest of the max CPU core frequencies. The unit is Hz. 656 """ 657 max_frequency = -1 658 paths = _get_cpufreq_paths('cpuinfo_max_freq') 659 for path in paths: 660 # Convert from kHz to Hz. 661 frequency = 1000 * _get_float_from_file(path, 0, None, None) 662 max_frequency = max(frequency, max_frequency) 663 # Sanity check. 664 assert max_frequency > 1e8, 'Unreasonably low CPU frequency.' 665 return max_frequency 666 667 668def get_cpu_min_frequency(): 669 """ 670 Returns the smallest of the minimum CPU core frequencies. 671 """ 672 min_frequency = 1e20 673 paths = _get_cpufreq_paths('cpuinfo_min_freq') 674 for path in paths: 675 frequency = _get_float_from_file(path, 0, None, None) 676 min_frequency = min(frequency, min_frequency) 677 # Sanity check. 678 assert min_frequency > 1e8, 'Unreasonably low CPU frequency.' 679 return min_frequency 680 681 682def get_cpu_model(): 683 """ 684 Returns the CPU model. 685 Only works on Intel. 686 """ 687 cpu_model = _get_int_from_file(_CPUINFO, 'model\t', ': ', None) 688 return cpu_model 689 690 691def get_cpu_family(): 692 """ 693 Returns the CPU family. 694 Only works on Intel. 695 """ 696 cpu_family = _get_int_from_file(_CPUINFO, 'cpu family\t', ': ', None) 697 return cpu_family 698 699 700def get_board(): 701 """ 702 Get the ChromeOS release board name from /etc/lsb-release. 703 """ 704 f = open('/etc/lsb-release') 705 try: 706 return re.search('BOARD=(.*)', f.read()).group(1) 707 finally: 708 f.close() 709 710 711def get_board_with_frequency_and_memory(): 712 """ 713 Returns a board name modified with CPU frequency and memory size to 714 differentiate between different board variants. For instance 715 link -> link_1.8GHz_4GB. 716 """ 717 board_name = get_board() 718 # Rounded to nearest GB and GHz. 719 memory = int(round(get_mem_total()/1024.0)) 720 # Convert frequency to GHz with 1 digit accuracy after the decimal point. 721 frequency = int(round(get_cpu_max_frequency() * 1e-8)) * 0.1 722 board = "%s_%1.1fGHz_%dGB" % (board_name, frequency, memory) 723 return board 724 725 726def get_mem_total(): 727 """ 728 Returns the total memory available in the system in MBytes. 729 """ 730 mem_total = _get_float_from_file(_MEMINFO, 'MemTotal:', 'MemTotal:', ' kB') 731 # Sanity check, all Chromebooks have at least 1GB of memory. 732 assert mem_total > 1024*1024, 'Unreasonable amount of memory.' 733 return mem_total / 1024 734 735 736def get_mem_free(): 737 """ 738 Returns the currently free memory in the system in MBytes. 739 """ 740 mem_free = _get_float_from_file(_MEMINFO, 'MemFree:', 'MemFree:', ' kB') 741 return mem_free / 1024 742 743 744def get_kernel_max(): 745 """ 746 Returns content of kernel_max. 747 """ 748 kernel_max = _get_int_from_file(_KERNEL_MAX, 0, None, None) 749 # Sanity check. 750 assert ((kernel_max > 0) and (kernel_max < 257)), 'Unreasonable kernel_max.' 751 return kernel_max 752 753 754def set_high_performance_mode(): 755 """ 756 Sets the kernel governor mode to the highest setting. 757 Returns previous governor state. 758 """ 759 original_governors = get_scaling_governor_states() 760 set_scaling_governors('performance') 761 return original_governors 762 763 764def set_scaling_governors(value): 765 """ 766 Sets all scaling governor to string value. 767 Sample values: 'performance', 'interactive', 'ondemand', 'powersave'. 768 """ 769 paths = _get_cpufreq_paths('scaling_governor') 770 for path in paths: 771 cmd = 'sudo echo %s > %s' % (value, path) 772 logging.info('Writing scaling governor mode \'%s\' -> %s', value, path) 773 utils.system(cmd) 774 775 776def _get_cpufreq_paths(filename): 777 """ 778 Returns a list of paths to the governors. 779 """ 780 cmd = 'ls /sys/devices/system/cpu/cpu*/cpufreq/' + filename 781 paths = utils.run(cmd, verbose=False).stdout.splitlines() 782 return paths 783 784 785def get_scaling_governor_states(): 786 """ 787 Returns a list of (performance governor path, current state) tuples. 788 """ 789 paths = _get_cpufreq_paths('scaling_governor') 790 path_value_list = [] 791 for path in paths: 792 value = _get_line_from_file(path, 0) 793 path_value_list.append((path, value)) 794 return path_value_list 795 796 797def restore_scaling_governor_states(path_value_list): 798 """ 799 Restores governor states. Inverse operation to get_scaling_governor_states. 800 """ 801 for (path, value) in path_value_list: 802 cmd = 'sudo echo %s > %s' % (value, path) 803 utils.system(cmd) 804 805 806def get_gpu_family(): 807 """Return the GPU family name""" 808 cpuarch = base_utils.get_cpu_soc_family() 809 if cpuarch == 'exynos5': 810 return 'mali' 811 if cpuarch == 'tegra': 812 return 'tegra' 813 814 pci_path = '/sys/bus/pci/devices/0000:00:02.0/device' 815 816 if not os.path.exists(pci_path): 817 raise error.TestError('PCI device 0000:00:02.0 not found') 818 819 device_id = int(utils.read_one_line(pci_path), 16) 820 intel_architecture = { 821 0xa011: 'pinetrail', 822 0x0106: 'sandybridge', 823 0x0126: 'sandybridge', 824 0x0156: 'ivybridge', 825 0x0166: 'ivybridge', 826 0x0a06: 'haswell', 827 0x0f31: 'baytrail', 828 } 829 830 return intel_architecture[device_id] 831