1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker *
4*8d67ca89SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker *
8*8d67ca89SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker *
10*8d67ca89SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker */
16*8d67ca89SAndroid Build Coastguard Worker
17*8d67ca89SAndroid Build Coastguard Worker #include <string.h>
18*8d67ca89SAndroid Build Coastguard Worker #include <sys/mman.h>
19*8d67ca89SAndroid Build Coastguard Worker #include <sys/syscall.h>
20*8d67ca89SAndroid Build Coastguard Worker
21*8d67ca89SAndroid Build Coastguard Worker #include <android-base/file.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
24*8d67ca89SAndroid Build Coastguard Worker
25*8d67ca89SAndroid Build Coastguard Worker #include "util.h"
26*8d67ca89SAndroid Build Coastguard Worker
27*8d67ca89SAndroid Build Coastguard Worker enum BenchmarkType : uint8_t {
28*8d67ca89SAndroid Build Coastguard Worker kBenchmarkMmapOnly,
29*8d67ca89SAndroid Build Coastguard Worker kBenchmarkMunmapOnly,
30*8d67ca89SAndroid Build Coastguard Worker kBenchmarkAll,
31*8d67ca89SAndroid Build Coastguard Worker };
32*8d67ca89SAndroid Build Coastguard Worker
33*8d67ca89SAndroid Build Coastguard Worker static size_t page_sz = getpagesize();
34*8d67ca89SAndroid Build Coastguard Worker
35*8d67ca89SAndroid Build Coastguard Worker struct MmapParams {
36*8d67ca89SAndroid Build Coastguard Worker int prot;
37*8d67ca89SAndroid Build Coastguard Worker int flags;
38*8d67ca89SAndroid Build Coastguard Worker int64_t size;
39*8d67ca89SAndroid Build Coastguard Worker };
40*8d67ca89SAndroid Build Coastguard Worker
41*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams {
42*8d67ca89SAndroid Build Coastguard Worker int initial_prot;
43*8d67ca89SAndroid Build Coastguard Worker int mprotect_prot;
44*8d67ca89SAndroid Build Coastguard Worker int64_t size;
45*8d67ca89SAndroid Build Coastguard Worker };
46*8d67ca89SAndroid Build Coastguard Worker
47*8d67ca89SAndroid Build Coastguard Worker template <BenchmarkType type>
MmapBenchmarkImpl(benchmark::State & state,const struct MmapParams & params,int fd,void * area=nullptr)48*8d67ca89SAndroid Build Coastguard Worker void MmapBenchmarkImpl(benchmark::State& state, const struct MmapParams& params, int fd,
49*8d67ca89SAndroid Build Coastguard Worker void* area = nullptr) {
50*8d67ca89SAndroid Build Coastguard Worker for (auto _ : state) {
51*8d67ca89SAndroid Build Coastguard Worker if (type == kBenchmarkMunmapOnly) state.PauseTiming();
52*8d67ca89SAndroid Build Coastguard Worker void* addr = mmap(area, params.size, params.prot, params.flags, fd, 0);
53*8d67ca89SAndroid Build Coastguard Worker if (addr == MAP_FAILED) {
54*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("mmap failed: %s", strerror(errno)).c_str());
55*8d67ca89SAndroid Build Coastguard Worker break;
56*8d67ca89SAndroid Build Coastguard Worker }
57*8d67ca89SAndroid Build Coastguard Worker
58*8d67ca89SAndroid Build Coastguard Worker if (type == kBenchmarkMmapOnly) state.PauseTiming();
59*8d67ca89SAndroid Build Coastguard Worker
60*8d67ca89SAndroid Build Coastguard Worker if (params.prot & PROT_WRITE) {
61*8d67ca89SAndroid Build Coastguard Worker MakeAllocationResident(addr, params.size, page_sz);
62*8d67ca89SAndroid Build Coastguard Worker }
63*8d67ca89SAndroid Build Coastguard Worker
64*8d67ca89SAndroid Build Coastguard Worker if (type == kBenchmarkMunmapOnly) state.ResumeTiming();
65*8d67ca89SAndroid Build Coastguard Worker
66*8d67ca89SAndroid Build Coastguard Worker if (munmap(addr, params.size) != 0) {
67*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(
68*8d67ca89SAndroid Build Coastguard Worker android::base::StringPrintf("munmap failed: %s", strerror(errno)).c_str());
69*8d67ca89SAndroid Build Coastguard Worker break;
70*8d67ca89SAndroid Build Coastguard Worker }
71*8d67ca89SAndroid Build Coastguard Worker if (type == kBenchmarkMmapOnly) state.ResumeTiming();
72*8d67ca89SAndroid Build Coastguard Worker }
73*8d67ca89SAndroid Build Coastguard Worker }
74*8d67ca89SAndroid Build Coastguard Worker
MmapBenchmark(benchmark::State & state,const struct MmapParams & params,int fd,void * area=nullptr)75*8d67ca89SAndroid Build Coastguard Worker static void MmapBenchmark(benchmark::State& state, const struct MmapParams& params, int fd,
76*8d67ca89SAndroid Build Coastguard Worker void* area = nullptr) {
77*8d67ca89SAndroid Build Coastguard Worker MmapBenchmarkImpl<kBenchmarkAll>(state, params, fd, area);
78*8d67ca89SAndroid Build Coastguard Worker }
79*8d67ca89SAndroid Build Coastguard Worker
MmapFixedBenchmark(benchmark::State & state,const struct MmapParams & params,int fd,size_t area_size,size_t offs)80*8d67ca89SAndroid Build Coastguard Worker static void MmapFixedBenchmark(benchmark::State& state, const struct MmapParams& params, int fd,
81*8d67ca89SAndroid Build Coastguard Worker size_t area_size, size_t offs) {
82*8d67ca89SAndroid Build Coastguard Worker if ((params.flags & MAP_FIXED) == 0) {
83*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError("MmapFixedBenchmark called without MAP_FIXED set");
84*8d67ca89SAndroid Build Coastguard Worker return;
85*8d67ca89SAndroid Build Coastguard Worker }
86*8d67ca89SAndroid Build Coastguard Worker
87*8d67ca89SAndroid Build Coastguard Worker // Create the mmap that will be used for the fixed mmaps.
88*8d67ca89SAndroid Build Coastguard Worker uint8_t* area = reinterpret_cast<uint8_t*>(
89*8d67ca89SAndroid Build Coastguard Worker mmap(nullptr, area_size, params.prot, params.flags & ~MAP_FIXED, fd, 0));
90*8d67ca89SAndroid Build Coastguard Worker if (area == MAP_FAILED) {
91*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("mmap failed: %s", strerror(errno)).c_str());
92*8d67ca89SAndroid Build Coastguard Worker return;
93*8d67ca89SAndroid Build Coastguard Worker }
94*8d67ca89SAndroid Build Coastguard Worker
95*8d67ca89SAndroid Build Coastguard Worker MmapBenchmark(state, params, fd, area + offs);
96*8d67ca89SAndroid Build Coastguard Worker
97*8d67ca89SAndroid Build Coastguard Worker if (munmap(area, area_size) != 0) {
98*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("munmap failed: %s", strerror(errno)).c_str());
99*8d67ca89SAndroid Build Coastguard Worker return;
100*8d67ca89SAndroid Build Coastguard Worker }
101*8d67ca89SAndroid Build Coastguard Worker }
102*8d67ca89SAndroid Build Coastguard Worker
MmapFileBenchmark(benchmark::State & state,const struct MmapParams & params,size_t area_size,size_t offs)103*8d67ca89SAndroid Build Coastguard Worker static void MmapFileBenchmark(benchmark::State& state, const struct MmapParams& params,
104*8d67ca89SAndroid Build Coastguard Worker size_t area_size, size_t offs) {
105*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
106*8d67ca89SAndroid Build Coastguard Worker
107*8d67ca89SAndroid Build Coastguard Worker if (tf.fd < 0) {
108*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(
109*8d67ca89SAndroid Build Coastguard Worker android::base::StringPrintf("failed to create a temporary file: %s", strerror(errno))
110*8d67ca89SAndroid Build Coastguard Worker .c_str());
111*8d67ca89SAndroid Build Coastguard Worker return;
112*8d67ca89SAndroid Build Coastguard Worker }
113*8d67ca89SAndroid Build Coastguard Worker
114*8d67ca89SAndroid Build Coastguard Worker if (area_size > 0 && ftruncate(tf.fd, area_size)) {
115*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(
116*8d67ca89SAndroid Build Coastguard Worker android::base::StringPrintf("ftruncate failed: %s", strerror(errno)).c_str());
117*8d67ca89SAndroid Build Coastguard Worker return;
118*8d67ca89SAndroid Build Coastguard Worker }
119*8d67ca89SAndroid Build Coastguard Worker
120*8d67ca89SAndroid Build Coastguard Worker if (params.flags & MAP_FIXED) {
121*8d67ca89SAndroid Build Coastguard Worker MmapFixedBenchmark(state, params, tf.fd, area_size, offs);
122*8d67ca89SAndroid Build Coastguard Worker } else {
123*8d67ca89SAndroid Build Coastguard Worker MmapBenchmark(state, params, tf.fd);
124*8d67ca89SAndroid Build Coastguard Worker }
125*8d67ca89SAndroid Build Coastguard Worker }
126*8d67ca89SAndroid Build Coastguard Worker
127*8d67ca89SAndroid Build Coastguard Worker // anon mmap
BM_syscall_mmap_anon_rw(benchmark::State & state)128*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_rw(benchmark::State& state) {
129*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
130*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
131*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
132*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
133*8d67ca89SAndroid Build Coastguard Worker };
134*8d67ca89SAndroid Build Coastguard Worker
135*8d67ca89SAndroid Build Coastguard Worker MmapBenchmark(state, params, 0);
136*8d67ca89SAndroid Build Coastguard Worker }
137*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_rw, "AT_ALL_PAGE_SIZES");
138*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_noreserve(benchmark::State & state)139*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_noreserve(benchmark::State& state) {
140*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
141*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_NONE,
142*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
143*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
144*8d67ca89SAndroid Build Coastguard Worker };
145*8d67ca89SAndroid Build Coastguard Worker
146*8d67ca89SAndroid Build Coastguard Worker MmapBenchmark(state, params, 0);
147*8d67ca89SAndroid Build Coastguard Worker }
148*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_noreserve, "AT_ALL_PAGE_SIZES");
149*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_none(benchmark::State & state)150*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_none(benchmark::State& state) {
151*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
152*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_NONE,
153*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
154*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
155*8d67ca89SAndroid Build Coastguard Worker };
156*8d67ca89SAndroid Build Coastguard Worker
157*8d67ca89SAndroid Build Coastguard Worker MmapBenchmark(state, params, 0);
158*8d67ca89SAndroid Build Coastguard Worker }
159*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_none, "AT_ALL_PAGE_SIZES");
160*8d67ca89SAndroid Build Coastguard Worker
161*8d67ca89SAndroid Build Coastguard Worker // anon fixed mmap
BM_syscall_mmap_anon_rw_fixed(benchmark::State & state)162*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_rw_fixed(benchmark::State& state) {
163*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
164*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
165*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
166*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
167*8d67ca89SAndroid Build Coastguard Worker };
168*8d67ca89SAndroid Build Coastguard Worker
169*8d67ca89SAndroid Build Coastguard Worker MmapFixedBenchmark(state, params, -1, params.size, 0);
170*8d67ca89SAndroid Build Coastguard Worker }
171*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_rw_fixed, "AT_ALL_PAGE_SIZES");
172*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_none_fixed(benchmark::State & state)173*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_none_fixed(benchmark::State& state) {
174*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
175*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_NONE,
176*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
177*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
178*8d67ca89SAndroid Build Coastguard Worker };
179*8d67ca89SAndroid Build Coastguard Worker
180*8d67ca89SAndroid Build Coastguard Worker MmapFixedBenchmark(state, params, -1, params.size, 0);
181*8d67ca89SAndroid Build Coastguard Worker }
182*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_none_fixed, "AT_ALL_PAGE_SIZES");
183*8d67ca89SAndroid Build Coastguard Worker
184*8d67ca89SAndroid Build Coastguard Worker // file mmap
BM_syscall_mmap_file_rd_priv(benchmark::State & state)185*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_rd_priv(benchmark::State& state) {
186*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
187*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ,
188*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE,
189*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
190*8d67ca89SAndroid Build Coastguard Worker };
191*8d67ca89SAndroid Build Coastguard Worker
192*8d67ca89SAndroid Build Coastguard Worker MmapFileBenchmark(state, params, params.size, 0);
193*8d67ca89SAndroid Build Coastguard Worker }
194*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_rd_priv, "AT_ALL_PAGE_SIZES");
195*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_rw_shared(benchmark::State & state)196*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_rw_shared(benchmark::State& state) {
197*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
198*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
199*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_SHARED,
200*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
201*8d67ca89SAndroid Build Coastguard Worker };
202*8d67ca89SAndroid Build Coastguard Worker
203*8d67ca89SAndroid Build Coastguard Worker MmapFileBenchmark(state, params, params.size, 0);
204*8d67ca89SAndroid Build Coastguard Worker }
205*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_rw_shared, "AT_ALL_PAGE_SIZES");
206*8d67ca89SAndroid Build Coastguard Worker
207*8d67ca89SAndroid Build Coastguard Worker // file fixed mmap
BM_syscall_mmap_file_rw_priv_fixed_start(benchmark::State & state)208*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_rw_priv_fixed_start(benchmark::State& state) {
209*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
210*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
211*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_FIXED,
212*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
213*8d67ca89SAndroid Build Coastguard Worker };
214*8d67ca89SAndroid Build Coastguard Worker
215*8d67ca89SAndroid Build Coastguard Worker // allocate 3x area and map at the start
216*8d67ca89SAndroid Build Coastguard Worker MmapFileBenchmark(state, params, params.size * 3, 0);
217*8d67ca89SAndroid Build Coastguard Worker }
218*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_rw_priv_fixed_start, "AT_ALL_PAGE_SIZES");
219*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_rw_priv_fixed_mid(benchmark::State & state)220*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_rw_priv_fixed_mid(benchmark::State& state) {
221*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
222*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
223*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_FIXED,
224*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
225*8d67ca89SAndroid Build Coastguard Worker };
226*8d67ca89SAndroid Build Coastguard Worker
227*8d67ca89SAndroid Build Coastguard Worker // allocate 3x area and map at the middle
228*8d67ca89SAndroid Build Coastguard Worker MmapFileBenchmark(state, params, params.size * 3, params.size);
229*8d67ca89SAndroid Build Coastguard Worker }
230*8d67ca89SAndroid Build Coastguard Worker // mapping at sub-page size offset is not supported, so run only for AT_MULTI_PAGE_SIZES
231*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_rw_priv_fixed_mid, "AT_MULTI_PAGE_SIZES");
232*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_rw_priv_fixed_end(benchmark::State & state)233*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_rw_priv_fixed_end(benchmark::State& state) {
234*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
235*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
236*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_FIXED,
237*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
238*8d67ca89SAndroid Build Coastguard Worker };
239*8d67ca89SAndroid Build Coastguard Worker
240*8d67ca89SAndroid Build Coastguard Worker // allocate 3x area and map at the end
241*8d67ca89SAndroid Build Coastguard Worker MmapFileBenchmark(state, params, params.size * 3, params.size * 2);
242*8d67ca89SAndroid Build Coastguard Worker }
243*8d67ca89SAndroid Build Coastguard Worker // mapping at sub-page size offset is not supported, so run only for AT_MULTI_PAGE_SIZES
244*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_rw_priv_fixed_end, "AT_MULTI_PAGE_SIZES");
245*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_mmap_only(benchmark::State & state)246*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_mmap_only(benchmark::State& state) {
247*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
248*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
249*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
250*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
251*8d67ca89SAndroid Build Coastguard Worker };
252*8d67ca89SAndroid Build Coastguard Worker MmapBenchmarkImpl<kBenchmarkMmapOnly>(state, params, 0);
253*8d67ca89SAndroid Build Coastguard Worker }
254*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_mmap_only, "AT_MULTI_PAGE_SIZES");
255*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_munmap_only(benchmark::State & state)256*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_munmap_only(benchmark::State& state) {
257*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
258*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
259*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
260*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
261*8d67ca89SAndroid Build Coastguard Worker };
262*8d67ca89SAndroid Build Coastguard Worker MmapBenchmarkImpl<kBenchmarkMunmapOnly>(state, params, 0);
263*8d67ca89SAndroid Build Coastguard Worker }
264*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_munmap_only, "AT_MULTI_PAGE_SIZES");
265*8d67ca89SAndroid Build Coastguard Worker
MadviseBenchmark(benchmark::State & state,const struct MmapParams & params,int madvise_flags)266*8d67ca89SAndroid Build Coastguard Worker void MadviseBenchmark(benchmark::State& state, const struct MmapParams& params, int madvise_flags) {
267*8d67ca89SAndroid Build Coastguard Worker void* addr = mmap(nullptr, params.size, params.prot, params.flags, 0, 0);
268*8d67ca89SAndroid Build Coastguard Worker if (addr == MAP_FAILED) {
269*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("mmap failed: %s", strerror(errno)).c_str());
270*8d67ca89SAndroid Build Coastguard Worker return;
271*8d67ca89SAndroid Build Coastguard Worker }
272*8d67ca89SAndroid Build Coastguard Worker for (auto _ : state) {
273*8d67ca89SAndroid Build Coastguard Worker state.PauseTiming();
274*8d67ca89SAndroid Build Coastguard Worker if (params.prot & PROT_WRITE) {
275*8d67ca89SAndroid Build Coastguard Worker MakeAllocationResident(addr, params.size, page_sz);
276*8d67ca89SAndroid Build Coastguard Worker }
277*8d67ca89SAndroid Build Coastguard Worker state.ResumeTiming();
278*8d67ca89SAndroid Build Coastguard Worker
279*8d67ca89SAndroid Build Coastguard Worker madvise(addr, params.size, madvise_flags);
280*8d67ca89SAndroid Build Coastguard Worker }
281*8d67ca89SAndroid Build Coastguard Worker
282*8d67ca89SAndroid Build Coastguard Worker if (munmap(addr, params.size) != 0) {
283*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("munmap failed: %s", strerror(errno)).c_str());
284*8d67ca89SAndroid Build Coastguard Worker }
285*8d67ca89SAndroid Build Coastguard Worker }
286*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_madvise_dontneed(benchmark::State & state)287*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_madvise_dontneed(benchmark::State& state) {
288*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
289*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
290*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
291*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
292*8d67ca89SAndroid Build Coastguard Worker };
293*8d67ca89SAndroid Build Coastguard Worker MadviseBenchmark(state, params, MADV_DONTNEED);
294*8d67ca89SAndroid Build Coastguard Worker }
295*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_madvise_dontneed, "AT_MULTI_PAGE_SIZES");
296*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_madvise_pageout(benchmark::State & state)297*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_madvise_pageout(benchmark::State& state) {
298*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
299*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
300*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
301*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
302*8d67ca89SAndroid Build Coastguard Worker };
303*8d67ca89SAndroid Build Coastguard Worker MadviseBenchmark(state, params, MADV_PAGEOUT);
304*8d67ca89SAndroid Build Coastguard Worker }
305*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_madvise_pageout, "AT_MULTI_PAGE_SIZES");
306*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_madvise_free(benchmark::State & state)307*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_madvise_free(benchmark::State& state) {
308*8d67ca89SAndroid Build Coastguard Worker struct MmapParams params = {
309*8d67ca89SAndroid Build Coastguard Worker .prot = PROT_READ | PROT_WRITE,
310*8d67ca89SAndroid Build Coastguard Worker .flags = MAP_PRIVATE | MAP_ANONYMOUS,
311*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
312*8d67ca89SAndroid Build Coastguard Worker };
313*8d67ca89SAndroid Build Coastguard Worker MadviseBenchmark(state, params, MADV_FREE);
314*8d67ca89SAndroid Build Coastguard Worker }
315*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_madvise_free, "AT_MULTI_PAGE_SIZES");
316*8d67ca89SAndroid Build Coastguard Worker
MprotectBenchmark(benchmark::State & state,const struct MprotectParams & params,void * addr)317*8d67ca89SAndroid Build Coastguard Worker void MprotectBenchmark(benchmark::State& state, const struct MprotectParams& params, void* addr) {
318*8d67ca89SAndroid Build Coastguard Worker for (auto _ : state) {
319*8d67ca89SAndroid Build Coastguard Worker state.PauseTiming();
320*8d67ca89SAndroid Build Coastguard Worker /*
321*8d67ca89SAndroid Build Coastguard Worker * Guarantee that physical memory pages are allocated for this region to prevent
322*8d67ca89SAndroid Build Coastguard Worker * segmentation fault when using mprotect to change permissions.
323*8d67ca89SAndroid Build Coastguard Worker */
324*8d67ca89SAndroid Build Coastguard Worker if (params.initial_prot & PROT_WRITE) {
325*8d67ca89SAndroid Build Coastguard Worker MakeAllocationResident(addr, params.size, page_sz);
326*8d67ca89SAndroid Build Coastguard Worker }
327*8d67ca89SAndroid Build Coastguard Worker state.ResumeTiming();
328*8d67ca89SAndroid Build Coastguard Worker
329*8d67ca89SAndroid Build Coastguard Worker if (mprotect(addr, params.size, params.mprotect_prot) != 0) {
330*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("mprotect failed: %m"));
331*8d67ca89SAndroid Build Coastguard Worker break;
332*8d67ca89SAndroid Build Coastguard Worker }
333*8d67ca89SAndroid Build Coastguard Worker
334*8d67ca89SAndroid Build Coastguard Worker state.PauseTiming();
335*8d67ca89SAndroid Build Coastguard Worker // Revert back to the original protection
336*8d67ca89SAndroid Build Coastguard Worker int res = mprotect(addr, params.size, params.initial_prot);
337*8d67ca89SAndroid Build Coastguard Worker state.ResumeTiming();
338*8d67ca89SAndroid Build Coastguard Worker if (res != 0) {
339*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(
340*8d67ca89SAndroid Build Coastguard Worker android::base::StringPrintf("mprotect failed to revert to original prot: %m"));
341*8d67ca89SAndroid Build Coastguard Worker break;
342*8d67ca89SAndroid Build Coastguard Worker }
343*8d67ca89SAndroid Build Coastguard Worker }
344*8d67ca89SAndroid Build Coastguard Worker }
345*8d67ca89SAndroid Build Coastguard Worker
MprotectBenchmarkWithMmapAnon(benchmark::State & state,const struct MprotectParams & params)346*8d67ca89SAndroid Build Coastguard Worker static void MprotectBenchmarkWithMmapAnon(benchmark::State& state,
347*8d67ca89SAndroid Build Coastguard Worker const struct MprotectParams& params) {
348*8d67ca89SAndroid Build Coastguard Worker void* addr = mmap(nullptr, params.size, params.initial_prot, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
349*8d67ca89SAndroid Build Coastguard Worker if (addr == MAP_FAILED) {
350*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("mmap failed: %m"));
351*8d67ca89SAndroid Build Coastguard Worker return;
352*8d67ca89SAndroid Build Coastguard Worker }
353*8d67ca89SAndroid Build Coastguard Worker
354*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmark(state, params, addr);
355*8d67ca89SAndroid Build Coastguard Worker
356*8d67ca89SAndroid Build Coastguard Worker if (munmap(addr, params.size) != 0)
357*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("munmap failed: %m"));
358*8d67ca89SAndroid Build Coastguard Worker }
359*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_mprotect_rw_to_rd(benchmark::State & state)360*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_mprotect_rw_to_rd(benchmark::State& state) {
361*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
362*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_READ | PROT_WRITE,
363*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_READ,
364*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
365*8d67ca89SAndroid Build Coastguard Worker };
366*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapAnon(state, params);
367*8d67ca89SAndroid Build Coastguard Worker }
368*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_mprotect_rw_to_rd, "AT_ALL_PAGE_SIZES");
369*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_mprotect_rw_to_none(benchmark::State & state)370*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_mprotect_rw_to_none(benchmark::State& state) {
371*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
372*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_READ | PROT_WRITE,
373*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_NONE,
374*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
375*8d67ca89SAndroid Build Coastguard Worker };
376*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapAnon(state, params);
377*8d67ca89SAndroid Build Coastguard Worker }
378*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_mprotect_rw_to_none, "AT_ALL_PAGE_SIZES");
379*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_anon_mprotect_rd_to_none(benchmark::State & state)380*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_anon_mprotect_rd_to_none(benchmark::State& state) {
381*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
382*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_READ,
383*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_NONE,
384*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
385*8d67ca89SAndroid Build Coastguard Worker };
386*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapAnon(state, params);
387*8d67ca89SAndroid Build Coastguard Worker }
388*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_anon_mprotect_rd_to_none, "AT_ALL_PAGE_SIZES");
389*8d67ca89SAndroid Build Coastguard Worker
MprotectBenchmarkWithMmapFile(benchmark::State & state,const struct MprotectParams & params)390*8d67ca89SAndroid Build Coastguard Worker static void MprotectBenchmarkWithMmapFile(benchmark::State& state,
391*8d67ca89SAndroid Build Coastguard Worker const struct MprotectParams& params) {
392*8d67ca89SAndroid Build Coastguard Worker TemporaryFile tf;
393*8d67ca89SAndroid Build Coastguard Worker
394*8d67ca89SAndroid Build Coastguard Worker if (tf.fd < 0) {
395*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("failed to create a temporary file: %m"));
396*8d67ca89SAndroid Build Coastguard Worker return;
397*8d67ca89SAndroid Build Coastguard Worker }
398*8d67ca89SAndroid Build Coastguard Worker
399*8d67ca89SAndroid Build Coastguard Worker if (params.size > 0 && ftruncate(tf.fd, params.size)) {
400*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("ftruncate failed: %m"));
401*8d67ca89SAndroid Build Coastguard Worker return;
402*8d67ca89SAndroid Build Coastguard Worker }
403*8d67ca89SAndroid Build Coastguard Worker
404*8d67ca89SAndroid Build Coastguard Worker void* addr = mmap(nullptr, params.size, params.initial_prot, MAP_PRIVATE, tf.fd, 0);
405*8d67ca89SAndroid Build Coastguard Worker if (addr == MAP_FAILED) {
406*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("mmap failed: %m"));
407*8d67ca89SAndroid Build Coastguard Worker return;
408*8d67ca89SAndroid Build Coastguard Worker }
409*8d67ca89SAndroid Build Coastguard Worker
410*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmark(state, params, addr);
411*8d67ca89SAndroid Build Coastguard Worker
412*8d67ca89SAndroid Build Coastguard Worker if (munmap(addr, params.size) != 0)
413*8d67ca89SAndroid Build Coastguard Worker state.SkipWithError(android::base::StringPrintf("munmap failed: %m"));
414*8d67ca89SAndroid Build Coastguard Worker }
415*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_mprotect_rw_to_rd(benchmark::State & state)416*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_mprotect_rw_to_rd(benchmark::State& state) {
417*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
418*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_READ | PROT_WRITE,
419*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_READ,
420*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
421*8d67ca89SAndroid Build Coastguard Worker };
422*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapFile(state, params);
423*8d67ca89SAndroid Build Coastguard Worker }
424*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_mprotect_rw_to_rd, "AT_ALL_PAGE_SIZES");
425*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_mprotect_rw_to_none(benchmark::State & state)426*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_mprotect_rw_to_none(benchmark::State& state) {
427*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
428*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_READ | PROT_WRITE,
429*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_NONE,
430*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
431*8d67ca89SAndroid Build Coastguard Worker };
432*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapFile(state, params);
433*8d67ca89SAndroid Build Coastguard Worker }
434*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_mprotect_rw_to_none, "AT_ALL_PAGE_SIZES");
435*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_mprotect_none_to_rw(benchmark::State & state)436*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_mprotect_none_to_rw(benchmark::State& state) {
437*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
438*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_NONE,
439*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_READ | PROT_WRITE,
440*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
441*8d67ca89SAndroid Build Coastguard Worker };
442*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapFile(state, params);
443*8d67ca89SAndroid Build Coastguard Worker }
444*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_mprotect_none_to_rw, "AT_ALL_PAGE_SIZES");
445*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_mprotect_none_to_rd(benchmark::State & state)446*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_mprotect_none_to_rd(benchmark::State& state) {
447*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
448*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_NONE,
449*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_READ,
450*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
451*8d67ca89SAndroid Build Coastguard Worker };
452*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapFile(state, params);
453*8d67ca89SAndroid Build Coastguard Worker }
454*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_mprotect_none_to_rd, "AT_ALL_PAGE_SIZES");
455*8d67ca89SAndroid Build Coastguard Worker
BM_syscall_mmap_file_mprotect_rd_to_none(benchmark::State & state)456*8d67ca89SAndroid Build Coastguard Worker static void BM_syscall_mmap_file_mprotect_rd_to_none(benchmark::State& state) {
457*8d67ca89SAndroid Build Coastguard Worker struct MprotectParams params = {
458*8d67ca89SAndroid Build Coastguard Worker .initial_prot = PROT_READ,
459*8d67ca89SAndroid Build Coastguard Worker .mprotect_prot = PROT_NONE,
460*8d67ca89SAndroid Build Coastguard Worker .size = state.range(0),
461*8d67ca89SAndroid Build Coastguard Worker };
462*8d67ca89SAndroid Build Coastguard Worker MprotectBenchmarkWithMmapFile(state, params);
463*8d67ca89SAndroid Build Coastguard Worker }
464*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_syscall_mmap_file_mprotect_rd_to_none, "AT_ALL_PAGE_SIZES");
465