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