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 "platform/globals.h" // NOLINT | 5 #include "platform/globals.h" // NOLINT |
6 #if defined(TARGET_OS_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
7 | 7 |
8 #include "vm/growable_array.h" | 8 #include "vm/growable_array.h" |
9 #include "vm/os_thread.h" | 9 #include "vm/os_thread.h" |
10 | 10 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 } | 191 } |
192 } | 192 } |
193 | 193 |
194 | 194 |
195 Mutex::Mutex() { | 195 Mutex::Mutex() { |
196 // Allocate unnamed semaphore with initial count 1 and max count 1. | 196 // Allocate unnamed semaphore with initial count 1 and max count 1. |
197 data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL); | 197 data_.semaphore_ = CreateSemaphore(NULL, 1, 1, NULL); |
198 if (data_.semaphore_ == NULL) { | 198 if (data_.semaphore_ == NULL) { |
199 FATAL1("Mutex allocation failed %d", GetLastError()); | 199 FATAL1("Mutex allocation failed %d", GetLastError()); |
200 } | 200 } |
| 201 #if defined(DEBUG) |
201 // When running with assertions enabled we do track the owner. | 202 // When running with assertions enabled we do track the owner. |
202 #if defined(DEBUG) | |
203 owner_ = OSThread::kInvalidThreadId; | 203 owner_ = OSThread::kInvalidThreadId; |
204 #endif // defined(DEBUG) | 204 #endif // defined(DEBUG) |
205 } | 205 } |
206 | 206 |
207 | 207 |
208 Mutex::~Mutex() { | 208 Mutex::~Mutex() { |
209 CloseHandle(data_.semaphore_); | 209 CloseHandle(data_.semaphore_); |
| 210 #if defined(DEBUG) |
210 // When running with assertions enabled we do track the owner. | 211 // When running with assertions enabled we do track the owner. |
211 #if defined(DEBUG) | |
212 ASSERT(owner_ == OSThread::kInvalidThreadId); | 212 ASSERT(owner_ == OSThread::kInvalidThreadId); |
213 #endif // defined(DEBUG) | 213 #endif // defined(DEBUG) |
214 } | 214 } |
215 | 215 |
216 | 216 |
217 void Mutex::Lock() { | 217 void Mutex::Lock() { |
218 DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE); | 218 DWORD result = WaitForSingleObject(data_.semaphore_, INFINITE); |
219 if (result != WAIT_OBJECT_0) { | 219 if (result != WAIT_OBJECT_0) { |
220 FATAL1("Mutex lock failed %d", GetLastError()); | 220 FATAL1("Mutex lock failed %d", GetLastError()); |
221 } | 221 } |
| 222 #if defined(DEBUG) |
222 // When running with assertions enabled we do track the owner. | 223 // When running with assertions enabled we do track the owner. |
223 #if defined(DEBUG) | |
224 owner_ = OSThread::GetCurrentThreadId(); | 224 owner_ = OSThread::GetCurrentThreadId(); |
225 #endif // defined(DEBUG) | 225 #endif // defined(DEBUG) |
226 } | 226 } |
227 | 227 |
228 | 228 |
229 bool Mutex::TryLock() { | 229 bool Mutex::TryLock() { |
230 // Attempt to pass the semaphore but return immediately. | 230 // Attempt to pass the semaphore but return immediately. |
231 DWORD result = WaitForSingleObject(data_.semaphore_, 0); | 231 DWORD result = WaitForSingleObject(data_.semaphore_, 0); |
232 if (result == WAIT_OBJECT_0) { | 232 if (result == WAIT_OBJECT_0) { |
| 233 #if defined(DEBUG) |
233 // When running with assertions enabled we do track the owner. | 234 // When running with assertions enabled we do track the owner. |
234 #if defined(DEBUG) | |
235 owner_ = OSThread::GetCurrentThreadId(); | 235 owner_ = OSThread::GetCurrentThreadId(); |
236 #endif // defined(DEBUG) | 236 #endif // defined(DEBUG) |
237 return true; | 237 return true; |
238 } | 238 } |
239 if (result == WAIT_ABANDONED || result == WAIT_FAILED) { | 239 if (result == WAIT_ABANDONED || result == WAIT_FAILED) { |
240 FATAL1("Mutex try lock failed %d", GetLastError()); | 240 FATAL1("Mutex try lock failed %d", GetLastError()); |
241 } | 241 } |
242 ASSERT(result == WAIT_TIMEOUT); | 242 ASSERT(result == WAIT_TIMEOUT); |
243 return false; | 243 return false; |
244 } | 244 } |
245 | 245 |
246 | 246 |
247 void Mutex::Unlock() { | 247 void Mutex::Unlock() { |
| 248 #if defined(DEBUG) |
248 // When running with assertions enabled we do track the owner. | 249 // When running with assertions enabled we do track the owner. |
249 #if defined(DEBUG) | |
250 ASSERT(IsOwnedByCurrentThread()); | 250 ASSERT(IsOwnedByCurrentThread()); |
251 owner_ = OSThread::kInvalidThreadId; | 251 owner_ = OSThread::kInvalidThreadId; |
252 #endif // defined(DEBUG) | 252 #endif // defined(DEBUG) |
253 BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL); | 253 BOOL result = ReleaseSemaphore(data_.semaphore_, 1, NULL); |
254 if (result == 0) { | 254 if (result == 0) { |
255 FATAL1("Mutex unlock failed %d", GetLastError()); | 255 FATAL1("Mutex unlock failed %d", GetLastError()); |
256 } | 256 } |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = | 260 ThreadLocalKey MonitorWaitData::monitor_wait_data_key_ = |
261 OSThread::kUnsetThreadLocalKey; | 261 OSThread::kUnsetThreadLocalKey; |
262 | 262 |
263 | 263 |
264 Monitor::Monitor() { | 264 Monitor::Monitor() { |
265 InitializeCriticalSection(&data_.cs_); | 265 InitializeCriticalSection(&data_.cs_); |
266 InitializeCriticalSection(&data_.waiters_cs_); | 266 InitializeCriticalSection(&data_.waiters_cs_); |
267 data_.waiters_head_ = NULL; | 267 data_.waiters_head_ = NULL; |
268 data_.waiters_tail_ = NULL; | 268 data_.waiters_tail_ = NULL; |
| 269 |
| 270 #if defined(DEBUG) |
| 271 // When running with assertions enabled we track the owner. |
| 272 owner_ = OSThread::kInvalidThreadId; |
| 273 #endif // defined(DEBUG) |
269 } | 274 } |
270 | 275 |
271 | 276 |
272 Monitor::~Monitor() { | 277 Monitor::~Monitor() { |
| 278 #if defined(DEBUG) |
| 279 // When running with assertions enabled we track the owner. |
| 280 ASSERT(owner_ == OSThread::kInvalidThreadId); |
| 281 #endif // defined(DEBUG) |
| 282 |
273 DeleteCriticalSection(&data_.cs_); | 283 DeleteCriticalSection(&data_.cs_); |
274 DeleteCriticalSection(&data_.waiters_cs_); | 284 DeleteCriticalSection(&data_.waiters_cs_); |
275 } | 285 } |
276 | 286 |
277 | 287 |
278 void Monitor::Enter() { | 288 void Monitor::Enter() { |
279 EnterCriticalSection(&data_.cs_); | 289 EnterCriticalSection(&data_.cs_); |
| 290 |
| 291 #if defined(DEBUG) |
| 292 // When running with assertions enabled we track the owner. |
| 293 ASSERT(owner_ == OSThread::kInvalidThreadId); |
| 294 owner_ = OSThread::GetCurrentThreadId(); |
| 295 #endif // defined(DEBUG) |
280 } | 296 } |
281 | 297 |
282 | 298 |
283 void Monitor::Exit() { | 299 void Monitor::Exit() { |
| 300 #if defined(DEBUG) |
| 301 // When running with assertions enabled we track the owner. |
| 302 ASSERT(IsOwnedByCurrentThread()); |
| 303 owner_ = OSThread::kInvalidThreadId; |
| 304 #endif // defined(DEBUG) |
| 305 |
284 LeaveCriticalSection(&data_.cs_); | 306 LeaveCriticalSection(&data_.cs_); |
285 } | 307 } |
286 | 308 |
287 | 309 |
288 void MonitorWaitData::ThreadExit() { | 310 void MonitorWaitData::ThreadExit() { |
289 if (MonitorWaitData::monitor_wait_data_key_ != | 311 if (MonitorWaitData::monitor_wait_data_key_ != |
290 OSThread::kUnsetThreadLocalKey) { | 312 OSThread::kUnsetThreadLocalKey) { |
291 uword raw_wait_data = | 313 uword raw_wait_data = |
292 OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); | 314 OSThread::GetThreadLocal(MonitorWaitData::monitor_wait_data_key_); |
293 // Clear in case this is called a second time. | 315 // Clear in case this is called a second time. |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 reinterpret_cast<uword>(wait_data)); | 432 reinterpret_cast<uword>(wait_data)); |
411 } else { | 433 } else { |
412 wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data); | 434 wait_data = reinterpret_cast<MonitorWaitData*>(raw_wait_data); |
413 wait_data->next_ = NULL; | 435 wait_data->next_ = NULL; |
414 } | 436 } |
415 return wait_data; | 437 return wait_data; |
416 } | 438 } |
417 | 439 |
418 | 440 |
419 Monitor::WaitResult Monitor::Wait(int64_t millis) { | 441 Monitor::WaitResult Monitor::Wait(int64_t millis) { |
| 442 #if defined(DEBUG) |
| 443 // When running with assertions enabled we track the owner. |
| 444 ASSERT(IsOwnedByCurrentThread()); |
| 445 ThreadId saved_owner = owner_; |
| 446 owner_ = OSThread::kInvalidThreadId; |
| 447 #endif // defined(DEBUG) |
| 448 |
420 Monitor::WaitResult retval = kNotified; | 449 Monitor::WaitResult retval = kNotified; |
421 | 450 |
422 // Get the wait data object containing the event to wait for. | 451 // Get the wait data object containing the event to wait for. |
423 MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread(); | 452 MonitorWaitData* wait_data = MonitorData::GetMonitorWaitDataForThread(); |
424 | 453 |
425 // Start waiting by adding the MonitorWaitData to the list of | 454 // Start waiting by adding the MonitorWaitData to the list of |
426 // waiters. | 455 // waiters. |
427 data_.AddWaiter(wait_data); | 456 data_.AddWaiter(wait_data); |
428 | 457 |
429 // Leave the monitor critical section while waiting. | 458 // Leave the monitor critical section while waiting. |
(...skipping 17 matching lines...) Expand all Loading... |
447 if (result == WAIT_TIMEOUT) { | 476 if (result == WAIT_TIMEOUT) { |
448 // No longer waiting. Remove from the list of waiters. | 477 // No longer waiting. Remove from the list of waiters. |
449 data_.RemoveWaiter(wait_data); | 478 data_.RemoveWaiter(wait_data); |
450 retval = kTimedOut; | 479 retval = kTimedOut; |
451 } | 480 } |
452 } | 481 } |
453 | 482 |
454 // Reacquire the monitor critical section before continuing. | 483 // Reacquire the monitor critical section before continuing. |
455 EnterCriticalSection(&data_.cs_); | 484 EnterCriticalSection(&data_.cs_); |
456 | 485 |
| 486 #if defined(DEBUG) |
| 487 // When running with assertions enabled we track the owner. |
| 488 ASSERT(owner_ == OSThread::kInvalidThreadId); |
| 489 owner_ = OSThread::GetCurrentThreadId(); |
| 490 ASSERT(owner_ == saved_owner); |
| 491 #endif // defined(DEBUG) |
457 return retval; | 492 return retval; |
458 } | 493 } |
459 | 494 |
460 | 495 |
461 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) { | 496 Monitor::WaitResult Monitor::WaitMicros(int64_t micros) { |
462 // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows. | 497 // TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows. |
463 int64_t millis = micros / kMicrosecondsPerMillisecond; | 498 int64_t millis = micros / kMicrosecondsPerMillisecond; |
464 if ((millis * kMicrosecondsPerMillisecond) < micros) { | 499 if ((millis * kMicrosecondsPerMillisecond) < micros) { |
465 // We've been asked to sleep for a fraction of a millisecond, | 500 // We've been asked to sleep for a fraction of a millisecond, |
466 // this isn't supported on Windows. Bumps milliseconds up by one | 501 // this isn't supported on Windows. Bumps milliseconds up by one |
467 // so that we never return too early. We likely return late though. | 502 // so that we never return too early. We likely return late though. |
468 millis += 1; | 503 millis += 1; |
469 } | 504 } |
470 return Wait(millis); | 505 return Wait(millis); |
471 } | 506 } |
472 | 507 |
473 | 508 |
474 void Monitor::Notify() { | 509 void Monitor::Notify() { |
| 510 // When running with assertions enabled we track the owner. |
| 511 ASSERT(IsOwnedByCurrentThread()); |
475 data_.SignalAndRemoveFirstWaiter(); | 512 data_.SignalAndRemoveFirstWaiter(); |
476 } | 513 } |
477 | 514 |
478 | 515 |
479 void Monitor::NotifyAll() { | 516 void Monitor::NotifyAll() { |
| 517 // When running with assertions enabled we track the owner. |
| 518 ASSERT(IsOwnedByCurrentThread()); |
480 // If one of the objects in the list of waiters wakes because of a | 519 // If one of the objects in the list of waiters wakes because of a |
481 // timeout before we signal it, that object will get an extra | 520 // timeout before we signal it, that object will get an extra |
482 // signal. This will be treated as a spurious wake-up and is OK | 521 // signal. This will be treated as a spurious wake-up and is OK |
483 // since all uses of monitors should recheck the condition after a | 522 // since all uses of monitors should recheck the condition after a |
484 // Wait. | 523 // Wait. |
485 data_.SignalAndRemoveAllWaiters(); | 524 data_.SignalAndRemoveAllWaiters(); |
486 } | 525 } |
487 | 526 |
488 | 527 |
489 void ThreadLocalData::AddThreadLocal(ThreadLocalKey key, | 528 void ThreadLocalData::AddThreadLocal(ThreadLocalKey key, |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 #pragma data_seg(".CRT$XLB") | 677 #pragma data_seg(".CRT$XLB") |
639 PIMAGE_TLS_CALLBACK p_thread_callback_dart = OnDartThreadExit; | 678 PIMAGE_TLS_CALLBACK p_thread_callback_dart = OnDartThreadExit; |
640 | 679 |
641 // Reset the default section. | 680 // Reset the default section. |
642 #pragma data_seg() | 681 #pragma data_seg() |
643 | 682 |
644 #endif // _WIN64 | 683 #endif // _WIN64 |
645 } // extern "C" | 684 } // extern "C" |
646 | 685 |
647 #endif // defined(TARGET_OS_WINDOWS) | 686 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |