Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: runtime/platform/thread_android.cc

Issue 463993002: - Separate the thread implementation used in bin/ and vm/ (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "platform/globals.h"
6 #if defined(TARGET_OS_ANDROID)
7
8 #include "platform/thread.h"
9
10 #include <errno.h> // NOLINT
11 #include <sys/time.h> // NOLINT
12
13 #include "platform/assert.h"
14
15 namespace dart {
16
17 #define VALIDATE_PTHREAD_RESULT(result) \
18 if (result != 0) { \
19 const int kBufferSize = 1024; \
20 char error_message[kBufferSize]; \
21 strerror_r(result, error_message, kBufferSize); \
22 FATAL2("pthread error: %d (%s)", result, error_message); \
23 }
24
25
26 #ifdef DEBUG
27 #define RETURN_ON_PTHREAD_FAILURE(result) \
28 if (result != 0) { \
29 const int kBufferSize = 1024; \
30 char error_message[kBufferSize]; \
31 strerror_r(result, error_message, kBufferSize); \
32 fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", \
33 __FILE__, __LINE__, result, error_message); \
34 return result; \
35 }
36 #else
37 #define RETURN_ON_PTHREAD_FAILURE(result) \
38 if (result != 0) return result;
39 #endif
40
41
42 static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
43 struct timeval tv;
44 int64_t secs = micros / kMicrosecondsPerSecond;
45 int64_t remaining_micros = (micros - (secs * kMicrosecondsPerSecond));
46 int result = gettimeofday(&tv, NULL);
47 ASSERT(result == 0);
48 ts->tv_sec = tv.tv_sec + secs;
49 ts->tv_nsec = (tv.tv_usec + remaining_micros) * kNanosecondsPerMicrosecond;
50 if (ts->tv_nsec >= kNanosecondsPerSecond) {
51 ts->tv_sec += 1;
52 ts->tv_nsec -= kNanosecondsPerSecond;
53 }
54 }
55
56
57 class ThreadStartData {
58 public:
59 ThreadStartData(Thread::ThreadStartFunction function,
60 uword parameter)
61 : function_(function), parameter_(parameter) {}
62
63 Thread::ThreadStartFunction function() const { return function_; }
64 uword parameter() const { return parameter_; }
65
66 private:
67 Thread::ThreadStartFunction function_;
68 uword parameter_;
69
70 DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
71 };
72
73
74 // Dispatch to the thread start function provided by the caller. This trampoline
75 // is used to ensure that the thread is properly destroyed if the thread just
76 // exits.
77 static void* ThreadStart(void* data_ptr) {
78 ThreadStartData* data = reinterpret_cast<ThreadStartData*>(data_ptr);
79
80 Thread::ThreadStartFunction function = data->function();
81 uword parameter = data->parameter();
82 delete data;
83
84 // Call the supplied thread start function handing it its parameters.
85 function(parameter);
86
87 return NULL;
88 }
89
90
91 int Thread::Start(ThreadStartFunction function, uword parameter) {
92 pthread_attr_t attr;
93 int result = pthread_attr_init(&attr);
94 RETURN_ON_PTHREAD_FAILURE(result);
95
96 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
97 RETURN_ON_PTHREAD_FAILURE(result);
98
99 result = pthread_attr_setstacksize(&attr, Thread::GetMaxStackSize());
100 RETURN_ON_PTHREAD_FAILURE(result);
101
102 ThreadStartData* data = new ThreadStartData(function, parameter);
103
104 pthread_t tid;
105 result = pthread_create(&tid, &attr, ThreadStart, data);
106 RETURN_ON_PTHREAD_FAILURE(result);
107
108 result = pthread_attr_destroy(&attr);
109 RETURN_ON_PTHREAD_FAILURE(result);
110
111 return 0;
112 }
113
114
115 ThreadLocalKey Thread::kUnsetThreadLocalKey = static_cast<pthread_key_t>(-1);
116 ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
117
118 ThreadLocalKey Thread::CreateThreadLocal() {
119 pthread_key_t key = kUnsetThreadLocalKey;
120 int result = pthread_key_create(&key, NULL);
121 VALIDATE_PTHREAD_RESULT(result);
122 ASSERT(key != kUnsetThreadLocalKey);
123 return key;
124 }
125
126
127 void Thread::DeleteThreadLocal(ThreadLocalKey key) {
128 ASSERT(key != kUnsetThreadLocalKey);
129 int result = pthread_key_delete(key);
130 VALIDATE_PTHREAD_RESULT(result);
131 }
132
133
134 void Thread::SetThreadLocal(ThreadLocalKey key, uword value) {
135 ASSERT(key != kUnsetThreadLocalKey);
136 int result = pthread_setspecific(key, reinterpret_cast<void*>(value));
137 VALIDATE_PTHREAD_RESULT(result);
138 }
139
140
141 intptr_t Thread::GetMaxStackSize() {
142 const int kStackSize = (128 * kWordSize * KB);
143 return kStackSize;
144 }
145
146
147 ThreadId Thread::GetCurrentThreadId() {
148 return gettid();
149 }
150
151
152 bool Thread::Join(ThreadId id) {
153 return false;
154 }
155
156
157 intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
158 ASSERT(sizeof(id) == sizeof(intptr_t));
159 return static_cast<intptr_t>(id);
160 }
161
162
163 bool Thread::Compare(ThreadId a, ThreadId b) {
164 return a == b;
165 }
166
167
168 void Thread::GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage) {
169 ASSERT(thread_id == GetCurrentThreadId());
170 ASSERT(cpu_usage != NULL);
171 struct timespec ts;
172 int r = clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts);
173 ASSERT(r == 0);
174 *cpu_usage = (ts.tv_sec * kNanosecondsPerSecond + ts.tv_nsec) /
175 kNanosecondsPerMicrosecond;
176 }
177
178
179 Mutex::Mutex() {
180 pthread_mutexattr_t attr;
181 int result = pthread_mutexattr_init(&attr);
182 VALIDATE_PTHREAD_RESULT(result);
183
184 #if defined(DEBUG)
185 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
186 VALIDATE_PTHREAD_RESULT(result);
187 #endif // defined(DEBUG)
188
189 result = pthread_mutex_init(data_.mutex(), &attr);
190 // Verify that creating a pthread_mutex succeeded.
191 VALIDATE_PTHREAD_RESULT(result);
192
193 result = pthread_mutexattr_destroy(&attr);
194 VALIDATE_PTHREAD_RESULT(result);
195 }
196
197
198 Mutex::~Mutex() {
199 int result = pthread_mutex_destroy(data_.mutex());
200 // Verify that the pthread_mutex was destroyed.
201 VALIDATE_PTHREAD_RESULT(result);
202 }
203
204
205 void Mutex::Lock() {
206 int result = pthread_mutex_lock(data_.mutex());
207 // Specifically check for dead lock to help debugging.
208 ASSERT(result != EDEADLK);
209 ASSERT(result == 0); // Verify no other errors.
210 // TODO(iposva): Do we need to track lock owners?
211 }
212
213
214 bool Mutex::TryLock() {
215 int result = pthread_mutex_trylock(data_.mutex());
216 // Return false if the lock is busy and locking failed.
217 if (result == EBUSY) {
218 return false;
219 }
220 ASSERT(result == 0); // Verify no other errors.
221 // TODO(iposva): Do we need to track lock owners?
222 return true;
223 }
224
225
226 void Mutex::Unlock() {
227 // TODO(iposva): Do we need to track lock owners?
228 int result = pthread_mutex_unlock(data_.mutex());
229 // Specifically check for wrong thread unlocking to aid debugging.
230 ASSERT(result != EPERM);
231 ASSERT(result == 0); // Verify no other errors.
232 }
233
234
235 Monitor::Monitor() {
236 pthread_mutexattr_t mutex_attr;
237 int result = pthread_mutexattr_init(&mutex_attr);
238 VALIDATE_PTHREAD_RESULT(result);
239
240 #if defined(DEBUG)
241 result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
242 VALIDATE_PTHREAD_RESULT(result);
243 #endif // defined(DEBUG)
244
245 result = pthread_mutex_init(data_.mutex(), &mutex_attr);
246 VALIDATE_PTHREAD_RESULT(result);
247
248 result = pthread_mutexattr_destroy(&mutex_attr);
249 VALIDATE_PTHREAD_RESULT(result);
250
251 pthread_condattr_t cond_attr;
252 result = pthread_condattr_init(&cond_attr);
253 VALIDATE_PTHREAD_RESULT(result);
254
255 result = pthread_cond_init(data_.cond(), &cond_attr);
256 VALIDATE_PTHREAD_RESULT(result);
257
258 result = pthread_condattr_destroy(&cond_attr);
259 VALIDATE_PTHREAD_RESULT(result);
260 }
261
262
263 Monitor::~Monitor() {
264 int result = pthread_mutex_destroy(data_.mutex());
265 VALIDATE_PTHREAD_RESULT(result);
266
267 result = pthread_cond_destroy(data_.cond());
268 VALIDATE_PTHREAD_RESULT(result);
269 }
270
271
272 void Monitor::Enter() {
273 int result = pthread_mutex_lock(data_.mutex());
274 VALIDATE_PTHREAD_RESULT(result);
275 // TODO(iposva): Do we need to track lock owners?
276 }
277
278
279 void Monitor::Exit() {
280 // TODO(iposva): Do we need to track lock owners?
281 int result = pthread_mutex_unlock(data_.mutex());
282 VALIDATE_PTHREAD_RESULT(result);
283 }
284
285
286 Monitor::WaitResult Monitor::Wait(int64_t millis) {
287 return WaitMicros(millis * kMicrosecondsPerMillisecond);
288 }
289
290
291 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
292 // TODO(iposva): Do we need to track lock owners?
293 Monitor::WaitResult retval = kNotified;
294 if (micros == kNoTimeout) {
295 // Wait forever.
296 int result = pthread_cond_wait(data_.cond(), data_.mutex());
297 VALIDATE_PTHREAD_RESULT(result);
298 } else {
299 struct timespec ts;
300 ComputeTimeSpecMicros(&ts, micros);
301 int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
302 ASSERT((result == 0) || (result == ETIMEDOUT));
303 if (result == ETIMEDOUT) {
304 retval = kTimedOut;
305 }
306 }
307 return retval;
308 }
309
310
311 void Monitor::Notify() {
312 // TODO(iposva): Do we need to track lock owners?
313 int result = pthread_cond_signal(data_.cond());
314 VALIDATE_PTHREAD_RESULT(result);
315 }
316
317
318 void Monitor::NotifyAll() {
319 // TODO(iposva): Do we need to track lock owners?
320 int result = pthread_cond_broadcast(data_.cond());
321 VALIDATE_PTHREAD_RESULT(result);
322 }
323
324 } // namespace dart
325
326 #endif // defined(TARGET_OS_ANDROID)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698