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