1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include <benchmark/benchmark.h>
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <securec.h>
19800b99b8Sopenharmony_ci#include <string>
20800b99b8Sopenharmony_ci#include <vector>
21800b99b8Sopenharmony_ci#include <unistd.h>
22800b99b8Sopenharmony_ci#include "dfx_define.h"
23800b99b8Sopenharmony_ci#include "dfx_log.h"
24800b99b8Sopenharmony_ci#include <libunwind.h>
25800b99b8Sopenharmony_ci#include "dfx_test_util.h"
26800b99b8Sopenharmony_ci
27800b99b8Sopenharmony_ciusing namespace OHOS::HiviewDFX;
28800b99b8Sopenharmony_ciusing namespace std;
29800b99b8Sopenharmony_ci
30800b99b8Sopenharmony_cistatic constexpr size_t TEST_MIN_UNWIND_FRAMES = 5;
31800b99b8Sopenharmony_ci
32800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc5(size_t (*func)(void))
33800b99b8Sopenharmony_ci{
34800b99b8Sopenharmony_ci    return func();
35800b99b8Sopenharmony_ci}
36800b99b8Sopenharmony_ci
37800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc4(size_t (*func)(void))
38800b99b8Sopenharmony_ci{
39800b99b8Sopenharmony_ci    return TestFunc5(func);
40800b99b8Sopenharmony_ci}
41800b99b8Sopenharmony_ci
42800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc3(size_t (*func)(void))
43800b99b8Sopenharmony_ci{
44800b99b8Sopenharmony_ci    return TestFunc4(func);
45800b99b8Sopenharmony_ci}
46800b99b8Sopenharmony_ci
47800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc2(size_t (*func)(void))
48800b99b8Sopenharmony_ci{
49800b99b8Sopenharmony_ci    return TestFunc3(func);
50800b99b8Sopenharmony_ci}
51800b99b8Sopenharmony_ci
52800b99b8Sopenharmony_ciNOINLINE static size_t TestFunc1(size_t (*func)(void))
53800b99b8Sopenharmony_ci{
54800b99b8Sopenharmony_ci    return TestFunc2(func);
55800b99b8Sopenharmony_ci}
56800b99b8Sopenharmony_ci
57800b99b8Sopenharmony_cistatic size_t UnwindLocal()
58800b99b8Sopenharmony_ci{
59800b99b8Sopenharmony_ci    unw_context_t context;
60800b99b8Sopenharmony_ci    (void)memset_s(&context, sizeof(unw_context_t), 0, sizeof(unw_context_t));
61800b99b8Sopenharmony_ci    unw_getcontext(&context);
62800b99b8Sopenharmony_ci
63800b99b8Sopenharmony_ci    unw_cursor_t cursor;
64800b99b8Sopenharmony_ci    unw_init_local(&cursor, &context);
65800b99b8Sopenharmony_ci
66800b99b8Sopenharmony_ci    std::vector<unw_word_t> pcs;
67800b99b8Sopenharmony_ci    size_t index = 0;
68800b99b8Sopenharmony_ci    unw_word_t pc = 0;
69800b99b8Sopenharmony_ci    unw_word_t prevPc = 0;
70800b99b8Sopenharmony_ci    do {
71800b99b8Sopenharmony_ci        if ((unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t*)(&(pc)))) || (prevPc == pc)) {
72800b99b8Sopenharmony_ci            break;
73800b99b8Sopenharmony_ci        }
74800b99b8Sopenharmony_ci        pcs.emplace_back(pc);
75800b99b8Sopenharmony_ci        prevPc = pc;
76800b99b8Sopenharmony_ci        index++;
77800b99b8Sopenharmony_ci    } while (unw_step(&cursor) > 0);
78800b99b8Sopenharmony_ci    DFXLOGU("%{public}s pcs.size: %{public}zu", __func__, pcs.size());
79800b99b8Sopenharmony_ci    return pcs.size();
80800b99b8Sopenharmony_ci}
81800b99b8Sopenharmony_ci
82800b99b8Sopenharmony_cistatic void Run(benchmark::State& state, size_t (*func)(void))
83800b99b8Sopenharmony_ci{
84800b99b8Sopenharmony_ci    DFXLOGU("++++++pid: %{public}d", getpid());
85800b99b8Sopenharmony_ci    for (const auto& _ : state) {
86800b99b8Sopenharmony_ci        if (TestFunc1(func) < TEST_MIN_UNWIND_FRAMES) {
87800b99b8Sopenharmony_ci            state.SkipWithError("Failed to unwind.");
88800b99b8Sopenharmony_ci        }
89800b99b8Sopenharmony_ci    }
90800b99b8Sopenharmony_ci    DFXLOGU("------pid: %{public}d", getpid());
91800b99b8Sopenharmony_ci}
92800b99b8Sopenharmony_ci
93800b99b8Sopenharmony_ci/**
94800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwindLocal
95800b99b8Sopenharmony_ci* @tc.desc: Unwind local
96800b99b8Sopenharmony_ci* @tc.type: FUNC
97800b99b8Sopenharmony_ci*/
98800b99b8Sopenharmony_cistatic void BenchmarkUnwindLocal(benchmark::State& state)
99800b99b8Sopenharmony_ci{
100800b99b8Sopenharmony_ci    Run(state, UnwindLocal);
101800b99b8Sopenharmony_ci}
102800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwindLocal);
103800b99b8Sopenharmony_ci
104800b99b8Sopenharmony_ci/**
105800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwindLocalCache
106800b99b8Sopenharmony_ci* @tc.desc: Unwind local cache
107800b99b8Sopenharmony_ci* @tc.type: FUNC
108800b99b8Sopenharmony_ci*/
109800b99b8Sopenharmony_cistatic void BenchmarkUnwindLocalCache(benchmark::State& state)
110800b99b8Sopenharmony_ci{
111800b99b8Sopenharmony_ci    Run(state, UnwindLocal);
112800b99b8Sopenharmony_ci}
113800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwindLocalCache);
114