1 // Copyright (C) 2014 The Android Open Source Project
2 //
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 #include "aemu/base/threads/AndroidThread.h"
16
17 #include "aemu/base/threads/AndroidThreadStore.h"
18
19 #include <log/log.h>
20 #include <assert.h>
21 #include <errno.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #ifndef _MSC_VER
25 #include <unistd.h>
26 #endif
27 #ifdef __linux__
28 #include <sys/syscall.h>
29 #include <sys/types.h>
30 #endif
31
32 #ifdef __Fuchsia__
33 #include <zircon/process.h>
34 #endif
35
36 namespace android {
37 namespace base {
38 namespace guest {
39
Thread(ThreadFlags flags,int stackSize)40 Thread::Thread(ThreadFlags flags, int stackSize)
41 : mThread((pthread_t)NULL), mStackSize(stackSize), mFlags(flags) {}
42
~Thread()43 Thread::~Thread() {
44 assert(!mStarted || mFinished);
45 if ((mFlags & ThreadFlags::Detach) == ThreadFlags::NoFlags && mStarted &&
46 !mJoined) {
47 // Make sure we reclaim the OS resources.
48 pthread_join(mThread, nullptr);
49 }
50 }
51
start()52 bool Thread::start() {
53 if (mStarted) {
54 return false;
55 }
56
57 bool ret = true;
58 mStarted = true;
59
60 const auto useAttributes = mStackSize != 0;
61
62 pthread_attr_t attr;
63 if (useAttributes) {
64 pthread_attr_init(&attr);
65 pthread_attr_setstacksize(&attr, mStackSize);
66 }
67
68 if (pthread_create(&mThread, mStackSize ? &attr : nullptr, thread_main,
69 this)) {
70 ALOGE("Thread: failed to create a thread, errno %d\n", errno);
71 ret = false;
72 // We _do not_ need to guard this access to |mFinished| because we're
73 // sure that the launched thread failed, so there can't be parallel
74 // access.
75 mFinished = true;
76 mExitStatus = -errno;
77 // Nothing to join, so technically it's joined.
78 mJoined = true;
79 }
80
81 if (useAttributes) {
82 pthread_attr_destroy(&attr);
83 }
84
85 return ret;
86 }
87
wait(intptr_t * exitStatus)88 bool Thread::wait(intptr_t* exitStatus) {
89 if (!mStarted || (mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
90 return false;
91 }
92
93 // NOTE: Do not hold the lock when waiting for the thread to ensure
94 // it can update mFinished and mExitStatus properly in thread_main
95 // without blocking.
96 if (!mJoined && pthread_join(mThread, NULL)) {
97 return false;
98 }
99 mJoined = true;
100
101 if (exitStatus) {
102 *exitStatus = mExitStatus;
103 }
104 return true;
105 }
106
tryWait(intptr_t * exitStatus)107 bool Thread::tryWait(intptr_t* exitStatus) {
108 if (!mStarted || (mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
109 return false;
110 }
111
112 {
113 AutoLock<Lock> locker(mLock);
114 if (!mFinished) {
115 return false;
116 }
117 }
118
119 if (!mJoined) {
120 if (pthread_join(mThread, NULL)) {
121 ALOGW("Thread: failed to join a finished thread, errno %d\n", errno);
122 }
123 mJoined = true;
124 }
125
126 if (exitStatus) {
127 *exitStatus = mExitStatus;
128 }
129 return true;
130 }
131
132 // static
thread_main(void * arg)133 void* Thread::thread_main(void* arg) {
134 intptr_t ret;
135
136 {
137 Thread* self = reinterpret_cast<Thread*>(arg);
138 if ((self->mFlags & ThreadFlags::MaskSignals) != ThreadFlags::NoFlags) {
139 Thread::maskAllSignals();
140 }
141
142 if ((self->mFlags & ThreadFlags::Detach) != ThreadFlags::NoFlags) {
143 if (pthread_detach(pthread_self())) {
144 // This only means a slow memory leak, so use VERBOSE.
145 ALOGV("Failed to set thread to detach mode\n");
146 }
147 }
148
149 ret = self->main();
150
151 {
152 AutoLock<Lock> lock(self->mLock);
153 self->mFinished = true;
154 self->mExitStatus = ret;
155 }
156
157 self->onExit();
158 // |self| is not valid beyond this point
159 }
160
161 ::android::base::guest::ThreadStoreBase::OnThreadExit();
162
163 // This return value is ignored.
164 return NULL;
165 }
166
167 // static
maskAllSignals()168 void Thread::maskAllSignals() {
169 sigset_t set;
170 sigfillset(&set);
171 pthread_sigmask(SIG_SETMASK, &set, nullptr);
172 }
173
174 // static
sleepMs(unsigned n)175 void Thread::sleepMs(unsigned n) {
176 usleep(n * 1000);
177 }
178
179 // static
sleepUs(unsigned n)180 void Thread::sleepUs(unsigned n) {
181 usleep(n);
182 }
183
184 // static
yield()185 void Thread::yield() {
186 sched_yield();
187 }
188
getCurrentThreadId()189 unsigned long getCurrentThreadId() {
190 #ifdef __ANDROID__
191 // bionic has an efficient implementation for gettid.
192 pid_t tid = gettid();
193 #elif defined(__linux__)
194 // Linux doesn't always include an implementation of gettid, so we use syscall.
195 thread_local pid_t tid = -1;
196 if (tid == -1) {
197 tid = syscall(__NR_gettid);
198 }
199 #elif defined(__Fuchsia__)
200 zx_handle_t tid = zx_thread_self();
201 #else
202 pthread_t thread = pthread_self();
203 // POSIX doesn't require pthread_t to be a numeric type.
204 // Instead, just pick up the first sizeof(long) bytes as the "id".
205 static_assert(sizeof(thread) >= sizeof(long),
206 "Expected pthread_t to be at least sizeof(long) wide");
207 unsigned long tid = *reinterpret_cast<unsigned long*>(&tid);
208 #endif
209 static_assert(sizeof(tid) <= sizeof(long),
210 "Expected thread handle to be at most sizeof(long) wide");
211 return static_cast<unsigned long>(tid);
212 }
213
214 } // namespace guest
215 } // namespace base
216 } // namespace android
217