• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 #include <algorithm>
17 #include <chrono>
18 #include <cstdint>
19 #include <cstdio>
20 #include "libpandabase/os/thread.h"
21 #include "libpandabase/utils/logger.h"
22 #ifdef PANDA_TARGET_OHOS
23 #include "libpandabase/os/mem.h"
24 #endif
25 #ifdef PANDA_TARGET_UNIX
26 #include <fcntl.h>
27 #include <pthread.h>
28 #include <sys/resource.h>
29 #include <sys/syscall.h>
30 #include <csignal>
31 #endif
32 #include <securec.h>
33 #include <unistd.h>
34 
35 namespace ark::os::thread {
GetCurrentThreadId()36 ThreadId GetCurrentThreadId()
37 {
38 #if defined(HAVE_GETTID)
39     static_assert(sizeof(decltype(gettid())) == sizeof(ThreadId), "Incorrect alias for ThreadID");
40     return static_cast<ThreadId>(gettid());
41 #elif defined(PANDA_TARGET_MACOS)
42     uint64_t tid64;
43     pthread_threadid_np(NULL, &tid64);
44     return static_cast<ThreadId>(tid64);
45 #else
46     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
47     return static_cast<ThreadId>(syscall(SYS_gettid));
48 #endif
49 }
50 
GetPid()51 int GetPid()
52 {
53     return getpid();
54 }
55 
GetPPid()56 int GetPPid()
57 {
58     return getppid();
59 }
60 
GetUid()61 int GetUid()
62 {
63     return getuid();
64 }
65 
GetEuid()66 int GetEuid()
67 {
68     return geteuid();
69 }
70 
GetGid()71 uint32_t GetGid()
72 {
73     return getgid();
74 }
75 
GetEgid()76 uint32_t GetEgid()
77 {
78     return getegid();
79 }
80 
GetGroups()81 std::vector<uint32_t> GetGroups()
82 {
83     int groupCount = getgroups(0, nullptr);
84     if (groupCount == -1) {
85         return {};
86     }
87 
88     std::vector<gid_t> groups(groupCount);
89     groupCount = getgroups(groupCount, groups.data());
90     if (groupCount == -1) {
91         return {};
92     }
93 
94     groups.resize(groupCount);
95 
96     gid_t egid = getegid();
97     if (std::find(groups.begin(), groups.end(), egid) == groups.end()) {
98         groups.push_back(egid);
99     }
100 
101     return groups;
102 }
103 
SetPriority(int threadId,int prio)104 int SetPriority(int threadId, int prio)
105 {
106     // The priority can be set within range [-20, 19]
107     ASSERT(prio <= 19);   // 19: the lowest priority
108     ASSERT(prio >= -20);  // -20: the highest priority
109     // The return value is 0 if the function succeeds, and -1 if it fails.
110     return setpriority(PRIO_PROCESS, threadId, prio);
111 }
112 
GetPriority(int threadId)113 int GetPriority(int threadId)
114 {
115     return getpriority(PRIO_PROCESS, threadId);
116 }
117 
SetThreadName(NativeHandleType pthreadHandle,const char * name)118 int SetThreadName(NativeHandleType pthreadHandle, const char *name)
119 {
120     ASSERT(pthreadHandle != 0);
121 #if defined(PANDA_TARGET_MACOS)
122     return pthread_setname_np(name);
123 #else
124     return pthread_setname_np(pthreadHandle, name);
125 #endif
126 }
127 
GetNativeHandle()128 NativeHandleType GetNativeHandle()
129 {
130     return pthread_self();
131 }
132 
Yield()133 void Yield()
134 {
135     std::this_thread::yield();
136 }
137 
NativeSleep(unsigned int ms)138 void NativeSleep(unsigned int ms)
139 {
140     std::this_thread::sleep_for(std::chrono::milliseconds(ms));
141 }
142 
NativeSleepUS(std::chrono::microseconds us)143 void NativeSleepUS(std::chrono::microseconds us)
144 {
145     std::this_thread::sleep_for(us);
146 }
147 
ThreadDetach(NativeHandleType pthreadHandle)148 void ThreadDetach(NativeHandleType pthreadHandle)
149 {
150     pthread_detach(pthreadHandle);
151 }
152 
ThreadJoin(NativeHandleType pthreadHandle,void ** ret)153 void ThreadJoin(NativeHandleType pthreadHandle, void **ret)
154 {
155     pthread_join(pthreadHandle, ret);
156 }
157 
ThreadSendSignal(NativeHandleType pthreadHandle,int sig)158 void ThreadSendSignal(NativeHandleType pthreadHandle, int sig)
159 {
160     LOG_IF(pthread_kill(pthreadHandle, sig) != 0, FATAL, COMMON) << "pthread_kill failed";
161 }
162 
ThreadGetStackInfo(NativeHandleType thread,void ** stackAddr,size_t * stackSize,size_t * guardSize)163 int ThreadGetStackInfo(NativeHandleType thread, void **stackAddr, size_t *stackSize, size_t *guardSize)
164 {
165     pthread_attr_t attr;
166     int s = pthread_attr_init(&attr);
167 #ifndef PANDA_TARGET_MACOS
168     s += pthread_getattr_np(thread, &attr);
169     if (s == 0) {
170         s += pthread_attr_getguardsize(&attr, guardSize);
171         s += pthread_attr_getstack(&attr, stackAddr, stackSize);
172 #if defined(PANDA_TARGET_OHOS)
173         if (getpid() == gettid()) {
174             /**
175              *  konstanting:
176              *  main thread's stack can automatically grow up to the RLIMIT_STACK by means of the OS,
177              *  but MUSL does not care about that and returns the current (already mmap-ped) stack size.
178              *  This can lead to complicated errors, so let's adjust the stack size manually.
179              */
180             struct rlimit lim;
181             s += getrlimit(RLIMIT_STACK, &lim);
182             if (s == 0) {
183                 uintptr_t stackHiAddr = ToUintPtr(*stackAddr) + *stackSize;
184                 size_t stackSizeLimit = lim.rlim_cur;
185                 // for some reason pthread interfaces subtract 1 page from size regardless of guard size
186                 uintptr_t stackLoAddr = stackHiAddr - stackSizeLimit + ark::os::mem::GetPageSize();
187                 *stackSize = stackSizeLimit;
188                 *stackAddr = ToVoidPtr(stackLoAddr);
189             }
190         }
191 #endif /* defined(PANDA_TARGET_OHOS) */
192     }
193 #else  /* PANDA_TARGET_MACOS */
194     s += pthread_attr_getguardsize(&attr, guardSize);
195     s += pthread_attr_getstack(&attr, stackAddr, stackSize);
196 #endif /* PANDA_TARGET_MACOS */
197     s += pthread_attr_destroy(&attr);
198     return s;
199 }
200 
201 }  // namespace ark::os::thread
202