1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2024 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 <atomic>
17800b99b8Sopenharmony_ci#include <benchmark/benchmark.h>
18800b99b8Sopenharmony_ci#include <mutex>
19800b99b8Sopenharmony_ci#include <thread>
20800b99b8Sopenharmony_ci#include <unistd.h>
21800b99b8Sopenharmony_ci#include <vector>
22800b99b8Sopenharmony_ci#include "dfx_log.h"
23800b99b8Sopenharmony_ci#include "unwinder.h"
24800b99b8Sopenharmony_ci
25800b99b8Sopenharmony_ciusing namespace OHOS::HiviewDFX;
26800b99b8Sopenharmony_ciusing namespace std;
27800b99b8Sopenharmony_ci
28800b99b8Sopenharmony_ci#undef LOG_DOMAIN
29800b99b8Sopenharmony_ci#undef LOG_TAG
30800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
31800b99b8Sopenharmony_ci#define LOG_TAG "DfxUnwinderLocalTid"
32800b99b8Sopenharmony_ci
33800b99b8Sopenharmony_ci#define NOINLINE __attribute__((noinline))
34800b99b8Sopenharmony_cistatic constexpr size_t TEST_MIN_UNWIND_FRAMES = 5;
35800b99b8Sopenharmony_cistatic constexpr int NUM_ONE = 1;
36800b99b8Sopenharmony_cistatic constexpr int NUM_TWO = 2;
37800b99b8Sopenharmony_cistatic constexpr int NUM_THREE = 3;
38800b99b8Sopenharmony_cistatic constexpr int NUM_FOUR = 4;
39800b99b8Sopenharmony_cistatic constexpr int NUM_FIVE = 5;
40800b99b8Sopenharmony_ci
41800b99b8Sopenharmony_ciNOINLINE int TestFunc6(std::atomic_int* tid, std::atomic_bool* done)
42800b99b8Sopenharmony_ci{
43800b99b8Sopenharmony_ci    tid->store(gettid());
44800b99b8Sopenharmony_ci    while (!done->load()) {
45800b99b8Sopenharmony_ci    }
46800b99b8Sopenharmony_ci    return NUM_ONE;
47800b99b8Sopenharmony_ci}
48800b99b8Sopenharmony_ci
49800b99b8Sopenharmony_ciNOINLINE int TestFunc5(std::atomic_int* tid, std::atomic_bool* done)
50800b99b8Sopenharmony_ci{
51800b99b8Sopenharmony_ci    int val = TestFunc6(tid, done);
52800b99b8Sopenharmony_ci    return val * val + NUM_FIVE;
53800b99b8Sopenharmony_ci}
54800b99b8Sopenharmony_ci
55800b99b8Sopenharmony_ciNOINLINE int TestFunc4(std::atomic_int* tid, std::atomic_bool* done)
56800b99b8Sopenharmony_ci{
57800b99b8Sopenharmony_ci    int val = TestFunc5(tid, done);
58800b99b8Sopenharmony_ci    return val * val + NUM_FOUR;
59800b99b8Sopenharmony_ci}
60800b99b8Sopenharmony_ci
61800b99b8Sopenharmony_ciNOINLINE int TestFunc3(std::atomic_int* tid, std::atomic_bool* done)
62800b99b8Sopenharmony_ci{
63800b99b8Sopenharmony_ci    int val = TestFunc4(tid, done);
64800b99b8Sopenharmony_ci    return val * val + NUM_THREE;
65800b99b8Sopenharmony_ci}
66800b99b8Sopenharmony_ci
67800b99b8Sopenharmony_ciNOINLINE int TestFunc2(std::atomic_int* tid, std::atomic_bool* done)
68800b99b8Sopenharmony_ci{
69800b99b8Sopenharmony_ci    int val = TestFunc3(tid, done);
70800b99b8Sopenharmony_ci    return val * val + NUM_TWO;
71800b99b8Sopenharmony_ci}
72800b99b8Sopenharmony_ci
73800b99b8Sopenharmony_ciNOINLINE int TestFunc1(std::atomic_int* tid, std::atomic_bool* done)
74800b99b8Sopenharmony_ci{
75800b99b8Sopenharmony_ci    int val = TestFunc2(tid, done);
76800b99b8Sopenharmony_ci    return val * val + NUM_ONE;
77800b99b8Sopenharmony_ci}
78800b99b8Sopenharmony_ci
79800b99b8Sopenharmony_ci/**
80800b99b8Sopenharmony_ci* @tc.name: BenchmarkUnwinderLocalWithTid
81800b99b8Sopenharmony_ci* @tc.desc: Unwind local with tid
82800b99b8Sopenharmony_ci* @tc.type: FUNC
83800b99b8Sopenharmony_ci*/
84800b99b8Sopenharmony_cistatic void BenchmarkUnwinderLocalWithTid(benchmark::State& state)
85800b99b8Sopenharmony_ci{
86800b99b8Sopenharmony_ci    static std::mutex mutex;
87800b99b8Sopenharmony_ci    constexpr int waitThreadTime = 1000;
88800b99b8Sopenharmony_ci    std::atomic_int tid(0);
89800b99b8Sopenharmony_ci    std::atomic_bool done(false);
90800b99b8Sopenharmony_ci    std::thread th([&tid, &done] { TestFunc1(&tid, &done); });
91800b99b8Sopenharmony_ci    while (tid.load() == 0) {
92800b99b8Sopenharmony_ci        usleep(waitThreadTime);
93800b99b8Sopenharmony_ci        DFXLOGU("wait thread");
94800b99b8Sopenharmony_ci    }
95800b99b8Sopenharmony_ci    DFXLOGU("+++tid: %{public}d", tid.load());
96800b99b8Sopenharmony_ci#if defined(__aarch64__)
97800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>(false);
98800b99b8Sopenharmony_ci#else
99800b99b8Sopenharmony_ci    auto unwinder = std::make_shared<Unwinder>();
100800b99b8Sopenharmony_ci#endif
101800b99b8Sopenharmony_ci    unwinder->EnableFillFrames(false);
102800b99b8Sopenharmony_ci    for (const auto& _ : state) {
103800b99b8Sopenharmony_ci        std::unique_lock<std::mutex> lock(mutex);
104800b99b8Sopenharmony_ci        if (!unwinder->UnwindLocalWithTid(tid.load())) {
105800b99b8Sopenharmony_ci            continue;
106800b99b8Sopenharmony_ci        }
107800b99b8Sopenharmony_ci        auto unwSize = unwinder->GetPcs().size();
108800b99b8Sopenharmony_ci        //rk 64 frames size is 14, rk 32 frames size is 9
109800b99b8Sopenharmony_ci        DFXLOGU("%{public}s, frames.size: %{public}zu", __func__, unwSize);
110800b99b8Sopenharmony_ci        if (unwSize < TEST_MIN_UNWIND_FRAMES) {
111800b99b8Sopenharmony_ci            state.SkipWithError("Failed to unwind.");
112800b99b8Sopenharmony_ci        }
113800b99b8Sopenharmony_ci    }
114800b99b8Sopenharmony_ci
115800b99b8Sopenharmony_ci    done.store(true);
116800b99b8Sopenharmony_ci    DFXLOGU("---tid: %{public}d", tid.load());
117800b99b8Sopenharmony_ci    th.join();
118800b99b8Sopenharmony_ci}
119800b99b8Sopenharmony_ciBENCHMARK(BenchmarkUnwinderLocalWithTid);