1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef RELIABILITY_THREAD_SAMPLER_H 17 #define RELIABILITY_THREAD_SAMPLER_H 18 19 #include <atomic> 20 #include <condition_variable> 21 #include <memory> 22 #include <string> 23 24 #include <sys/mman.h> 25 26 #include "singleton.h" 27 28 #include "unwinder.h" 29 #include "unique_stack_table.h" 30 #include "dfx_accessors.h" 31 #include "dfx_maps.h" 32 #include "unwind_context.h" 33 34 namespace OHOS { 35 namespace HiviewDFX { 36 constexpr int STACK_BUFFER_SIZE = 16 * 1024; 37 constexpr uint32_t DEFAULT_UNIQUE_STACK_TABLE_SIZE = 128 * 1024; 38 39 struct ThreadUnwindContext { 40 uintptr_t pc {0}; 41 uintptr_t sp {0}; 42 uintptr_t fp {0}; 43 uintptr_t lr {0}; 44 uint64_t requestTime {0}; // begin sample 45 uint64_t snapshotTime {0}; // end of stack copy in signal handler 46 uint64_t processTime {0}; // end of unwind and unique stack 47 uint8_t buffer[STACK_BUFFER_SIZE] {0}; // 16K stack buffer 48 }; 49 50 struct UnwindInfo { 51 ThreadUnwindContext* context; 52 DfxMaps* maps; 53 }; 54 55 struct TimeAndFrames { 56 uint64_t requestTime {0}; 57 uint64_t snapshotTime {0}; 58 std::vector<DfxFrame> frameList; 59 }; 60 61 struct StackIdAndCount { 62 uint64_t stackId {0}; 63 uint32_t count {0}; 64 }; 65 66 class ThreadSampler : public Singleton<ThreadSampler> { 67 DECLARE_SINGLETON(ThreadSampler); 68 public: 69 static const int32_t SAMPLER_MAX_BUFFER_SZ = 2; 70 static void ThreadSamplerSignalHandler(int sig, siginfo_t* si, void* context); 71 72 // Initial sampler, include uwinder, recorde buffer etc. 73 bool Init(int collectStackCount); 74 int32_t Sample(); // Interface of sample, to send sample request. 75 // Collect stack info, can be formed into tree format or not. Unsafe in multi-thread environments 76 bool CollectStack(std::string& stack, bool treeFormat = true); 77 void Deinit(); // Release sampler 78 79 private: 80 bool InitRecordBuffer(); 81 void ReleaseRecordBuffer(); 82 bool InitUnwinder(); 83 void DestroyUnwinder(); 84 bool InitUniqueStackTable(); 85 void DeinitUniqueStackTable(); 86 bool InstallSignalHandler(); 87 void UninstallSignalHandler(); 88 void SendSampleRequest(); 89 void ProcessStackBuffer(); 90 int AccessElfMem(uintptr_t addr, uintptr_t *val); 91 92 static int FindUnwindTable(uintptr_t pc, UnwindTableInfo& outTableInfo, void *arg); 93 static int AccessMem(uintptr_t addr, uintptr_t *val, void *arg); 94 static int GetMapByPc(uintptr_t pc, std::shared_ptr<DfxMap>& map, void *arg); 95 96 ThreadUnwindContext* GetReadContext(); 97 ThreadUnwindContext* GetWriteContext(); 98 void WriteContext(void* context); 99 MAYBE_UNUSED void ResetConsumeInfo(); 100 101 bool init_ {false}; 102 uintptr_t stackBegin_ {0}; 103 uintptr_t stackEnd_ {0}; 104 int32_t pid_ {0}; 105 std::atomic<int32_t> writeIndex_ {0}; 106 std::atomic<int32_t> readIndex_ {0}; 107 void* mmapStart_ {MAP_FAILED}; 108 int32_t bufferSize_ {0}; 109 std::shared_ptr<Unwinder> unwinder_ {nullptr}; 110 std::unique_ptr<UniqueStackTable> uniqueStackTable_ {nullptr}; 111 std::shared_ptr<UnwindAccessors> accessors_ {nullptr}; 112 std::shared_ptr<DfxMaps> maps_ {nullptr}; 113 // size of the uniqueStackTableSize, default 128KB 114 uint32_t uniqueStackTableSize_ {DEFAULT_UNIQUE_STACK_TABLE_SIZE}; 115 // name of the mmap of uniqueStackTable 116 std::string uniTableMMapName_ {"hicollie_buf"}; 117 118 MAYBE_UNUSED uint64_t copyStackCount_ {0}; 119 MAYBE_UNUSED uint64_t copyStackTimeCost_ {0}; 120 MAYBE_UNUSED uint64_t unwindCount_ {0}; 121 MAYBE_UNUSED uint64_t unwindTimeCost_ {0}; 122 MAYBE_UNUSED uint64_t processTimeCost_ {0}; 123 MAYBE_UNUSED uint64_t sampleCount_ {0}; 124 MAYBE_UNUSED uint64_t requestCount_ {0}; 125 MAYBE_UNUSED uint64_t signalTimeCost_ {0}; 126 MAYBE_UNUSED uint64_t processCount_ {0}; 127 128 std::vector<TimeAndFrames> timeAndFrameList_; 129 std::vector<StackIdAndCount> stackIdCount_; 130 }; 131 } // end of namespace HiviewDFX 132 } // end of namespace OHOS 133 #endif 134