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