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 THREAD_CONTEXT_H
17 #define THREAD_CONTEXT_H
18 
19 #include <atomic>
20 #include <cstdint>
21 #include <condition_variable>
22 #include <csignal>
23 #include <mutex>
24 #include <nocopyable.h>
25 #include <string>
26 
27 #include "dfx_define.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 enum ThreadContextStatus : int32_t {
32     CONTEXT_UNUSED = -1,
33     CONTEXT_READY = -2,
34 };
35 
36 struct ThreadContext {
37     std::atomic<int32_t> tid {ThreadContextStatus::CONTEXT_UNUSED};
38     // for protecting ctx, shared between threads
39     std::mutex mtx;
40     // the thread should be suspended while unwinding
41     // blocked in the signal handler of target thread
42     std::condition_variable cv;
43     // store unwind context
44     ucontext_t* ctx {nullptr};
45     // stack range
46     uintptr_t stackBottom;
47     uintptr_t stackTop;
48 #if defined(__aarch64__)
49     // unwind in signal handler by fp
50     uintptr_t pcs[DEFAULT_MAX_LOCAL_FRAME_NUM] {0};
51 #endif
52     std::atomic<size_t> frameSz {0};
53     // first stack pointer
54     uintptr_t firstFrameSp;
55 
~ThreadContextThreadContext56     ~ThreadContext()
57     {
58         std::unique_lock<std::mutex> lock(mtx);
59         if (ctx != nullptr) {
60             delete ctx;
61             ctx = nullptr;
62         }
63     };
64 };
65 
66 class LocalThreadContext {
67 public:
68     static LocalThreadContext& GetInstance();
69 
70     bool GetStackRange(int32_t tid, uintptr_t& stackBottom, uintptr_t& stackTop);
71     std::shared_ptr<ThreadContext> CollectThreadContext(int32_t tid);
72     std::shared_ptr<ThreadContext> GetThreadContext(int32_t tid);
73     void ReleaseThread(int32_t tid);
74     void CleanUp();
75 
76 private:
77     LocalThreadContext() = default;
78     DISALLOW_COPY_AND_MOVE(LocalThreadContext);
79 
80     static void CopyContextAndWaitTimeout(int sig, siginfo_t *si, void *context);
81     bool SignalRequestThread(int32_t tid, ThreadContext* ctx);
82     void InitSignalHandler();
83 
84 private:
85     std::mutex localMutex_;
86 };
87 } // namespace Dfx
88 } // namespace OHOS
89 #endif
90