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

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

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

Powered by Google App Engine
This is Rietveld 408576698