blob: 64264c44bc30c6862ef25a482e002f40c7b94d94 [file] [log] [blame]
Ahmad Sharifae1714d2013-01-17 11:29:37 -08001// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "perf_tool.h"
6
Ben Chan9953a592014-02-05 23:32:00 -08007#include <base/strings/string_split.h>
Ahmad Sharif3abea3c2013-05-13 20:43:04 -07008
9#include "cpu_info_parser.h"
Ahmad Sharifae1714d2013-01-17 11:29:37 -080010#include "process_with_output.h"
11
Ben Chan55903dd2014-04-24 00:29:04 -070012using base::StringPrintf;
13
Ahmad Shariff5597f62013-04-25 12:25:41 -070014namespace {
15
16// Location of quipper on ChromeOS.
17const char kQuipperLocation[] = "/usr/bin/quipper";
18
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070019// This is the key in /proc/cpuinfo whose value is the model name of the CPU.
20const char kCPUModelNameKey[] = "model name";
Ahmad Shariff5597f62013-04-25 12:25:41 -070021
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070022// Processor model name substrings for which we have perf commands.
23const char* kCPUOddsFiles[] = {
24 "unknown",
25 "core",
26 "arm",
27};
Ahmad Shariff5597f62013-04-25 12:25:41 -070028
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070029// Prefix path to attach to the CPU odds file.
Ahmad Sharifbdb33912013-07-16 11:44:49 -040030const char kCPUOddsFilePrefix[] = "/etc/perf_commands/";
Ahmad Shariff5597f62013-04-25 12:25:41 -070031
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070032// Suffix to attach to the CPU odds file.
33const char kCPUOddsFileSuffix[] = ".txt";
Ahmad Shariff5597f62013-04-25 12:25:41 -070034
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070035// Goes through the list of kCPUOddsFiles, and if the any of those strings is a
36// substring of the |cpu_model_name|, returns that string. If no matches are
37// found, returns the first string of |kCPUOddsFiles| ("unknown").
38void GetOddsFilenameForCPU(const std::string& cpu_model_name,
39 std::string* odds_filename) {
40 std::string lowered_cpu_model_name = StringToLowerASCII(cpu_model_name);
41 for (size_t i = 0; i < arraysize(kCPUOddsFiles); ++i) {
42 if (lowered_cpu_model_name.find(kCPUOddsFiles[i]) != std::string::npos) {
43 *odds_filename = kCPUOddsFiles[i];
44 return;
45 }
46 }
47 *odds_filename = kCPUOddsFiles[0];
Ahmad Shariff5597f62013-04-25 12:25:41 -070048}
49
50} // namespace
51
Ahmad Sharifae1714d2013-01-17 11:29:37 -080052namespace debugd {
53
Ahmad Shariff5597f62013-04-25 12:25:41 -070054PerfTool::PerfTool() {
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070055 std::string cpu_model_name;
56 debugd::CPUInfoParser cpu_info_parser;
57 cpu_info_parser.GetKey(kCPUModelNameKey, &cpu_model_name);
58 std::string odds_filename;
59 GetOddsFilenameForCPU(cpu_model_name, &odds_filename);
Ben Chana0011d82014-05-13 00:19:29 -070060 std::string odds_file_path =
61 std::string(kCPUOddsFilePrefix) + odds_filename + kCPUOddsFileSuffix;
Ahmad Sharif3abea3c2013-05-13 20:43:04 -070062 random_selector_.SetOddsFromFile(odds_file_path);
Ahmad Shariff5597f62013-04-25 12:25:41 -070063}
Ahmad Sharifae1714d2013-01-17 11:29:37 -080064
65PerfTool::~PerfTool() { }
66
Ahmad Shariff5597f62013-04-25 12:25:41 -070067std::vector<uint8> PerfTool::GetRichPerfData(const uint32_t& duration_secs,
Ben Chana0011d82014-05-13 00:19:29 -070068 DBus::Error* error) {
Ahmad Shariff5597f62013-04-25 12:25:41 -070069 std::string perf_command_line;
70 random_selector_.GetNext(&perf_command_line);
71 std::string output_string;
72 GetPerfDataHelper(duration_secs, perf_command_line, error, &output_string);
73 return std::vector<uint8>(output_string.begin(), output_string.end());
74}
75
76void PerfTool::GetPerfDataHelper(const uint32_t& duration_secs,
77 const std::string& perf_command_line,
Ben Chana0011d82014-05-13 00:19:29 -070078 DBus::Error* error,
79 std::string* data_string) {
Ahmad Sharifae1714d2013-01-17 11:29:37 -080080 // This whole method is synchronous, so we create a subprocess, let it run to
81 // completion, then gather up its output to return it.
82 ProcessWithOutput process;
83 process.SandboxAs("root", "root");
84 if (!process.Init())
85 *data_string = "<process init failed>";
86 // If you're going to add switches to a command, have a look at the Process
87 // interface; there's support for adding options specifically.
Ahmad Shariff5597f62013-04-25 12:25:41 -070088 process.AddArg(kQuipperLocation);
89 process.AddArg(StringPrintf("%u", duration_secs));
90 process.AddArg(perf_command_line);
Ahmad Sharifae1714d2013-01-17 11:29:37 -080091 // Run the process to completion. If the process might take a while, you may
92 // have to make this asynchronous using .Start().
93 int status = process.Run();
94 if (status != 0)
95 *data_string = StringPrintf("<process exited with status: %d", status);
96 process.GetOutput(data_string);
97}
98
Ben Chana0011d82014-05-13 00:19:29 -070099} // namespace debugd