windows.hpp (17521B)
1 /* Relacy Race Detector 2 * Copyright (c) 2008-2010, Dmitry S. Vyukov 3 * All rights reserved. 4 * This software is provided AS-IS with no warranty, either express or implied. 5 * This software is distributed under a license and may not be copied, 6 * modified or distributed except as expressly authorized under the 7 * terms of the license contained in the file LICENSE.TXT in this distribution. 8 */ 9 10 #ifndef RL_WINDOWS_HPP 11 #define RL_WINDOWS_HPP 12 #ifdef _MSC_VER 13 # pragma once 14 #endif 15 16 #include "mutex.hpp" 17 #include "condition_variable.hpp" 18 #include "semaphore.hpp" 19 #include "event.hpp" 20 21 22 namespace rl 23 { 24 25 typedef win_object* rl_HANDLE; 26 unsigned long const rl_INFINITE = (unsigned long)-1; 27 28 unsigned long const rl_WAIT_FAILED = (unsigned long)-1; 29 unsigned long const rl_WAIT_OBJECT_0 = 100; 30 unsigned long const rl_WAIT_TIMEOUT = 1; 31 unsigned long const rl_WAIT_IO_COMPLETION = 2; 32 unsigned long const rl_MAXIMUM_WAIT_OBJECTS = wfmo_max_objects; 33 34 35 inline int rl_SwitchToThread(debug_info_param info) 36 { 37 yield(1, info); 38 return 1; 39 } 40 41 inline void rl_Sleep(unsigned long milliseconds, debug_info_param info) 42 { 43 yield(milliseconds ? milliseconds : 1, info); 44 } 45 46 47 48 inline unsigned long rl_WaitForSingleObjectEx(rl_HANDLE obj, unsigned long timeout, int alertable, debug_info_param info) 49 { 50 (void)alertable; //!!! not yet supported – support it! 51 //!!! support WAIT_IO_COMPLETION 52 RL_VERIFY(false == alertable && "Alertable wait is not supported in WaitForSingleObject() yet"); 53 54 bool try_wait = (timeout == 0); 55 bool is_timed = (timeout != rl_INFINITE); 56 sema_wakeup_reason reason = static_cast<win_waitable_object*>(obj)->wait(try_wait, is_timed, info); 57 if (reason == sema_wakeup_reason_success) 58 return rl_WAIT_OBJECT_0; 59 else if (reason == sema_wakeup_reason_timeout) 60 return rl_WAIT_TIMEOUT; 61 else if (reason == sema_wakeup_reason_failed) 62 return rl_WAIT_TIMEOUT; 63 RL_VERIFY(false); 64 return rl_WAIT_FAILED; 65 } 66 67 inline unsigned long rl_WaitForSingleObject(rl_HANDLE obj, unsigned long timeout, debug_info_param info) 68 { 69 return rl_WaitForSingleObjectEx(obj, timeout, 0, info); 70 } 71 72 inline unsigned long rl_WaitForMultipleObjectsEx(unsigned long count, rl_HANDLE* objects, int wait_all, unsigned long timeout, int alertable, debug_info_param info) 73 { 74 (void)alertable; //!!! 75 //!!! support WAIT_IO_COMPLETION 76 RL_VERIFY(false == alertable && "Alertable wait is not supported in WaitForMultipleObjects() yet"); 77 78 bool try_wait = (timeout == 0); 79 bool is_timed = (timeout != rl_INFINITE); 80 win_waitable_object** obj = reinterpret_cast<win_waitable_object**>(objects); 81 size_t signaled = 0; 82 sema_wakeup_reason reason = wait_for_multiple_objects(signaled, count, obj, !!wait_all, try_wait, is_timed, info); 83 if (reason == sema_wakeup_reason_success) 84 return rl_WAIT_OBJECT_0 + (int)signaled; 85 else if (reason == sema_wakeup_reason_timeout) 86 return rl_WAIT_TIMEOUT; 87 RL_VERIFY(false); 88 return rl_WAIT_FAILED; 89 } 90 91 inline unsigned long rl_WaitForMultipleObjects(unsigned long count, rl_HANDLE* objects, int wait_all, unsigned long timeout, debug_info_param info) 92 { 93 return rl_WaitForMultipleObjectsEx(count, objects, wait_all, timeout, 0, info); 94 } 95 96 inline unsigned long rl_SignalObjectAndWait(rl_HANDLE obj_to_signal, 97 rl_HANDLE obj_to_wait, 98 unsigned long timeout, 99 int alertable, 100 debug_info_param info) 101 { 102 bool result = static_cast<win_waitable_object*>(obj_to_signal)->signal(info); 103 if (false == result) 104 return result ? 1 : 0; 105 preemption_disabler pd (ctx()); 106 return rl_WaitForSingleObjectEx(obj_to_wait, timeout, alertable, info); 107 } 108 109 110 111 struct sem_tag_win; 112 113 inline rl_HANDLE rl_CreateSemaphore(void* /*security*/, long initial_count, long max_count, void const* /*name*/, debug_info_param info) 114 { 115 void* mem = ctx().alloc(sizeof(semaphore<sem_tag_win>), false, info); 116 semaphore<sem_tag_win>* sema = new (mem) semaphore<sem_tag_win>; 117 sema->init(false, initial_count, max_count, info); 118 return sema; 119 } 120 121 inline int rl_CloseHandle(rl_HANDLE h, debug_info_param info) 122 { 123 h->deinit(info); 124 h->~win_object(); 125 (ctx().free)(h, false, info); //!!! rename free because of the define 126 return 1; 127 } 128 129 inline int rl_ReleaseSemaphore(rl_HANDLE sema, long count, long* prev_count, debug_info_param info) 130 { 131 unsigned prev = 0; 132 bool result = static_cast<semaphore<sem_tag_win>*>(sema)->post(count, prev, info); 133 if (prev_count) 134 prev_count[0] = prev; 135 return result ? 1 : 0; 136 } 137 138 139 140 141 inline rl_HANDLE rl_CreateEvent(void* /*security*/, int manual_reset, int initial_state, void const* /*name*/, debug_info_param info) 142 { 143 void* mem = ctx().alloc(sizeof(generic_event), false, info); 144 generic_event* ev = new (mem) generic_event; 145 ev->init(!!manual_reset, !!initial_state, info); 146 return ev; 147 } 148 149 inline int rl_SetEvent(rl_HANDLE ev, debug_info_param info) 150 { 151 static_cast<generic_event*>(ev)->set(info); 152 return 1; 153 } 154 155 inline int rl_ResetEvent(rl_HANDLE ev, debug_info_param info) 156 { 157 static_cast<generic_event*>(ev)->reset(info); 158 return 1; 159 } 160 161 inline int rl_PulseEvent(rl_HANDLE ev, debug_info_param info) 162 { 163 static_cast<generic_event*>(ev)->pulse(info); 164 return 1; 165 } 166 167 168 169 struct mutex_tag_win_cs; 170 typedef generic_mutex<mutex_tag_win_cs> rl_CRITICAL_SECTION; 171 172 inline void rl_InitializeCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) 173 { 174 m->init(false, true, false, false, info); 175 } 176 177 inline int rl_InitializeCriticalSectionAndSpinCount(rl_CRITICAL_SECTION* m, unsigned long spin_count, debug_info_param info) 178 { 179 (void)spin_count; 180 m->init(false, true, false, false, info); 181 return 1; 182 } 183 184 inline int rl_InitializeCriticalSectionEx(rl_CRITICAL_SECTION* m, unsigned long spin_count, unsigned long flags, debug_info_param info) 185 { 186 (void)spin_count; 187 (void)flags; 188 m->init(false, true, false, false, info); 189 return 1; 190 } 191 192 inline void rl_DeleteCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) 193 { 194 m->deinit(info); 195 } 196 197 inline void rl_EnterCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) 198 { 199 m->lock_exclusive(info); 200 } 201 202 inline int rl_TryEnterCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) 203 { 204 return m->try_lock_exclusive(info) ? 1 : 0; 205 } 206 207 inline void rl_LeaveCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) 208 { 209 m->unlock_exclusive(info); 210 } 211 212 struct mutex_tag_win_srwl; 213 typedef generic_mutex<mutex_tag_win_srwl> rl_SRWLOCK; 214 215 inline void rl_InitializeSRWLock(rl_SRWLOCK* lock, debug_info_param info) 216 { 217 lock->init(true, false, false, false, info); 218 } 219 220 inline void rl_AcquireSRWLockExclusive(rl_SRWLOCK* lock, debug_info_param info) 221 { 222 lock->lock_exclusive(info); 223 } 224 225 inline void rl_AcquireSRWLockShared(rl_SRWLOCK* lock, debug_info_param info) 226 { 227 lock->lock_shared(info); 228 } 229 230 inline void rl_ReleaseSRWLockExclusive(rl_SRWLOCK* lock, debug_info_param info) 231 { 232 lock->unlock_exclusive(info); 233 } 234 235 inline void rl_ReleaseSRWLockShared(rl_SRWLOCK* lock, debug_info_param info) 236 { 237 lock->unlock_shared(info); 238 } 239 240 //!!! 241 inline void rl_DeleteSRWLock(rl_SRWLOCK* lock, debug_info_param info) 242 { 243 lock->deinit(info); 244 } 245 246 247 struct mutex_tag_win_mutex; 248 typedef generic_mutex<mutex_tag_win_mutex> rl_win_mutex; 249 250 251 inline rl_HANDLE rl_CreateMutex(void* /*security*/, int initial_owner, void const* /*name*/, debug_info_param info) 252 { 253 void* mem = ctx().alloc(sizeof(rl_win_mutex), false, info); 254 rl_win_mutex* mtx = new (mem) rl_win_mutex (); 255 mtx->init(false, true, false, false, info); 256 if (initial_owner) 257 mtx->lock_exclusive(info); 258 return mtx; 259 } 260 261 inline int rl_ReleaseMutex(rl_HANDLE mtx, debug_info_param info) 262 { 263 static_cast<rl_win_mutex*>(mtx)->unlock_exclusive(info); 264 return 1; 265 266 } 267 268 269 270 struct condvar_tag_win; 271 typedef condvar<condvar_tag_win> rl_CONDITION_VARIABLE; 272 unsigned long const rl_CONDITION_VARIABLE_LOCKMODE_SHARED = 1; 273 274 inline void rl_InitializeConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) 275 { 276 cv->init(false, info); 277 } 278 279 inline int rl_SleepConditionVariableCS(rl_CONDITION_VARIABLE* cv, rl_CRITICAL_SECTION* cs, unsigned long ms, debug_info_param info) 280 { 281 cv->wait(*cs, ms != rl_INFINITE, info); 282 return 0; 283 } 284 285 inline int rl_SleepConditionVariableSRW(rl_CONDITION_VARIABLE* cv, rl_SRWLOCK* lock, unsigned long ms, unsigned long flags, debug_info_param info) 286 { 287 //!!! CONDITION_VARIABLE_LOCKMODE_SHARED 288 (void)flags; 289 cv->wait(*lock, ms != rl_INFINITE, info); 290 return 0; 291 } 292 293 inline void rl_WakeAllConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) 294 { 295 cv->notify_all(info); 296 } 297 298 inline void rl_WakeConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) 299 { 300 cv->notify_one(info); 301 } 302 303 inline void rl_DeleteConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) 304 { 305 cv->deinit(info); 306 } 307 308 309 310 311 312 313 typedef unsigned long (RL_STDCALL *rl_WIN_START_ROUTINE)(void* param); 314 typedef unsigned (RL_STDCALL *rl_MSVCR_THREAD_ROUTINE)(void* param); 315 316 template<typename thread_fn_t> 317 struct win32_thread_helper 318 { 319 thread_fn_t fn; 320 void* param; 321 322 static void* thread(void* p) 323 { 324 win32_thread_helper* self = (win32_thread_helper*)p; 325 void* result = (void*)(uintptr_t)(self->fn(self->param)); 326 delete_impl(self, $); 327 return result; 328 } 329 }; 330 331 inline rl_HANDLE rl_CreateThread(void* security, unsigned stack_size, rl_WIN_START_ROUTINE fn, void* param, unsigned long creation_flags, unsigned long* thread_id, debug_info_param info) 332 { 333 (void)security; 334 (void)stack_size; 335 (void)creation_flags; 336 (void)thread_id; 337 338 void* mem = 339 ctx().alloc(sizeof(win32_thread_helper<rl_WIN_START_ROUTINE>), false, info); 340 win32_thread_helper<rl_WIN_START_ROUTINE>* arg = 341 new (mem) win32_thread_helper<rl_WIN_START_ROUTINE>; 342 arg->fn = fn; 343 arg->param = param; 344 win_waitable_object* handle = ctx().create_thread(&win32_thread_helper<rl_WIN_START_ROUTINE>::thread, arg); 345 return handle; 346 } 347 348 349 inline uintptr_t rl_beginthreadex(void *security, unsigned stack_size, rl_MSVCR_THREAD_ROUTINE start_address, void *arglist, unsigned initflag, unsigned* thrdaddr, debug_info_param info) 350 { 351 (void)security; 352 (void)stack_size; 353 (void)initflag; 354 (void)thrdaddr; 355 356 void* mem = ctx().alloc(sizeof(win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>), false, info); 357 win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>* arg = 358 new (mem) win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>; 359 arg->fn = start_address; 360 arg->param = arglist; 361 win_waitable_object* handle = ctx().create_thread(&win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>::thread, arg); 362 return (uintptr_t)handle; 363 } 364 365 inline unsigned long rl_SetThreadAffinityMask(rl_HANDLE th, unsigned long affinity_mask, debug_info_param info) 366 { 367 (void)(th); 368 (void)(affinity_mask); 369 (void)info; 370 return 0; 371 } 372 373 inline int rl_SuspendThread(rl_HANDLE th, debug_info_param info) 374 { 375 (void)th; 376 (void)info; 377 return 1; 378 } 379 380 inline int rl_ResumeThread(rl_HANDLE th, debug_info_param info) 381 { 382 (void)th; 383 (void)info; 384 return 1; 385 } 386 387 inline unsigned long GetLastError() 388 { 389 return (unsigned long)get_errno(); 390 } 391 392 inline void SetLastError(unsigned long value) 393 { 394 set_errno((int)value); 395 } 396 397 inline void rl_FlushProcessWriteBuffers(debug_info_param info) 398 { 399 systemwide_fence(info); 400 } 401 402 } 403 404 405 #ifdef HANDLE 406 # undef HANDLE 407 #endif 408 #define HANDLE rl::rl_HANDLE 409 410 #ifdef INFINITE 411 # undef INFINITE 412 #endif 413 #define INFINITE rl::rl_INFINITE 414 415 416 #ifdef WAIT_FAILED 417 # undef WAIT_FAILED 418 #endif 419 #define WAIT_FAILED rl::rl_WAIT_FAILED 420 421 #ifdef WAIT_OBJECT_0 422 # undef WAIT_OBJECT_0 423 #endif 424 #define WAIT_OBJECT_0 rl::rl_WAIT_OBJECT_0 425 426 #ifdef WAIT_TIMEOUT 427 # undef WAIT_TIMEOUT 428 #endif 429 #define WAIT_TIMEOUT rl::rl_WAIT_TIMEOUT 430 431 #ifdef WAIT_IO_COMPLETION 432 # undef WAIT_IO_COMPLETION 433 #endif 434 #define WAIT_IO_COMPLETION rl::rl_WAIT_IO_COMPLETION 435 436 #ifdef MAXIMUM_WAIT_OBJECTS 437 # undef MAXIMUM_WAIT_OBJECTS 438 #endif 439 #define MAXIMUM_WAIT_OBJECTS rl::rl_MAXIMUM_WAIT_OBJECTS 440 441 442 443 #define SwitchToThread() \ 444 rl::rl_SwitchToThread($) 445 446 #define Sleep(milliseconds) \ 447 rl::rl_Sleep(milliseconds, $) 448 449 450 451 #define CloseHandle(obj) \ 452 rl::rl_CloseHandle(obj, $) 453 454 #define WaitForSingleObject(obj, timeout) \ 455 rl::rl_WaitForSingleObject(obj, timeout, $) 456 457 #define WaitForMultipleObjects(count, objects, wait_all, timeout) \ 458 rl::rl_WaitForMultipleObjects(count, objects, wait_all, timeout, $) 459 460 #define WaitForMultipleObjectsEx(count, objects, wait_all, timeout, alertable)] \ 461 rl::rl_WaitForMultipleObjectsEx(count, objects, wait_all, timeout, alertable, $) 462 463 #define SignalObjectAndWait(obj_to_signal, obj_to_wait, timeout, alertable) \ 464 rl::rl_SignalObjectAndWait(obj_to_signal, obj_to_wait, timeout, alertable, $) 465 466 #ifdef CreateSemaphore 467 # undef CreateSemaphore 468 #endif 469 470 #ifdef CreateSemaphore 471 # undef ReleaseSemaphore 472 #endif 473 474 #define CreateSemaphoreA rl_CreateSemaphore 475 #define CreateSemaphoreW rl_CreateSemaphore 476 #define CreateSemaphore rl_CreateSemaphore 477 #define rl_CreateSemaphore(security, initial_count, max_count, name) \ 478 rl::rl_CreateSemaphore(security, initial_count, max_count, name, $)\ 479 480 #define ReleaseSemaphore(sema, count, prev_count) \ 481 rl::rl_ReleaseSemaphore(sema, count, prev_count, $) 482 483 484 485 #ifdef CreateEvent 486 # undef CreateEvent 487 #endif 488 #define CreateEventA rl_CreateEvent 489 #define CreateEventW rl_CreateEvent 490 #define CreateEvent rl_CreateEvent 491 #define rl_CreateEvent(security, manual_reset, initial_state, name)\ 492 rl::rl_CreateEvent(security, manual_reset, initial_state, name, $) 493 494 #define SetEvent(ev)\ 495 rl::rl_SetEvent(ev, $) 496 497 #define ResetEvent(ev)\ 498 rl::rl_ResetEvent(ev, $) 499 500 #define PulseEvent(ev)\ 501 rl::rl_PulseEvent(ev, $) 502 503 504 #ifdef CreateMutex 505 # undef CreateMutex 506 #endif 507 #define CreateMutexA rl_CreateMutex 508 #define CreateMutexW rl_CreateMutex 509 #define CreateMutex rl_CreateMutex 510 #define rl_CreateMutex(security, initial_owner, name)\ 511 rl::rl_CreateMutex(security, initial_owner, name, $) 512 513 #define ReleaseMutex(mtx)\ 514 rl::rl_ReleaseMutex(mtx, $) 515 516 517 518 #define CRITICAL_SECTION rl::rl_CRITICAL_SECTION 519 520 #define InitializeCriticalSection(cs) \ 521 rl::rl_InitializeCriticalSection(cs, $) 522 523 #define InitializeCriticalSectionAndSpinCount(cs, spin) \ 524 rl::rl_InitializeCriticalSectionAndSpinCount(cs, spin, $) 525 526 #define InitializeCriticalSectionEx(cs, spin, flags) \ 527 rl::rl_InitializeCriticalSectionEx(cs, spin, flags, $) 528 529 #define DeleteCriticalSection(cs) \ 530 rl::rl_DeleteCriticalSection(cs, $) 531 532 #define EnterCriticalSection(cs) \ 533 rl::rl_EnterCriticalSection(cs, $) 534 535 #define TryEnterCriticalSection(cs) \ 536 rl::rl_TryEnterCriticalSection(cs, $) 537 538 #define LeaveCriticalSection(cs) \ 539 rl::rl_LeaveCriticalSection(cs, $) 540 541 542 543 544 #define SRWLOCK rl::rl_SRWLOCK 545 546 #define InitializeSRWLock(lock) \ 547 rl::rl_InitializeSRWLock(lock, $) 548 549 #define AcquireSRWLockExclusive(lock) \ 550 rl::rl_AcquireSRWLockExclusive(lock, $) 551 552 #define AcquireSRWLockShared(lock) \ 553 rl::rl_AcquireSRWLockShared(lock, $) 554 555 #define ReleaseSRWLockExclusive(lock) \ 556 rl::rl_ReleaseSRWLockExclusive(lock, $) 557 558 #define ReleaseSRWLockShared(lock) \ 559 rl::rl_ReleaseSRWLockShared(lock, $) 560 561 //!!! no such function in WIN API 562 #define DeleteSRWLock(lock) \ 563 rl::rl_DeleteSRWLock(lock, $) 564 565 566 567 568 569 570 #define CONDITION_VARIABLE rl::rl_CONDITION_VARIABLE 571 572 #ifdef CONDITION_VARIABLE_LOCKMODE_SHARED 573 # undef CONDITION_VARIABLE_LOCKMODE_SHARED 574 #endif 575 #define CONDITION_VARIABLE_LOCKMODE_SHARED rl::rl_CONDITION_VARIABLE_LOCKMODE_SHARED 576 577 #define InitializeConditionVariable(cv) \ 578 rl::rl_InitializeConditionVariable(cv, $) 579 580 #define SleepConditionVariableCS(cv, cs, ms) \ 581 rl::rl_SleepConditionVariableCS(cv, cs, ms, $) 582 583 #define SleepConditionVariableSRW(cv, lock, ms, flags) \ 584 rl::rl_SleepConditionVariableSRW(cv, lock, ms, flags, $) 585 586 #define WakeAllConditionVariable(cv) \ 587 rl::rl_WakeAllConditionVariable(cv, $) 588 589 #define WakeConditionVariable(cv) \ 590 rl::rl_WakeConditionVariable(cv, $) 591 592 //!!! no such function in WIN API 593 #define DeleteConditionVariable(cv) \ 594 rl::rl_DeleteConditionVariable(cv, $) 595 596 597 598 #define CreateThread(security, stack_size, fn, param, creation_flags, thread_id) \ 599 rl::rl_CreateThread(security, stack_size, fn, param, creation_flags, thread_id, $) 600 601 #define _beginthreadex(security, stack_size, start_address, arglist, initflag, thrdaddr) \ 602 rl::rl_beginthreadex(security, stack_size, start_address, arglist, initflag, thrdaddr, $) 603 604 #define SetThreadAffinityMask(th, affinity_mask) \ 605 rl::rl_SetThreadAffinityMask(th, affinity_mask, $) 606 607 #define SuspendThread(th) \ 608 rl::rl_SuspendThread(th, $) 609 610 #define ResumeThread(th) \ 611 rl::rl_ResumeThread(th, $) 612 613 #define FlushProcessWriteBuffers() \ 614 rl::rl_FlushProcessWriteBuffers($) 615 616 617 #endif