1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include <errno.h>
18*6dbdd20aSAndroid Build Coastguard Worker #include <fcntl.h>
19*6dbdd20aSAndroid Build Coastguard Worker #include <signal.h>
20*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <stdlib.h>
22*6dbdd20aSAndroid Build Coastguard Worker #include <string.h>
23*6dbdd20aSAndroid Build Coastguard Worker #include <sys/stat.h>
24*6dbdd20aSAndroid Build Coastguard Worker #include <sys/types.h>
25*6dbdd20aSAndroid Build Coastguard Worker #include <unistd.h>
26*6dbdd20aSAndroid Build Coastguard Worker
27*6dbdd20aSAndroid Build Coastguard Worker #include <cinttypes>
28*6dbdd20aSAndroid Build Coastguard Worker #include <memory>
29*6dbdd20aSAndroid Build Coastguard Worker
30*6dbdd20aSAndroid Build Coastguard Worker namespace {
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker constexpr auto kIdleSize = 10000 * 4096;
33*6dbdd20aSAndroid Build Coastguard Worker constexpr auto kNoIdleSize = 1000 * 4096;
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard Worker static bool interrupted = false;
36*6dbdd20aSAndroid Build Coastguard Worker
37*6dbdd20aSAndroid Build Coastguard Worker volatile unsigned char* __attribute__((noinline)) AllocIdle(size_t bytes);
AllocIdle(size_t bytes)38*6dbdd20aSAndroid Build Coastguard Worker volatile unsigned char* __attribute__((noinline)) AllocIdle(size_t bytes) {
39*6dbdd20aSAndroid Build Coastguard Worker // This volatile is needed to prevent the compiler from trying to be
40*6dbdd20aSAndroid Build Coastguard Worker // helpful and compiling a "useless" malloc + free into a noop.
41*6dbdd20aSAndroid Build Coastguard Worker volatile unsigned char* x = static_cast<unsigned char*>(malloc(bytes));
42*6dbdd20aSAndroid Build Coastguard Worker if (x) {
43*6dbdd20aSAndroid Build Coastguard Worker x[1] = 'x';
44*6dbdd20aSAndroid Build Coastguard Worker }
45*6dbdd20aSAndroid Build Coastguard Worker return x;
46*6dbdd20aSAndroid Build Coastguard Worker }
47*6dbdd20aSAndroid Build Coastguard Worker
48*6dbdd20aSAndroid Build Coastguard Worker volatile unsigned char* __attribute__((noinline)) AllocNoIdle(size_t bytes);
AllocNoIdle(size_t bytes)49*6dbdd20aSAndroid Build Coastguard Worker volatile unsigned char* __attribute__((noinline)) AllocNoIdle(size_t bytes) {
50*6dbdd20aSAndroid Build Coastguard Worker // This volatile is needed to prevent the compiler from trying to be
51*6dbdd20aSAndroid Build Coastguard Worker // helpful and compiling a "useless" malloc + free into a noop.
52*6dbdd20aSAndroid Build Coastguard Worker volatile unsigned char* x = static_cast<unsigned char*>(malloc(bytes));
53*6dbdd20aSAndroid Build Coastguard Worker if (x) {
54*6dbdd20aSAndroid Build Coastguard Worker x[0] = 'x';
55*6dbdd20aSAndroid Build Coastguard Worker }
56*6dbdd20aSAndroid Build Coastguard Worker return x;
57*6dbdd20aSAndroid Build Coastguard Worker }
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Worker class MemoryToucher {
60*6dbdd20aSAndroid Build Coastguard Worker public:
61*6dbdd20aSAndroid Build Coastguard Worker virtual void Touch(volatile unsigned char* nonidle) = 0;
62*6dbdd20aSAndroid Build Coastguard Worker virtual ~MemoryToucher() = default;
63*6dbdd20aSAndroid Build Coastguard Worker };
64*6dbdd20aSAndroid Build Coastguard Worker
65*6dbdd20aSAndroid Build Coastguard Worker class ReadDevZeroChunks : public MemoryToucher {
66*6dbdd20aSAndroid Build Coastguard Worker public:
ReadDevZeroChunks(size_t chunk_size)67*6dbdd20aSAndroid Build Coastguard Worker ReadDevZeroChunks(size_t chunk_size)
68*6dbdd20aSAndroid Build Coastguard Worker : chunk_size_(chunk_size), fd_(open("/dev/zero", O_RDONLY)) {
69*6dbdd20aSAndroid Build Coastguard Worker if (fd_ == -1) {
70*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Failed to open: %s", strerror(errno));
71*6dbdd20aSAndroid Build Coastguard Worker abort();
72*6dbdd20aSAndroid Build Coastguard Worker }
73*6dbdd20aSAndroid Build Coastguard Worker }
74*6dbdd20aSAndroid Build Coastguard Worker
75*6dbdd20aSAndroid Build Coastguard Worker ~ReadDevZeroChunks() override = default;
76*6dbdd20aSAndroid Build Coastguard Worker
Touch(volatile unsigned char * nonidle)77*6dbdd20aSAndroid Build Coastguard Worker void Touch(volatile unsigned char* nonidle) override {
78*6dbdd20aSAndroid Build Coastguard Worker size_t total_rd = 0;
79*6dbdd20aSAndroid Build Coastguard Worker while (total_rd < kNoIdleSize) {
80*6dbdd20aSAndroid Build Coastguard Worker size_t chunk = chunk_size_;
81*6dbdd20aSAndroid Build Coastguard Worker if (chunk > kNoIdleSize - total_rd)
82*6dbdd20aSAndroid Build Coastguard Worker chunk = kNoIdleSize - total_rd;
83*6dbdd20aSAndroid Build Coastguard Worker
84*6dbdd20aSAndroid Build Coastguard Worker ssize_t rd =
85*6dbdd20aSAndroid Build Coastguard Worker read(fd_, const_cast<unsigned char*>(nonidle) + total_rd, chunk);
86*6dbdd20aSAndroid Build Coastguard Worker if (rd == -1) {
87*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Failed to write: %s.", strerror(errno));
88*6dbdd20aSAndroid Build Coastguard Worker abort();
89*6dbdd20aSAndroid Build Coastguard Worker }
90*6dbdd20aSAndroid Build Coastguard Worker total_rd += static_cast<size_t>(rd);
91*6dbdd20aSAndroid Build Coastguard Worker }
92*6dbdd20aSAndroid Build Coastguard Worker }
93*6dbdd20aSAndroid Build Coastguard Worker
94*6dbdd20aSAndroid Build Coastguard Worker private:
95*6dbdd20aSAndroid Build Coastguard Worker size_t chunk_size_;
96*6dbdd20aSAndroid Build Coastguard Worker int fd_;
97*6dbdd20aSAndroid Build Coastguard Worker };
98*6dbdd20aSAndroid Build Coastguard Worker
99*6dbdd20aSAndroid Build Coastguard Worker class ReadDevZeroChunksAndSleep : public ReadDevZeroChunks {
100*6dbdd20aSAndroid Build Coastguard Worker public:
ReadDevZeroChunksAndSleep(size_t chunk_size)101*6dbdd20aSAndroid Build Coastguard Worker ReadDevZeroChunksAndSleep(size_t chunk_size)
102*6dbdd20aSAndroid Build Coastguard Worker : ReadDevZeroChunks(chunk_size) {}
Touch(volatile unsigned char * nonidle)103*6dbdd20aSAndroid Build Coastguard Worker void Touch(volatile unsigned char* nonidle) override {
104*6dbdd20aSAndroid Build Coastguard Worker ReadDevZeroChunks::Touch(nonidle);
105*6dbdd20aSAndroid Build Coastguard Worker sleep(1);
106*6dbdd20aSAndroid Build Coastguard Worker }
107*6dbdd20aSAndroid Build Coastguard Worker };
108*6dbdd20aSAndroid Build Coastguard Worker
109*6dbdd20aSAndroid Build Coastguard Worker class SumUp : public MemoryToucher {
110*6dbdd20aSAndroid Build Coastguard Worker public:
SumUp()111*6dbdd20aSAndroid Build Coastguard Worker SumUp()
112*6dbdd20aSAndroid Build Coastguard Worker : sum_(const_cast<volatile uint64_t*>(
113*6dbdd20aSAndroid Build Coastguard Worker static_cast<uint64_t*>(malloc(sizeof(uint64_t))))) {}
114*6dbdd20aSAndroid Build Coastguard Worker ~SumUp() override = default;
115*6dbdd20aSAndroid Build Coastguard Worker
Touch(volatile unsigned char * nonidle)116*6dbdd20aSAndroid Build Coastguard Worker void Touch(volatile unsigned char* nonidle) override {
117*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < kNoIdleSize; ++i)
118*6dbdd20aSAndroid Build Coastguard Worker *sum_ += nonidle[i];
119*6dbdd20aSAndroid Build Coastguard Worker }
120*6dbdd20aSAndroid Build Coastguard Worker
121*6dbdd20aSAndroid Build Coastguard Worker private:
122*6dbdd20aSAndroid Build Coastguard Worker volatile uint64_t* sum_;
123*6dbdd20aSAndroid Build Coastguard Worker };
124*6dbdd20aSAndroid Build Coastguard Worker
125*6dbdd20aSAndroid Build Coastguard Worker class ReadDevZeroChunksAndSum : public ReadDevZeroChunks {
126*6dbdd20aSAndroid Build Coastguard Worker public:
ReadDevZeroChunksAndSum(size_t chunk_size)127*6dbdd20aSAndroid Build Coastguard Worker ReadDevZeroChunksAndSum(size_t chunk_size) : ReadDevZeroChunks(chunk_size) {}
Touch(volatile unsigned char * nonidle)128*6dbdd20aSAndroid Build Coastguard Worker void Touch(volatile unsigned char* nonidle) override {
129*6dbdd20aSAndroid Build Coastguard Worker ReadDevZeroChunks::Touch(nonidle);
130*6dbdd20aSAndroid Build Coastguard Worker sum_up_.Touch(nonidle);
131*6dbdd20aSAndroid Build Coastguard Worker }
132*6dbdd20aSAndroid Build Coastguard Worker
133*6dbdd20aSAndroid Build Coastguard Worker private:
134*6dbdd20aSAndroid Build Coastguard Worker SumUp sum_up_;
135*6dbdd20aSAndroid Build Coastguard Worker };
136*6dbdd20aSAndroid Build Coastguard Worker
137*6dbdd20aSAndroid Build Coastguard Worker class AssignValues : public MemoryToucher {
138*6dbdd20aSAndroid Build Coastguard Worker public:
139*6dbdd20aSAndroid Build Coastguard Worker ~AssignValues() override = default;
140*6dbdd20aSAndroid Build Coastguard Worker
Touch(volatile unsigned char * nonidle)141*6dbdd20aSAndroid Build Coastguard Worker void Touch(volatile unsigned char* nonidle) override {
142*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < kNoIdleSize; ++i)
143*6dbdd20aSAndroid Build Coastguard Worker nonidle[i] = static_cast<unsigned char>(i % 256);
144*6dbdd20aSAndroid Build Coastguard Worker }
145*6dbdd20aSAndroid Build Coastguard Worker };
146*6dbdd20aSAndroid Build Coastguard Worker
147*6dbdd20aSAndroid Build Coastguard Worker } // namespace
148*6dbdd20aSAndroid Build Coastguard Worker
main(int argc,char ** argv)149*6dbdd20aSAndroid Build Coastguard Worker int main(int argc, char** argv) {
150*6dbdd20aSAndroid Build Coastguard Worker volatile auto* idle = AllocIdle(kIdleSize);
151*6dbdd20aSAndroid Build Coastguard Worker volatile auto* nonidle = AllocNoIdle(kNoIdleSize);
152*6dbdd20aSAndroid Build Coastguard Worker
153*6dbdd20aSAndroid Build Coastguard Worker printf("Own PID: %" PRIdMAX "\n", static_cast<intmax_t>(getpid()));
154*6dbdd20aSAndroid Build Coastguard Worker printf("Idle: %p\n", static_cast<void*>(const_cast<unsigned char*>(idle)));
155*6dbdd20aSAndroid Build Coastguard Worker printf("Nonidle: %p\n",
156*6dbdd20aSAndroid Build Coastguard Worker static_cast<void*>(const_cast<unsigned char*>(nonidle)));
157*6dbdd20aSAndroid Build Coastguard Worker
158*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < kIdleSize; ++i)
159*6dbdd20aSAndroid Build Coastguard Worker idle[i] = static_cast<unsigned char>(i % 256);
160*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < kNoIdleSize; ++i)
161*6dbdd20aSAndroid Build Coastguard Worker nonidle[i] = static_cast<unsigned char>(i % 256);
162*6dbdd20aSAndroid Build Coastguard Worker
163*6dbdd20aSAndroid Build Coastguard Worker printf("Allocated everything.\n");
164*6dbdd20aSAndroid Build Coastguard Worker
165*6dbdd20aSAndroid Build Coastguard Worker struct sigaction action = {};
166*6dbdd20aSAndroid Build Coastguard Worker action.sa_handler = [](int) { interrupted = true; };
167*6dbdd20aSAndroid Build Coastguard Worker if (sigaction(SIGUSR1, &action, nullptr) != 0) {
168*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Failed to register signal handler.\n");
169*6dbdd20aSAndroid Build Coastguard Worker abort();
170*6dbdd20aSAndroid Build Coastguard Worker }
171*6dbdd20aSAndroid Build Coastguard Worker
172*6dbdd20aSAndroid Build Coastguard Worker if (argc < 2) {
173*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr,
174*6dbdd20aSAndroid Build Coastguard Worker "Specifiy one of AssignValues / SumUp / ReadDevZeroChunks\n");
175*6dbdd20aSAndroid Build Coastguard Worker abort();
176*6dbdd20aSAndroid Build Coastguard Worker }
177*6dbdd20aSAndroid Build Coastguard Worker
178*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<MemoryToucher> toucher;
179*6dbdd20aSAndroid Build Coastguard Worker if (strcmp(argv[1], "AssignValues") == 0) {
180*6dbdd20aSAndroid Build Coastguard Worker toucher.reset(new AssignValues());
181*6dbdd20aSAndroid Build Coastguard Worker printf("Using AssignValues.\n");
182*6dbdd20aSAndroid Build Coastguard Worker } else if (strcmp(argv[1], "SumUp") == 0) {
183*6dbdd20aSAndroid Build Coastguard Worker toucher.reset(new SumUp());
184*6dbdd20aSAndroid Build Coastguard Worker printf("Using SumUp.\n");
185*6dbdd20aSAndroid Build Coastguard Worker } else if (strcmp(argv[1], "ReadDevZeroChunks") == 0 ||
186*6dbdd20aSAndroid Build Coastguard Worker strcmp(argv[1], "ReadDevZeroChunksAndSleep") == 0 ||
187*6dbdd20aSAndroid Build Coastguard Worker strcmp(argv[1], "ReadDevZeroChunksAndSum") == 0) {
188*6dbdd20aSAndroid Build Coastguard Worker if (argc < 3) {
189*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Specify chunk size.\n");
190*6dbdd20aSAndroid Build Coastguard Worker abort();
191*6dbdd20aSAndroid Build Coastguard Worker }
192*6dbdd20aSAndroid Build Coastguard Worker char* end;
193*6dbdd20aSAndroid Build Coastguard Worker long long chunk_arg = strtoll(argv[2], &end, 10);
194*6dbdd20aSAndroid Build Coastguard Worker if (*end != '\0' || *argv[2] == '\0') {
195*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Invalid chunk size: %s\n", argv[2]);
196*6dbdd20aSAndroid Build Coastguard Worker abort();
197*6dbdd20aSAndroid Build Coastguard Worker }
198*6dbdd20aSAndroid Build Coastguard Worker if (strcmp(argv[1], "ReadDevZeroChunksAndSleep") == 0) {
199*6dbdd20aSAndroid Build Coastguard Worker printf("Using ReadDevZeroChunksAndSleep.\n");
200*6dbdd20aSAndroid Build Coastguard Worker toucher.reset(
201*6dbdd20aSAndroid Build Coastguard Worker new ReadDevZeroChunksAndSleep(static_cast<size_t>(chunk_arg)));
202*6dbdd20aSAndroid Build Coastguard Worker } else if (strcmp(argv[1], "ReadDevZeroChunksAndSum") == 0) {
203*6dbdd20aSAndroid Build Coastguard Worker printf("Using ReadDevZeroChunksAndSum.\n");
204*6dbdd20aSAndroid Build Coastguard Worker toucher.reset(
205*6dbdd20aSAndroid Build Coastguard Worker new ReadDevZeroChunksAndSum(static_cast<size_t>(chunk_arg)));
206*6dbdd20aSAndroid Build Coastguard Worker } else {
207*6dbdd20aSAndroid Build Coastguard Worker printf("Using ReadDevZeroChunks.\n");
208*6dbdd20aSAndroid Build Coastguard Worker toucher.reset(new ReadDevZeroChunks(static_cast<size_t>(chunk_arg)));
209*6dbdd20aSAndroid Build Coastguard Worker }
210*6dbdd20aSAndroid Build Coastguard Worker } else {
211*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, "Invalid input.\n");
212*6dbdd20aSAndroid Build Coastguard Worker abort();
213*6dbdd20aSAndroid Build Coastguard Worker }
214*6dbdd20aSAndroid Build Coastguard Worker
215*6dbdd20aSAndroid Build Coastguard Worker while (true) {
216*6dbdd20aSAndroid Build Coastguard Worker bool report = interrupted;
217*6dbdd20aSAndroid Build Coastguard Worker if (report) {
218*6dbdd20aSAndroid Build Coastguard Worker printf("Waiting to finish touching everything.\n");
219*6dbdd20aSAndroid Build Coastguard Worker interrupted = false;
220*6dbdd20aSAndroid Build Coastguard Worker sleep(2);
221*6dbdd20aSAndroid Build Coastguard Worker }
222*6dbdd20aSAndroid Build Coastguard Worker
223*6dbdd20aSAndroid Build Coastguard Worker toucher->Touch(nonidle);
224*6dbdd20aSAndroid Build Coastguard Worker
225*6dbdd20aSAndroid Build Coastguard Worker if (report)
226*6dbdd20aSAndroid Build Coastguard Worker printf("Touched everything.\n");
227*6dbdd20aSAndroid Build Coastguard Worker }
228*6dbdd20aSAndroid Build Coastguard Worker }
229