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);