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

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

Powered by Google App Engine
This is Rietveld 408576698