OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <errno.h> | 5 #include <errno.h> |
6 #include <sys/time.h> | 6 #include <sys/time.h> |
7 | 7 |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/thread.h" | 9 #include "vm/thread.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 #define VALIDATE_PTHREAD_RESULT(result) \ | 13 #define VALIDATE_PTHREAD_RESULT(result) \ |
14 if (result != 0) { \ | 14 if (result != 0) { \ |
15 FATAL2("pthread error: %d (%s)", result, strerror(result)); \ | 15 FATAL2("pthread error: %d (%s)", result, strerror(result)); \ |
16 } | 16 } |
17 | 17 |
18 | 18 |
19 static void ComputeTimeSpec(struct timespec* ts, int64_t millis) { | |
20 int64_t secs = millis / kMillisecondsPerSecond; | |
21 int64_t nanos = | |
22 (millis - (secs * kMillisecondsPerSecond)) * kNanosecondsPerMillisecond; | |
23 int result = clock_gettime(CLOCK_MONOTONIC, ts); | |
24 ASSERT(result == 0); | |
25 ts->tv_sec += secs; | |
26 ts->tv_nsec += nanos; | |
27 if (ts->tv_nsec >= kNanosecondsPerSecond) { | |
28 ts->tv_sec += 1; | |
29 ts->tv_nsec -= kNanosecondsPerSecond; | |
30 } | |
31 } | |
32 | |
33 | |
34 class ThreadStartData { | 19 class ThreadStartData { |
35 public: | 20 public: |
36 ThreadStartData(Thread::ThreadStartFunction function, | 21 ThreadStartData(Thread::ThreadStartFunction function, |
37 uword parameter, | 22 uword parameter, |
38 Thread* thread) | 23 Thread* thread) |
39 : function_(function), parameter_(parameter), thread_(thread) {} | 24 : function_(function), parameter_(parameter), thread_(thread) {} |
40 | 25 |
41 Thread::ThreadStartFunction function() const { return function_; } | 26 Thread::ThreadStartFunction function() const { return function_; } |
42 uword parameter() const { return parameter_; } | 27 uword parameter() const { return parameter_; } |
43 Thread* thread() const { return thread_; } | 28 Thread* thread() const { return thread_; } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 data_.tid_ = tid; | 80 data_.tid_ = tid; |
96 | 81 |
97 result = pthread_attr_destroy(&attr); | 82 result = pthread_attr_destroy(&attr); |
98 VALIDATE_PTHREAD_RESULT(result); | 83 VALIDATE_PTHREAD_RESULT(result); |
99 } | 84 } |
100 | 85 |
101 | 86 |
102 Thread::~Thread() { | 87 Thread::~Thread() { |
103 } | 88 } |
104 | 89 |
105 | |
106 Mutex::Mutex() { | |
107 pthread_mutexattr_t attr; | |
108 int result = pthread_mutexattr_init(&attr); | |
109 VALIDATE_PTHREAD_RESULT(result); | |
110 | |
111 #if defined(DEBUG) | |
112 result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); | |
113 VALIDATE_PTHREAD_RESULT(result); | |
114 #endif // defined(DEBUG) | |
115 | |
116 result = pthread_mutex_init(data_.mutex(), &attr); | |
117 // Verify that creating a pthread_mutex succeeded. | |
118 VALIDATE_PTHREAD_RESULT(result); | |
119 | |
120 result = pthread_mutexattr_destroy(&attr); | |
121 VALIDATE_PTHREAD_RESULT(result); | |
122 } | |
123 | |
124 | |
125 Mutex::~Mutex() { | |
126 int result = pthread_mutex_destroy(data_.mutex()); | |
127 // Verify that the pthread_mutex was destroyed. | |
128 VALIDATE_PTHREAD_RESULT(result); | |
129 } | |
130 | |
131 | |
132 void Mutex::Lock() { | |
133 int result = pthread_mutex_lock(data_.mutex()); | |
134 // Specifically check for dead lock to help debugging. | |
135 ASSERT(result != EDEADLK); | |
136 ASSERT(result == 0); // Verify no other errors. | |
137 // TODO(iposva): Do we need to track lock owners? | |
138 } | |
139 | |
140 | |
141 bool Mutex::TryLock() { | |
142 int result = pthread_mutex_trylock(data_.mutex()); | |
143 // Return false if the lock is busy and locking failed. | |
144 if (result == EBUSY) { | |
145 return false; | |
146 } | |
147 ASSERT(result == 0); // Verify no other errors. | |
148 // TODO(iposva): Do we need to track lock owners? | |
149 return true; | |
150 } | |
151 | |
152 | |
153 void Mutex::Unlock() { | |
154 // TODO(iposva): Do we need to track lock owners? | |
155 int result = pthread_mutex_unlock(data_.mutex()); | |
156 // Specifically check for wrong thread unlocking to aid debugging. | |
157 ASSERT(result != EPERM); | |
158 ASSERT(result == 0); // Verify no other errors. | |
159 } | |
160 | |
161 | |
162 Monitor::Monitor() { | |
163 pthread_mutexattr_t mutex_attr; | |
164 int result = pthread_mutexattr_init(&mutex_attr); | |
165 VALIDATE_PTHREAD_RESULT(result); | |
166 | |
167 #if defined(DEBUG) | |
168 result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); | |
169 VALIDATE_PTHREAD_RESULT(result); | |
170 #endif // defined(DEBUG) | |
171 | |
172 result = pthread_mutex_init(data_.mutex(), &mutex_attr); | |
173 VALIDATE_PTHREAD_RESULT(result); | |
174 | |
175 result = pthread_mutexattr_destroy(&mutex_attr); | |
176 VALIDATE_PTHREAD_RESULT(result); | |
177 | |
178 pthread_condattr_t cond_attr; | |
179 result = pthread_condattr_init(&cond_attr); | |
180 VALIDATE_PTHREAD_RESULT(result); | |
181 | |
182 result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC); | |
183 VALIDATE_PTHREAD_RESULT(result); | |
184 | |
185 result = pthread_cond_init(data_.cond(), &cond_attr); | |
186 VALIDATE_PTHREAD_RESULT(result); | |
187 | |
188 result = pthread_condattr_destroy(&cond_attr); | |
189 VALIDATE_PTHREAD_RESULT(result); | |
190 } | |
191 | |
192 | |
193 Monitor::~Monitor() { | |
194 int result = pthread_mutex_destroy(data_.mutex()); | |
195 VALIDATE_PTHREAD_RESULT(result); | |
196 | |
197 result = pthread_cond_destroy(data_.cond()); | |
198 VALIDATE_PTHREAD_RESULT(result); | |
199 } | |
200 | |
201 | |
202 void Monitor::Enter() { | |
203 int result = pthread_mutex_lock(data_.mutex()); | |
204 VALIDATE_PTHREAD_RESULT(result); | |
205 // TODO(iposva): Do we need to track lock owners? | |
206 } | |
207 | |
208 | |
209 void Monitor::Exit() { | |
210 // TODO(iposva): Do we need to track lock owners? | |
211 int result = pthread_mutex_unlock(data_.mutex()); | |
212 VALIDATE_PTHREAD_RESULT(result); | |
213 } | |
214 | |
215 | |
216 Monitor::WaitResult Monitor::Wait(int64_t millis) { | |
217 // TODO(iposva): Do we need to track lock owners? | |
218 Monitor::WaitResult retval = kNotified; | |
219 if (millis == 0) { | |
220 // Wait forever. | |
221 int result = pthread_cond_wait(data_.cond(), data_.mutex()); | |
222 VALIDATE_PTHREAD_RESULT(result); | |
223 } else { | |
224 struct timespec ts; | |
225 ComputeTimeSpec(&ts, millis); | |
226 int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts); | |
227 ASSERT((result == 0) || (result == ETIMEDOUT)); | |
228 if (result == ETIMEDOUT) { | |
229 retval = kTimedOut; | |
230 } | |
231 } | |
232 return retval; | |
233 } | |
234 | |
235 | |
236 void Monitor::Notify() { | |
237 // TODO(iposva): Do we need to track lock owners? | |
238 int result = pthread_cond_signal(data_.cond()); | |
239 VALIDATE_PTHREAD_RESULT(result); | |
240 } | |
241 | |
242 | |
243 void Monitor::NotifyAll() { | |
244 // TODO(iposva): Do we need to track lock owners? | |
245 int result = pthread_cond_broadcast(data_.cond()); | |
246 VALIDATE_PTHREAD_RESULT(result); | |
247 } | |
248 | |
249 } // namespace dart | 90 } // namespace dart |
OLD | NEW |