xref: /aosp_15_r20/system/extras/simpleperf/cpu_hotplug_test.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker 
17*288bf522SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*288bf522SAndroid Build Coastguard Worker 
19*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
20*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
21*288bf522SAndroid Build Coastguard Worker #if defined(__BIONIC__)
22*288bf522SAndroid Build Coastguard Worker #include <android-base/properties.h>
23*288bf522SAndroid Build Coastguard Worker #endif
24*288bf522SAndroid Build Coastguard Worker 
25*288bf522SAndroid Build Coastguard Worker #include <atomic>
26*288bf522SAndroid Build Coastguard Worker #include <chrono>
27*288bf522SAndroid Build Coastguard Worker #include <thread>
28*288bf522SAndroid Build Coastguard Worker #include <unordered_map>
29*288bf522SAndroid Build Coastguard Worker 
30*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
31*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
32*288bf522SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
33*288bf522SAndroid Build Coastguard Worker 
34*288bf522SAndroid Build Coastguard Worker #include "environment.h"
35*288bf522SAndroid Build Coastguard Worker #include "event_attr.h"
36*288bf522SAndroid Build Coastguard Worker #include "event_fd.h"
37*288bf522SAndroid Build Coastguard Worker #include "event_type.h"
38*288bf522SAndroid Build Coastguard Worker #include "utils.h"
39*288bf522SAndroid Build Coastguard Worker 
40*288bf522SAndroid Build Coastguard Worker using namespace simpleperf;
41*288bf522SAndroid Build Coastguard Worker 
42*288bf522SAndroid Build Coastguard Worker static auto test_duration_for_long_tests = std::chrono::seconds(120);
43*288bf522SAndroid Build Coastguard Worker static auto cpu_hotplug_interval = std::chrono::microseconds(1000);
44*288bf522SAndroid Build Coastguard Worker static bool verbose_mode = false;
45*288bf522SAndroid Build Coastguard Worker 
46*288bf522SAndroid Build Coastguard Worker #if defined(__BIONIC__)
47*288bf522SAndroid Build Coastguard Worker class ScopedMpdecisionKiller {
48*288bf522SAndroid Build Coastguard Worker  public:
ScopedMpdecisionKiller()49*288bf522SAndroid Build Coastguard Worker   ScopedMpdecisionKiller() {
50*288bf522SAndroid Build Coastguard Worker     have_mpdecision_ = IsMpdecisionRunning();
51*288bf522SAndroid Build Coastguard Worker     if (have_mpdecision_) {
52*288bf522SAndroid Build Coastguard Worker       DisableMpdecision();
53*288bf522SAndroid Build Coastguard Worker     }
54*288bf522SAndroid Build Coastguard Worker   }
55*288bf522SAndroid Build Coastguard Worker 
~ScopedMpdecisionKiller()56*288bf522SAndroid Build Coastguard Worker   ~ScopedMpdecisionKiller() {
57*288bf522SAndroid Build Coastguard Worker     if (have_mpdecision_) {
58*288bf522SAndroid Build Coastguard Worker       EnableMpdecision();
59*288bf522SAndroid Build Coastguard Worker     }
60*288bf522SAndroid Build Coastguard Worker   }
61*288bf522SAndroid Build Coastguard Worker 
62*288bf522SAndroid Build Coastguard Worker  private:
IsMpdecisionRunning()63*288bf522SAndroid Build Coastguard Worker   bool IsMpdecisionRunning() {
64*288bf522SAndroid Build Coastguard Worker     std::string value = android::base::GetProperty("init.svc.mpdecision", "");
65*288bf522SAndroid Build Coastguard Worker     if (value.empty() || value.find("stopped") != std::string::npos) {
66*288bf522SAndroid Build Coastguard Worker       return false;
67*288bf522SAndroid Build Coastguard Worker     }
68*288bf522SAndroid Build Coastguard Worker     return true;
69*288bf522SAndroid Build Coastguard Worker   }
70*288bf522SAndroid Build Coastguard Worker 
DisableMpdecision()71*288bf522SAndroid Build Coastguard Worker   void DisableMpdecision() {
72*288bf522SAndroid Build Coastguard Worker     CHECK(android::base::SetProperty("ctl.stop", "mpdecision"));
73*288bf522SAndroid Build Coastguard Worker     // Need to wait until mpdecision is actually stopped.
74*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::milliseconds(500));
75*288bf522SAndroid Build Coastguard Worker     CHECK(!IsMpdecisionRunning());
76*288bf522SAndroid Build Coastguard Worker   }
77*288bf522SAndroid Build Coastguard Worker 
EnableMpdecision()78*288bf522SAndroid Build Coastguard Worker   void EnableMpdecision() {
79*288bf522SAndroid Build Coastguard Worker     CHECK(android::base::SetProperty("ctl.start", "mpdecision"));
80*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::milliseconds(500));
81*288bf522SAndroid Build Coastguard Worker     CHECK(IsMpdecisionRunning());
82*288bf522SAndroid Build Coastguard Worker   }
83*288bf522SAndroid Build Coastguard Worker 
84*288bf522SAndroid Build Coastguard Worker   bool have_mpdecision_;
85*288bf522SAndroid Build Coastguard Worker };
86*288bf522SAndroid Build Coastguard Worker #else
87*288bf522SAndroid Build Coastguard Worker class ScopedMpdecisionKiller {
88*288bf522SAndroid Build Coastguard Worker  public:
ScopedMpdecisionKiller()89*288bf522SAndroid Build Coastguard Worker   ScopedMpdecisionKiller() {}
90*288bf522SAndroid Build Coastguard Worker };
91*288bf522SAndroid Build Coastguard Worker #endif
92*288bf522SAndroid Build Coastguard Worker 
IsCpuOnline(int cpu,bool * has_error)93*288bf522SAndroid Build Coastguard Worker static bool IsCpuOnline(int cpu, bool* has_error) {
94*288bf522SAndroid Build Coastguard Worker   std::string filename = android::base::StringPrintf("/sys/devices/system/cpu/cpu%d/online", cpu);
95*288bf522SAndroid Build Coastguard Worker   std::string content;
96*288bf522SAndroid Build Coastguard Worker   bool ret = android::base::ReadFileToString(filename, &content);
97*288bf522SAndroid Build Coastguard Worker   if (!ret) {
98*288bf522SAndroid Build Coastguard Worker     PLOG(ERROR) << "failed to read file " << filename;
99*288bf522SAndroid Build Coastguard Worker     *has_error = true;
100*288bf522SAndroid Build Coastguard Worker     return false;
101*288bf522SAndroid Build Coastguard Worker   }
102*288bf522SAndroid Build Coastguard Worker   *has_error = false;
103*288bf522SAndroid Build Coastguard Worker   return (content.find('1') != std::string::npos);
104*288bf522SAndroid Build Coastguard Worker }
105*288bf522SAndroid Build Coastguard Worker 
SetCpuOnline(int cpu,bool online)106*288bf522SAndroid Build Coastguard Worker static bool SetCpuOnline(int cpu, bool online) {
107*288bf522SAndroid Build Coastguard Worker   bool has_error;
108*288bf522SAndroid Build Coastguard Worker   bool ret = IsCpuOnline(cpu, &has_error);
109*288bf522SAndroid Build Coastguard Worker   if (has_error) {
110*288bf522SAndroid Build Coastguard Worker     return false;
111*288bf522SAndroid Build Coastguard Worker   }
112*288bf522SAndroid Build Coastguard Worker   if (ret == online) {
113*288bf522SAndroid Build Coastguard Worker     return true;
114*288bf522SAndroid Build Coastguard Worker   }
115*288bf522SAndroid Build Coastguard Worker   std::string filename = android::base::StringPrintf("/sys/devices/system/cpu/cpu%d/online", cpu);
116*288bf522SAndroid Build Coastguard Worker   std::string content = online ? "1" : "0";
117*288bf522SAndroid Build Coastguard Worker   ret = android::base::WriteStringToFile(content, filename);
118*288bf522SAndroid Build Coastguard Worker   if (!ret) {
119*288bf522SAndroid Build Coastguard Worker     ret = IsCpuOnline(cpu, &has_error);
120*288bf522SAndroid Build Coastguard Worker     if (has_error) {
121*288bf522SAndroid Build Coastguard Worker       return false;
122*288bf522SAndroid Build Coastguard Worker     }
123*288bf522SAndroid Build Coastguard Worker     if (online == ret) {
124*288bf522SAndroid Build Coastguard Worker       return true;
125*288bf522SAndroid Build Coastguard Worker     }
126*288bf522SAndroid Build Coastguard Worker     PLOG(ERROR) << "failed to write " << content << " to " << filename;
127*288bf522SAndroid Build Coastguard Worker     return false;
128*288bf522SAndroid Build Coastguard Worker   }
129*288bf522SAndroid Build Coastguard Worker   // Kernel needs time to offline/online cpus, so use a loop to wait here.
130*288bf522SAndroid Build Coastguard Worker   size_t retry_count = 0;
131*288bf522SAndroid Build Coastguard Worker   while (true) {
132*288bf522SAndroid Build Coastguard Worker     ret = IsCpuOnline(cpu, &has_error);
133*288bf522SAndroid Build Coastguard Worker     if (has_error) {
134*288bf522SAndroid Build Coastguard Worker       return false;
135*288bf522SAndroid Build Coastguard Worker     }
136*288bf522SAndroid Build Coastguard Worker     if (ret == online) {
137*288bf522SAndroid Build Coastguard Worker       break;
138*288bf522SAndroid Build Coastguard Worker     }
139*288bf522SAndroid Build Coastguard Worker     LOG(ERROR) << "reading cpu retry count = " << retry_count << ", requested = " << online
140*288bf522SAndroid Build Coastguard Worker                << ", real = " << ret;
141*288bf522SAndroid Build Coastguard Worker     if (++retry_count == 10000) {
142*288bf522SAndroid Build Coastguard Worker       LOG(ERROR) << "setting cpu " << cpu << (online ? " online" : " offline")
143*288bf522SAndroid Build Coastguard Worker                  << " seems not to take effect";
144*288bf522SAndroid Build Coastguard Worker       return false;
145*288bf522SAndroid Build Coastguard Worker     }
146*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::milliseconds(1));
147*288bf522SAndroid Build Coastguard Worker   }
148*288bf522SAndroid Build Coastguard Worker   return true;
149*288bf522SAndroid Build Coastguard Worker }
150*288bf522SAndroid Build Coastguard Worker 
GetCpuCount()151*288bf522SAndroid Build Coastguard Worker static int GetCpuCount() {
152*288bf522SAndroid Build Coastguard Worker   return static_cast<int>(sysconf(_SC_NPROCESSORS_CONF));
153*288bf522SAndroid Build Coastguard Worker }
154*288bf522SAndroid Build Coastguard Worker 
155*288bf522SAndroid Build Coastguard Worker class CpuOnlineRestorer {
156*288bf522SAndroid Build Coastguard Worker  public:
CpuOnlineRestorer()157*288bf522SAndroid Build Coastguard Worker   CpuOnlineRestorer() {
158*288bf522SAndroid Build Coastguard Worker     for (int cpu = 1; cpu < GetCpuCount(); ++cpu) {
159*288bf522SAndroid Build Coastguard Worker       bool has_error;
160*288bf522SAndroid Build Coastguard Worker       bool ret = IsCpuOnline(cpu, &has_error);
161*288bf522SAndroid Build Coastguard Worker       if (has_error) {
162*288bf522SAndroid Build Coastguard Worker         continue;
163*288bf522SAndroid Build Coastguard Worker       }
164*288bf522SAndroid Build Coastguard Worker       online_map_[cpu] = ret;
165*288bf522SAndroid Build Coastguard Worker     }
166*288bf522SAndroid Build Coastguard Worker   }
167*288bf522SAndroid Build Coastguard Worker 
~CpuOnlineRestorer()168*288bf522SAndroid Build Coastguard Worker   ~CpuOnlineRestorer() {
169*288bf522SAndroid Build Coastguard Worker     for (const auto& pair : online_map_) {
170*288bf522SAndroid Build Coastguard Worker       SetCpuOnline(pair.first, pair.second);
171*288bf522SAndroid Build Coastguard Worker     }
172*288bf522SAndroid Build Coastguard Worker   }
173*288bf522SAndroid Build Coastguard Worker 
174*288bf522SAndroid Build Coastguard Worker  private:
175*288bf522SAndroid Build Coastguard Worker   std::unordered_map<int, bool> online_map_;
176*288bf522SAndroid Build Coastguard Worker };
177*288bf522SAndroid Build Coastguard Worker 
FindAHotpluggableCpu(int * hotpluggable_cpu)178*288bf522SAndroid Build Coastguard Worker bool FindAHotpluggableCpu(int* hotpluggable_cpu) {
179*288bf522SAndroid Build Coastguard Worker   if (!IsRoot()) {
180*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "This test needs root privilege to hotplug cpu.";
181*288bf522SAndroid Build Coastguard Worker     return false;
182*288bf522SAndroid Build Coastguard Worker   }
183*288bf522SAndroid Build Coastguard Worker   for (int cpu = 1; cpu < GetCpuCount(); ++cpu) {
184*288bf522SAndroid Build Coastguard Worker     bool has_error;
185*288bf522SAndroid Build Coastguard Worker     bool online = IsCpuOnline(cpu, &has_error);
186*288bf522SAndroid Build Coastguard Worker     if (has_error) {
187*288bf522SAndroid Build Coastguard Worker       continue;
188*288bf522SAndroid Build Coastguard Worker     }
189*288bf522SAndroid Build Coastguard Worker     if (SetCpuOnline(cpu, !online)) {
190*288bf522SAndroid Build Coastguard Worker       *hotpluggable_cpu = cpu;
191*288bf522SAndroid Build Coastguard Worker       return true;
192*288bf522SAndroid Build Coastguard Worker     }
193*288bf522SAndroid Build Coastguard Worker   }
194*288bf522SAndroid Build Coastguard Worker   GTEST_LOG_(INFO) << "There is no hotpluggable cpu.";
195*288bf522SAndroid Build Coastguard Worker   return false;
196*288bf522SAndroid Build Coastguard Worker }
197*288bf522SAndroid Build Coastguard Worker 
198*288bf522SAndroid Build Coastguard Worker struct CpuToggleThreadArg {
199*288bf522SAndroid Build Coastguard Worker   int toggle_cpu;
200*288bf522SAndroid Build Coastguard Worker   std::atomic<bool> end_flag;
201*288bf522SAndroid Build Coastguard Worker   std::atomic<bool> cpu_hotplug_failed;
202*288bf522SAndroid Build Coastguard Worker 
CpuToggleThreadArgCpuToggleThreadArg203*288bf522SAndroid Build Coastguard Worker   CpuToggleThreadArg(int cpu) : toggle_cpu(cpu), end_flag(false), cpu_hotplug_failed(false) {}
204*288bf522SAndroid Build Coastguard Worker };
205*288bf522SAndroid Build Coastguard Worker 
CpuToggleThread(CpuToggleThreadArg * arg)206*288bf522SAndroid Build Coastguard Worker static void CpuToggleThread(CpuToggleThreadArg* arg) {
207*288bf522SAndroid Build Coastguard Worker   while (!arg->end_flag) {
208*288bf522SAndroid Build Coastguard Worker     if (!SetCpuOnline(arg->toggle_cpu, true)) {
209*288bf522SAndroid Build Coastguard Worker       arg->cpu_hotplug_failed = true;
210*288bf522SAndroid Build Coastguard Worker       break;
211*288bf522SAndroid Build Coastguard Worker     }
212*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(cpu_hotplug_interval);
213*288bf522SAndroid Build Coastguard Worker     if (!SetCpuOnline(arg->toggle_cpu, false)) {
214*288bf522SAndroid Build Coastguard Worker       arg->cpu_hotplug_failed = true;
215*288bf522SAndroid Build Coastguard Worker       break;
216*288bf522SAndroid Build Coastguard Worker     }
217*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(cpu_hotplug_interval);
218*288bf522SAndroid Build Coastguard Worker   }
219*288bf522SAndroid Build Coastguard Worker }
220*288bf522SAndroid Build Coastguard Worker 
221*288bf522SAndroid Build Coastguard Worker // http://b/25193162.
TEST(cpu_offline,offline_while_recording)222*288bf522SAndroid Build Coastguard Worker TEST(cpu_offline, offline_while_recording) {
223*288bf522SAndroid Build Coastguard Worker   ScopedMpdecisionKiller scoped_mpdecision_killer;
224*288bf522SAndroid Build Coastguard Worker   CpuOnlineRestorer cpuonline_restorer;
225*288bf522SAndroid Build Coastguard Worker   if (GetCpuCount() == 1) {
226*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "This test does nothing, because there is only one cpu in the system.";
227*288bf522SAndroid Build Coastguard Worker     return;
228*288bf522SAndroid Build Coastguard Worker   }
229*288bf522SAndroid Build Coastguard Worker   // Start cpu hotpluger.
230*288bf522SAndroid Build Coastguard Worker   int test_cpu;
231*288bf522SAndroid Build Coastguard Worker   if (!FindAHotpluggableCpu(&test_cpu)) {
232*288bf522SAndroid Build Coastguard Worker     return;
233*288bf522SAndroid Build Coastguard Worker   }
234*288bf522SAndroid Build Coastguard Worker   CpuToggleThreadArg cpu_toggle_arg(test_cpu);
235*288bf522SAndroid Build Coastguard Worker   std::thread cpu_toggle_thread(CpuToggleThread, &cpu_toggle_arg);
236*288bf522SAndroid Build Coastguard Worker 
237*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
238*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(event_type_modifier != nullptr);
239*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
240*288bf522SAndroid Build Coastguard Worker   attr.disabled = 0;
241*288bf522SAndroid Build Coastguard Worker   attr.enable_on_exec = 0;
242*288bf522SAndroid Build Coastguard Worker 
243*288bf522SAndroid Build Coastguard Worker   auto start_time = std::chrono::steady_clock::now();
244*288bf522SAndroid Build Coastguard Worker   auto cur_time = start_time;
245*288bf522SAndroid Build Coastguard Worker   auto end_time = std::chrono::steady_clock::now() + test_duration_for_long_tests;
246*288bf522SAndroid Build Coastguard Worker   auto report_step = std::chrono::seconds(15);
247*288bf522SAndroid Build Coastguard Worker   size_t iterations = 0;
248*288bf522SAndroid Build Coastguard Worker 
249*288bf522SAndroid Build Coastguard Worker   while (cur_time < end_time && !cpu_toggle_arg.cpu_hotplug_failed) {
250*288bf522SAndroid Build Coastguard Worker     if (cur_time + report_step < std::chrono::steady_clock::now()) {
251*288bf522SAndroid Build Coastguard Worker       // Report test time.
252*288bf522SAndroid Build Coastguard Worker       auto diff = std::chrono::duration_cast<std::chrono::seconds>(
253*288bf522SAndroid Build Coastguard Worker           std::chrono::steady_clock::now() - start_time);
254*288bf522SAndroid Build Coastguard Worker       if (verbose_mode) {
255*288bf522SAndroid Build Coastguard Worker         GTEST_LOG_(INFO) << "Have Tested " << (diff.count() / 60.0) << " minutes.";
256*288bf522SAndroid Build Coastguard Worker       }
257*288bf522SAndroid Build Coastguard Worker       cur_time = std::chrono::steady_clock::now();
258*288bf522SAndroid Build Coastguard Worker     }
259*288bf522SAndroid Build Coastguard Worker 
260*288bf522SAndroid Build Coastguard Worker     std::unique_ptr<EventFd> event_fd =
261*288bf522SAndroid Build Coastguard Worker         EventFd::OpenEventFile(attr, -1, test_cpu, nullptr, event_type_modifier->name, false);
262*288bf522SAndroid Build Coastguard Worker     if (event_fd == nullptr) {
263*288bf522SAndroid Build Coastguard Worker       // Failed to open because the test_cpu is offline.
264*288bf522SAndroid Build Coastguard Worker       continue;
265*288bf522SAndroid Build Coastguard Worker     }
266*288bf522SAndroid Build Coastguard Worker     iterations++;
267*288bf522SAndroid Build Coastguard Worker     if (verbose_mode) {
268*288bf522SAndroid Build Coastguard Worker       GTEST_LOG_(INFO) << "Test offline while recording for " << iterations << " times.";
269*288bf522SAndroid Build Coastguard Worker     }
270*288bf522SAndroid Build Coastguard Worker   }
271*288bf522SAndroid Build Coastguard Worker   if (cpu_toggle_arg.cpu_hotplug_failed) {
272*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "Test ends because of cpu hotplug failure.";
273*288bf522SAndroid Build Coastguard Worker   }
274*288bf522SAndroid Build Coastguard Worker   cpu_toggle_arg.end_flag = true;
275*288bf522SAndroid Build Coastguard Worker   cpu_toggle_thread.join();
276*288bf522SAndroid Build Coastguard Worker }
277*288bf522SAndroid Build Coastguard Worker 
278*288bf522SAndroid Build Coastguard Worker // http://b/25193162.
TEST(cpu_offline,offline_while_ioctl_enable)279*288bf522SAndroid Build Coastguard Worker TEST(cpu_offline, offline_while_ioctl_enable) {
280*288bf522SAndroid Build Coastguard Worker   ScopedMpdecisionKiller scoped_mpdecision_killer;
281*288bf522SAndroid Build Coastguard Worker   CpuOnlineRestorer cpuonline_restorer;
282*288bf522SAndroid Build Coastguard Worker   if (GetCpuCount() == 1) {
283*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "This test does nothing, because there is only one cpu in the system.";
284*288bf522SAndroid Build Coastguard Worker     return;
285*288bf522SAndroid Build Coastguard Worker   }
286*288bf522SAndroid Build Coastguard Worker   // Start cpu hotpluger.
287*288bf522SAndroid Build Coastguard Worker   int test_cpu;
288*288bf522SAndroid Build Coastguard Worker   if (!FindAHotpluggableCpu(&test_cpu)) {
289*288bf522SAndroid Build Coastguard Worker     return;
290*288bf522SAndroid Build Coastguard Worker   }
291*288bf522SAndroid Build Coastguard Worker   CpuToggleThreadArg cpu_toggle_arg(test_cpu);
292*288bf522SAndroid Build Coastguard Worker   std::thread cpu_toggle_thread(CpuToggleThread, &cpu_toggle_arg);
293*288bf522SAndroid Build Coastguard Worker 
294*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
295*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(event_type_modifier != nullptr);
296*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
297*288bf522SAndroid Build Coastguard Worker   attr.disabled = 1;
298*288bf522SAndroid Build Coastguard Worker   attr.enable_on_exec = 0;
299*288bf522SAndroid Build Coastguard Worker 
300*288bf522SAndroid Build Coastguard Worker   auto start_time = std::chrono::steady_clock::now();
301*288bf522SAndroid Build Coastguard Worker   auto cur_time = start_time;
302*288bf522SAndroid Build Coastguard Worker   auto end_time = std::chrono::steady_clock::now() + test_duration_for_long_tests;
303*288bf522SAndroid Build Coastguard Worker   auto report_step = std::chrono::seconds(15);
304*288bf522SAndroid Build Coastguard Worker   size_t iterations = 0;
305*288bf522SAndroid Build Coastguard Worker 
306*288bf522SAndroid Build Coastguard Worker   while (cur_time < end_time && !cpu_toggle_arg.cpu_hotplug_failed) {
307*288bf522SAndroid Build Coastguard Worker     if (cur_time + report_step < std::chrono::steady_clock::now()) {
308*288bf522SAndroid Build Coastguard Worker       // Report test time.
309*288bf522SAndroid Build Coastguard Worker       auto diff = std::chrono::duration_cast<std::chrono::seconds>(
310*288bf522SAndroid Build Coastguard Worker           std::chrono::steady_clock::now() - start_time);
311*288bf522SAndroid Build Coastguard Worker       if (verbose_mode) {
312*288bf522SAndroid Build Coastguard Worker         GTEST_LOG_(INFO) << "Have Tested " << (diff.count() / 60.0) << " minutes.";
313*288bf522SAndroid Build Coastguard Worker       }
314*288bf522SAndroid Build Coastguard Worker       cur_time = std::chrono::steady_clock::now();
315*288bf522SAndroid Build Coastguard Worker     }
316*288bf522SAndroid Build Coastguard Worker     std::unique_ptr<EventFd> event_fd =
317*288bf522SAndroid Build Coastguard Worker         EventFd::OpenEventFile(attr, -1, test_cpu, nullptr, event_type_modifier->name, false);
318*288bf522SAndroid Build Coastguard Worker     if (event_fd == nullptr) {
319*288bf522SAndroid Build Coastguard Worker       // Failed to open because the test_cpu is offline.
320*288bf522SAndroid Build Coastguard Worker       continue;
321*288bf522SAndroid Build Coastguard Worker     }
322*288bf522SAndroid Build Coastguard Worker     // Wait a little for the event to be installed on test_cpu's perf context.
323*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::milliseconds(1));
324*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(event_fd->SetEnableEvent(true));
325*288bf522SAndroid Build Coastguard Worker     iterations++;
326*288bf522SAndroid Build Coastguard Worker     if (verbose_mode) {
327*288bf522SAndroid Build Coastguard Worker       GTEST_LOG_(INFO) << "Test offline while ioctl(PERF_EVENT_IOC_ENABLE) for " << iterations
328*288bf522SAndroid Build Coastguard Worker                        << " times.";
329*288bf522SAndroid Build Coastguard Worker     }
330*288bf522SAndroid Build Coastguard Worker   }
331*288bf522SAndroid Build Coastguard Worker   if (cpu_toggle_arg.cpu_hotplug_failed) {
332*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "Test ends because of cpu hotplug failure.";
333*288bf522SAndroid Build Coastguard Worker   }
334*288bf522SAndroid Build Coastguard Worker   cpu_toggle_arg.end_flag = true;
335*288bf522SAndroid Build Coastguard Worker   cpu_toggle_thread.join();
336*288bf522SAndroid Build Coastguard Worker }
337*288bf522SAndroid Build Coastguard Worker 
338*288bf522SAndroid Build Coastguard Worker struct CpuSpinThreadArg {
339*288bf522SAndroid Build Coastguard Worker   int spin_cpu;
340*288bf522SAndroid Build Coastguard Worker   std::atomic<pid_t> tid;
341*288bf522SAndroid Build Coastguard Worker   std::atomic<bool> end_flag;
342*288bf522SAndroid Build Coastguard Worker };
343*288bf522SAndroid Build Coastguard Worker 
CpuSpinThread(CpuSpinThreadArg * arg)344*288bf522SAndroid Build Coastguard Worker static void CpuSpinThread(CpuSpinThreadArg* arg) {
345*288bf522SAndroid Build Coastguard Worker   arg->tid = gettid();
346*288bf522SAndroid Build Coastguard Worker   while (!arg->end_flag) {
347*288bf522SAndroid Build Coastguard Worker     cpu_set_t mask;
348*288bf522SAndroid Build Coastguard Worker     CPU_ZERO(&mask);
349*288bf522SAndroid Build Coastguard Worker     CPU_SET(arg->spin_cpu, &mask);
350*288bf522SAndroid Build Coastguard Worker     // If toggle_cpu is offline, setaffinity fails. So call it in a loop to
351*288bf522SAndroid Build Coastguard Worker     // make sure current thread mostly runs on toggle_cpu.
352*288bf522SAndroid Build Coastguard Worker     sched_setaffinity(arg->tid, sizeof(mask), &mask);
353*288bf522SAndroid Build Coastguard Worker   }
354*288bf522SAndroid Build Coastguard Worker }
355*288bf522SAndroid Build Coastguard Worker 
356*288bf522SAndroid Build Coastguard Worker // http://b/28086229.
TEST(cpu_offline,offline_while_user_process_profiling)357*288bf522SAndroid Build Coastguard Worker TEST(cpu_offline, offline_while_user_process_profiling) {
358*288bf522SAndroid Build Coastguard Worker   ScopedMpdecisionKiller scoped_mpdecision_killer;
359*288bf522SAndroid Build Coastguard Worker   CpuOnlineRestorer cpuonline_restorer;
360*288bf522SAndroid Build Coastguard Worker   // Start cpu hotpluger.
361*288bf522SAndroid Build Coastguard Worker   int test_cpu;
362*288bf522SAndroid Build Coastguard Worker   if (!FindAHotpluggableCpu(&test_cpu)) {
363*288bf522SAndroid Build Coastguard Worker     return;
364*288bf522SAndroid Build Coastguard Worker   }
365*288bf522SAndroid Build Coastguard Worker   CpuToggleThreadArg cpu_toggle_arg(test_cpu);
366*288bf522SAndroid Build Coastguard Worker   std::thread cpu_toggle_thread(CpuToggleThread, &cpu_toggle_arg);
367*288bf522SAndroid Build Coastguard Worker 
368*288bf522SAndroid Build Coastguard Worker   // Start cpu spinner.
369*288bf522SAndroid Build Coastguard Worker   CpuSpinThreadArg cpu_spin_arg;
370*288bf522SAndroid Build Coastguard Worker   cpu_spin_arg.spin_cpu = test_cpu;
371*288bf522SAndroid Build Coastguard Worker   cpu_spin_arg.tid = 0;
372*288bf522SAndroid Build Coastguard Worker   cpu_spin_arg.end_flag = false;
373*288bf522SAndroid Build Coastguard Worker   std::thread cpu_spin_thread(CpuSpinThread, &cpu_spin_arg);
374*288bf522SAndroid Build Coastguard Worker   while (cpu_spin_arg.tid == 0) {
375*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::milliseconds(1));
376*288bf522SAndroid Build Coastguard Worker   }
377*288bf522SAndroid Build Coastguard Worker 
378*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
379*288bf522SAndroid Build Coastguard Worker   ASSERT_TRUE(event_type_modifier != nullptr);
380*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
381*288bf522SAndroid Build Coastguard Worker   // Enable profiling in perf_event_open system call.
382*288bf522SAndroid Build Coastguard Worker   attr.disabled = 0;
383*288bf522SAndroid Build Coastguard Worker   attr.enable_on_exec = 0;
384*288bf522SAndroid Build Coastguard Worker 
385*288bf522SAndroid Build Coastguard Worker   auto start_time = std::chrono::steady_clock::now();
386*288bf522SAndroid Build Coastguard Worker   auto cur_time = start_time;
387*288bf522SAndroid Build Coastguard Worker   auto end_time = start_time + test_duration_for_long_tests;
388*288bf522SAndroid Build Coastguard Worker   auto report_step = std::chrono::seconds(15);
389*288bf522SAndroid Build Coastguard Worker   size_t iterations = 0;
390*288bf522SAndroid Build Coastguard Worker 
391*288bf522SAndroid Build Coastguard Worker   while (cur_time < end_time && !cpu_toggle_arg.cpu_hotplug_failed) {
392*288bf522SAndroid Build Coastguard Worker     if (cur_time + report_step < std::chrono::steady_clock::now()) {
393*288bf522SAndroid Build Coastguard Worker       auto diff = std::chrono::duration_cast<std::chrono::seconds>(
394*288bf522SAndroid Build Coastguard Worker           std::chrono::steady_clock::now() - start_time);
395*288bf522SAndroid Build Coastguard Worker       if (verbose_mode) {
396*288bf522SAndroid Build Coastguard Worker         GTEST_LOG_(INFO) << "Have Tested " << (diff.count() / 60.0) << " minutes.";
397*288bf522SAndroid Build Coastguard Worker       }
398*288bf522SAndroid Build Coastguard Worker       cur_time = std::chrono::steady_clock::now();
399*288bf522SAndroid Build Coastguard Worker     }
400*288bf522SAndroid Build Coastguard Worker     // Test if the cpu pmu is still usable.
401*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(EventFd::OpenEventFile(attr, 0, -1, nullptr, event_type_modifier->name, true) !=
402*288bf522SAndroid Build Coastguard Worker                 nullptr);
403*288bf522SAndroid Build Coastguard Worker 
404*288bf522SAndroid Build Coastguard Worker     std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(
405*288bf522SAndroid Build Coastguard Worker         attr, cpu_spin_arg.tid, test_cpu, nullptr, event_type_modifier->name, false);
406*288bf522SAndroid Build Coastguard Worker     if (event_fd == nullptr) {
407*288bf522SAndroid Build Coastguard Worker       // Failed to open because the test_cpu is offline.
408*288bf522SAndroid Build Coastguard Worker       continue;
409*288bf522SAndroid Build Coastguard Worker     }
410*288bf522SAndroid Build Coastguard Worker     // profile for a while.
411*288bf522SAndroid Build Coastguard Worker     std::this_thread::sleep_for(std::chrono::milliseconds(1));
412*288bf522SAndroid Build Coastguard Worker     iterations++;
413*288bf522SAndroid Build Coastguard Worker     if (verbose_mode) {
414*288bf522SAndroid Build Coastguard Worker       GTEST_LOG_(INFO) << "Test offline while user process profiling for " << iterations
415*288bf522SAndroid Build Coastguard Worker                        << " times.";
416*288bf522SAndroid Build Coastguard Worker     }
417*288bf522SAndroid Build Coastguard Worker   }
418*288bf522SAndroid Build Coastguard Worker   if (cpu_toggle_arg.cpu_hotplug_failed) {
419*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "Test ends because of cpu hotplug failure.";
420*288bf522SAndroid Build Coastguard Worker   }
421*288bf522SAndroid Build Coastguard Worker   cpu_toggle_arg.end_flag = true;
422*288bf522SAndroid Build Coastguard Worker   cpu_toggle_thread.join();
423*288bf522SAndroid Build Coastguard Worker   cpu_spin_arg.end_flag = true;
424*288bf522SAndroid Build Coastguard Worker   cpu_spin_thread.join();
425*288bf522SAndroid Build Coastguard Worker   // Check if the cpu-cycle event is still available on test_cpu.
426*288bf522SAndroid Build Coastguard Worker   if (SetCpuOnline(test_cpu, true)) {
427*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(EventFd::OpenEventFile(attr, -1, test_cpu, nullptr, event_type_modifier->name,
428*288bf522SAndroid Build Coastguard Worker                                        true) != nullptr);
429*288bf522SAndroid Build Coastguard Worker   }
430*288bf522SAndroid Build Coastguard Worker }
431*288bf522SAndroid Build Coastguard Worker 
432*288bf522SAndroid Build Coastguard Worker // http://b/19863147.
TEST(cpu_offline,offline_while_recording_on_another_cpu)433*288bf522SAndroid Build Coastguard Worker TEST(cpu_offline, offline_while_recording_on_another_cpu) {
434*288bf522SAndroid Build Coastguard Worker   ScopedMpdecisionKiller scoped_mpdecision_killer;
435*288bf522SAndroid Build Coastguard Worker   CpuOnlineRestorer cpuonline_restorer;
436*288bf522SAndroid Build Coastguard Worker 
437*288bf522SAndroid Build Coastguard Worker   if (GetCpuCount() == 1) {
438*288bf522SAndroid Build Coastguard Worker     GTEST_LOG_(INFO) << "This test does nothing, because there is only one cpu in the system.";
439*288bf522SAndroid Build Coastguard Worker     return;
440*288bf522SAndroid Build Coastguard Worker   }
441*288bf522SAndroid Build Coastguard Worker   int test_cpu;
442*288bf522SAndroid Build Coastguard Worker   if (!FindAHotpluggableCpu(&test_cpu)) {
443*288bf522SAndroid Build Coastguard Worker     return;
444*288bf522SAndroid Build Coastguard Worker   }
445*288bf522SAndroid Build Coastguard Worker   std::unique_ptr<EventTypeAndModifier> event_type_modifier = ParseEventType("cpu-cycles");
446*288bf522SAndroid Build Coastguard Worker   perf_event_attr attr = CreateDefaultPerfEventAttr(event_type_modifier->event_type);
447*288bf522SAndroid Build Coastguard Worker   attr.disabled = 0;
448*288bf522SAndroid Build Coastguard Worker   attr.enable_on_exec = 0;
449*288bf522SAndroid Build Coastguard Worker 
450*288bf522SAndroid Build Coastguard Worker   const size_t TEST_ITERATION_COUNT = 10u;
451*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < TEST_ITERATION_COUNT; ++i) {
452*288bf522SAndroid Build Coastguard Worker     int record_cpu = 0;
453*288bf522SAndroid Build Coastguard Worker     if (!SetCpuOnline(test_cpu, true)) {
454*288bf522SAndroid Build Coastguard Worker       break;
455*288bf522SAndroid Build Coastguard Worker     }
456*288bf522SAndroid Build Coastguard Worker     std::unique_ptr<EventFd> event_fd =
457*288bf522SAndroid Build Coastguard Worker         EventFd::OpenEventFile(attr, getpid(), record_cpu, nullptr, event_type_modifier->name);
458*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(event_fd != nullptr);
459*288bf522SAndroid Build Coastguard Worker     if (!SetCpuOnline(test_cpu, false)) {
460*288bf522SAndroid Build Coastguard Worker       break;
461*288bf522SAndroid Build Coastguard Worker     }
462*288bf522SAndroid Build Coastguard Worker     event_fd = nullptr;
463*288bf522SAndroid Build Coastguard Worker     event_fd =
464*288bf522SAndroid Build Coastguard Worker         EventFd::OpenEventFile(attr, getpid(), record_cpu, nullptr, event_type_modifier->name);
465*288bf522SAndroid Build Coastguard Worker     ASSERT_TRUE(event_fd != nullptr);
466*288bf522SAndroid Build Coastguard Worker   }
467*288bf522SAndroid Build Coastguard Worker }
468*288bf522SAndroid Build Coastguard Worker 
main(int argc,char ** argv)469*288bf522SAndroid Build Coastguard Worker int main(int argc, char** argv) {
470*288bf522SAndroid Build Coastguard Worker   for (int i = 1; i < argc; ++i) {
471*288bf522SAndroid Build Coastguard Worker     if (strcmp(argv[i], "--help") == 0) {
472*288bf522SAndroid Build Coastguard Worker       printf("--long_test_duration <second> Set test duration for long tests. Default is 120s.\n");
473*288bf522SAndroid Build Coastguard Worker       printf(
474*288bf522SAndroid Build Coastguard Worker           "--cpu_hotplug_interval <microseconds> Set cpu hotplug interval. Default is 1000us.\n");
475*288bf522SAndroid Build Coastguard Worker       printf("--verbose  Show verbose log.\n");
476*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[i], "--long_test_duration") == 0) {
477*288bf522SAndroid Build Coastguard Worker       if (i + 1 < argc) {
478*288bf522SAndroid Build Coastguard Worker         int second_count = atoi(argv[i + 1]);
479*288bf522SAndroid Build Coastguard Worker         if (second_count <= 0) {
480*288bf522SAndroid Build Coastguard Worker           fprintf(stderr, "Invalid arg for --long_test_duration.\n");
481*288bf522SAndroid Build Coastguard Worker           return 1;
482*288bf522SAndroid Build Coastguard Worker         }
483*288bf522SAndroid Build Coastguard Worker         test_duration_for_long_tests = std::chrono::seconds(second_count);
484*288bf522SAndroid Build Coastguard Worker         i++;
485*288bf522SAndroid Build Coastguard Worker       }
486*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[i], "--cpu_hotplug_interval") == 0) {
487*288bf522SAndroid Build Coastguard Worker       if (i + 1 < argc) {
488*288bf522SAndroid Build Coastguard Worker         int microsecond_count = atoi(argv[i + 1]);
489*288bf522SAndroid Build Coastguard Worker         if (microsecond_count <= 0) {
490*288bf522SAndroid Build Coastguard Worker           fprintf(stderr, "Invalid arg for --cpu_hotplug_interval\n");
491*288bf522SAndroid Build Coastguard Worker           return 1;
492*288bf522SAndroid Build Coastguard Worker         }
493*288bf522SAndroid Build Coastguard Worker         cpu_hotplug_interval = std::chrono::microseconds(microsecond_count);
494*288bf522SAndroid Build Coastguard Worker         i++;
495*288bf522SAndroid Build Coastguard Worker       }
496*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[i], "--verbose") == 0) {
497*288bf522SAndroid Build Coastguard Worker       verbose_mode = true;
498*288bf522SAndroid Build Coastguard Worker     }
499*288bf522SAndroid Build Coastguard Worker   }
500*288bf522SAndroid Build Coastguard Worker   testing::InitGoogleTest(&argc, argv);
501*288bf522SAndroid Build Coastguard Worker   android::base::InitLogging(argv, android::base::StderrLogger);
502*288bf522SAndroid Build Coastguard Worker   return RUN_ALL_TESTS();
503*288bf522SAndroid Build Coastguard Worker }
504