• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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