1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker *
4*eb293b8fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker *
8*eb293b8fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker *
10*eb293b8fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker */
16*eb293b8fSAndroid Build Coastguard Worker
17*eb293b8fSAndroid Build Coastguard Worker #include <signal.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
19*eb293b8fSAndroid Build Coastguard Worker
20*eb293b8fSAndroid Build Coastguard Worker #include <atomic>
21*eb293b8fSAndroid Build Coastguard Worker #include <thread>
22*eb293b8fSAndroid Build Coastguard Worker
23*eb293b8fSAndroid Build Coastguard Worker #include <android-base/threads.h>
24*eb293b8fSAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
27*eb293b8fSAndroid Build Coastguard Worker
28*eb293b8fSAndroid Build Coastguard Worker constexpr size_t kMaxFrames = 32;
29*eb293b8fSAndroid Build Coastguard Worker
ThreadCall6(std::atomic_int * tid,std::atomic_bool * done)30*eb293b8fSAndroid Build Coastguard Worker void ThreadCall6(std::atomic_int* tid, std::atomic_bool* done) {
31*eb293b8fSAndroid Build Coastguard Worker tid->store(android::base::GetThreadId());
32*eb293b8fSAndroid Build Coastguard Worker
33*eb293b8fSAndroid Build Coastguard Worker while (!done->load()) {
34*eb293b8fSAndroid Build Coastguard Worker }
35*eb293b8fSAndroid Build Coastguard Worker }
36*eb293b8fSAndroid Build Coastguard Worker
ThreadCall5(std::atomic_int * tid,std::atomic_bool * done)37*eb293b8fSAndroid Build Coastguard Worker void ThreadCall5(std::atomic_int* tid, std::atomic_bool* done) {
38*eb293b8fSAndroid Build Coastguard Worker ThreadCall6(tid, done);
39*eb293b8fSAndroid Build Coastguard Worker }
40*eb293b8fSAndroid Build Coastguard Worker
ThreadCall4(std::atomic_int * tid,std::atomic_bool * done)41*eb293b8fSAndroid Build Coastguard Worker void ThreadCall4(std::atomic_int* tid, std::atomic_bool* done) {
42*eb293b8fSAndroid Build Coastguard Worker ThreadCall5(tid, done);
43*eb293b8fSAndroid Build Coastguard Worker }
44*eb293b8fSAndroid Build Coastguard Worker
ThreadCall3(std::atomic_int * tid,std::atomic_bool * done)45*eb293b8fSAndroid Build Coastguard Worker void ThreadCall3(std::atomic_int* tid, std::atomic_bool* done) {
46*eb293b8fSAndroid Build Coastguard Worker ThreadCall4(tid, done);
47*eb293b8fSAndroid Build Coastguard Worker }
48*eb293b8fSAndroid Build Coastguard Worker
ThreadCall2(std::atomic_int * tid,std::atomic_bool * done)49*eb293b8fSAndroid Build Coastguard Worker void ThreadCall2(std::atomic_int* tid, std::atomic_bool* done) {
50*eb293b8fSAndroid Build Coastguard Worker ThreadCall3(tid, done);
51*eb293b8fSAndroid Build Coastguard Worker }
52*eb293b8fSAndroid Build Coastguard Worker
ThreadCall1(std::atomic_int * tid,std::atomic_bool * done)53*eb293b8fSAndroid Build Coastguard Worker void ThreadCall1(std::atomic_int* tid, std::atomic_bool* done) {
54*eb293b8fSAndroid Build Coastguard Worker ThreadCall2(tid, done);
55*eb293b8fSAndroid Build Coastguard Worker }
56*eb293b8fSAndroid Build Coastguard Worker
BM_thread_unwind(benchmark::State & state)57*eb293b8fSAndroid Build Coastguard Worker static void BM_thread_unwind(benchmark::State& state) {
58*eb293b8fSAndroid Build Coastguard Worker std::atomic_int tid(0);
59*eb293b8fSAndroid Build Coastguard Worker std::atomic_bool done;
60*eb293b8fSAndroid Build Coastguard Worker
61*eb293b8fSAndroid Build Coastguard Worker // Create the thread before the unwinder object so all maps are no
62*eb293b8fSAndroid Build Coastguard Worker // longer changing.
63*eb293b8fSAndroid Build Coastguard Worker std::thread thread([&tid, &done] { ThreadCall1(&tid, &done); });
64*eb293b8fSAndroid Build Coastguard Worker
65*eb293b8fSAndroid Build Coastguard Worker while (tid.load() == 0) {
66*eb293b8fSAndroid Build Coastguard Worker }
67*eb293b8fSAndroid Build Coastguard Worker
68*eb293b8fSAndroid Build Coastguard Worker unwindstack::ThreadUnwinder unwinder(kMaxFrames);
69*eb293b8fSAndroid Build Coastguard Worker if (!unwinder.Init()) {
70*eb293b8fSAndroid Build Coastguard Worker state.SkipWithError("Failed to init.");
71*eb293b8fSAndroid Build Coastguard Worker }
72*eb293b8fSAndroid Build Coastguard Worker
73*eb293b8fSAndroid Build Coastguard Worker for (const auto& _ : state) {
74*eb293b8fSAndroid Build Coastguard Worker unwinder.UnwindWithSignal(SIGRTMIN, tid.load());
75*eb293b8fSAndroid Build Coastguard Worker if (unwinder.NumFrames() < 5) {
76*eb293b8fSAndroid Build Coastguard Worker state.SkipWithError("Failed to unwind.");
77*eb293b8fSAndroid Build Coastguard Worker }
78*eb293b8fSAndroid Build Coastguard Worker }
79*eb293b8fSAndroid Build Coastguard Worker
80*eb293b8fSAndroid Build Coastguard Worker done.store(true);
81*eb293b8fSAndroid Build Coastguard Worker thread.join();
82*eb293b8fSAndroid Build Coastguard Worker }
83*eb293b8fSAndroid Build Coastguard Worker BENCHMARK(BM_thread_unwind);
84