xref: /aosp_15_r20/bionic/benchmarks/syscall_mm_benchmark.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
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