• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 PANDA_LIBPANDABASE_OS_THREAD_H_
17 #define PANDA_LIBPANDABASE_OS_THREAD_H_
18 
19 #include "os/error.h"
20 #include "utils/expected.h"
21 
22 #include <cstdint>
23 #include <memory>
24 #include <thread>
25 #include <pthread.h>
26 #ifdef PANDA_TARGET_UNIX
27 #include "platforms/unix/libpandabase/thread.h"
28 #elif defined PANDA_TARGET_WINDOWS
29 #include "platforms/windows/libpandabase/thread.h"
30 #else
31 #error "Unsupported platform"
32 #endif
33 
34 namespace ark::os::thread {
35 
36 using ThreadId = uint32_t;
37 using NativeHandleType = std::thread::native_handle_type;
38 
39 WEAK_FOR_LTO_START
40 
41 PANDA_PUBLIC_API ThreadId GetCurrentThreadId();
42 PANDA_PUBLIC_API int GetPid();
43 PANDA_PUBLIC_API int GetPPid();
44 PANDA_PUBLIC_API int GetUid();
45 PANDA_PUBLIC_API int GetEuid();
46 PANDA_PUBLIC_API uint32_t GetGid();
47 PANDA_PUBLIC_API uint32_t GetEgid();
48 PANDA_PUBLIC_API std::vector<uint32_t> GetGroups();
49 PANDA_PUBLIC_API int SetThreadName(NativeHandleType pthreadHandle, const char *name);
50 PANDA_PUBLIC_API NativeHandleType GetNativeHandle();
51 PANDA_PUBLIC_API void Yield();
52 PANDA_PUBLIC_API void NativeSleep(unsigned int ms);
53 PANDA_PUBLIC_API void NativeSleepUS(std::chrono::microseconds us);
54 PANDA_PUBLIC_API void ThreadDetach(NativeHandleType pthreadHandle);
55 PANDA_PUBLIC_API void ThreadExit(void *ret);
56 PANDA_PUBLIC_API void ThreadJoin(NativeHandleType pthreadHandle, void **ret);
57 PANDA_PUBLIC_API void ThreadSendSignal(NativeHandleType pthreadHandle, int sig);
58 
59 WEAK_FOR_LTO_END
60 
61 // Templated functions need to be defined here to be accessible everywhere
62 
63 namespace internal {
64 
65 template <typename T>
66 struct SharedPtrStruct;
67 
68 template <typename T>
69 using SharedPtrToSharedPtrStruct = std::shared_ptr<SharedPtrStruct<T>>;
70 
71 template <typename T>
72 struct SharedPtrStruct {
73     SharedPtrToSharedPtrStruct<T> thisPtr;  // NOLINT(misc-non-private-member-variables-in-classes)
74     T data;                                 // NOLINT(misc-non-private-member-variables-in-classes)
SharedPtrStructSharedPtrStruct75     SharedPtrStruct(SharedPtrToSharedPtrStruct<T> ptrIn, T dataIn) : thisPtr(std::move(ptrIn)), data(std::move(dataIn))
76     {
77     }
78 };
79 
80 template <size_t... IS>
81 struct Seq {
82 };
83 
84 template <size_t N, size_t... IS>
85 struct GenArgSeq : GenArgSeq<N - 1, N - 1, IS...> {
86 };
87 
88 template <size_t... IS>
89 struct GenArgSeq<1, IS...> : Seq<IS...> {
90 };
91 
92 template <class Func, typename Tuple, size_t... I>
93 static void CallFunc(Func &func, Tuple &args, Seq<I...> /* unused */)
94 {
95     func(std::get<I>(args)...);
96 }
97 
98 template <class Func, typename Tuple, size_t N>
99 static void CallFunc(Func &func, Tuple &args)
100 {
101     CallFunc(func, args, GenArgSeq<N>());
102 }
103 
104 template <typename Func, typename Tuple, size_t N>
105 static void *ProxyFunc(void *args)
106 {
107     // Parse pointer and move args to local tuple.
108     // We need this pointer to be destroyed by the time function starts to avoid memleak on thread  termination
109     Tuple argsTuple;
110     {
111         auto argsPtr = static_cast<SharedPtrStruct<Tuple> *>(args);
112         SharedPtrToSharedPtrStruct<Tuple> local;
113         // This breaks shared pointer loop
114         local.swap(argsPtr->thisPtr);
115         // This moves tuple data to local variable
116         argsTuple = argsPtr->data;
117     }
118     Func *func = std::get<0>(argsTuple);
119     CallFunc<Func, Tuple, N>(*func, argsTuple);
120     return nullptr;
121 }
122 
123 }  // namespace internal
124 
125 template <typename Func, typename... Args>
126 NativeHandleType ThreadStart(Func *func, Args... args)
127 {
128 #ifdef PANDA_TARGET_UNIX
129     NativeHandleType tid;
130 #else
131     pthread_t tid;
132 #endif
133     auto argsTuple = std::make_tuple(func, std::move(args)...);
134     internal::SharedPtrStruct<decltype(argsTuple)> *ptr = nullptr;
135     {
136         auto sharedPtr = std::make_shared<internal::SharedPtrStruct<decltype(argsTuple)>>(nullptr, argsTuple);
137         ptr = sharedPtr.get();
138         // Make recursive ref to prevent from shared pointer being destroyed until child thread acquires it.
139         ptr->thisPtr = sharedPtr;
140         // Leave scope to make sure that local shared_ptr was destroyed before thread creation
141     }
142     pthread_create(&tid, nullptr,
143                    &internal::ProxyFunc<Func, decltype(argsTuple), std::tuple_size<decltype(argsTuple)>::value>,
144                    static_cast<void *>(ptr));
145 #ifdef PANDA_TARGET_UNIX
146     return tid;
147 #else
148     return reinterpret_cast<NativeHandleType>(tid);
149 #endif
150 }
151 
152 WEAK_FOR_LTO_START
153 PANDA_PUBLIC_API int ThreadGetStackInfo(NativeHandleType thread, void **stackAddr, size_t *stackSize,
154                                         size_t *guardSize);
155 WEAK_FOR_LTO_END
156 
157 inline bool IsSetPriorityError(int res)
158 {
159 #ifdef PANDA_TARGET_UNIX
160     return res != 0;
161 #elif defined(PANDA_TARGET_WINDOWS)
162     return res == 0;
163 #endif
164 }
165 }  // namespace ark::os::thread
166 
167 #endif  // PANDA_LIBPANDABASE_OS_THREAD_H_
168