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

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

Issue 1426743002: Add lock owner information for class Monitor and add assertions for wait/notify/notifyall. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: code-review-comments Created 5 years, 1 month 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
« no previous file with comments | « runtime/vm/os_thread_macos.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/vm/os_thread_macos.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698