text: /*  Relacy Race Detector
   *  Copyright (c) 2008-2010, Dmitry S. Vyukov
   *  All rights reserved.
   *  This software is provided AS-IS with no warranty, either express or implied.
   *  This software is distributed under a license and may not be copied,
   *  modified or distributed except as expressly authorized under the
   *  terms of the license contained in the file LICENSE.TXT in this distribution.
   */
  
  #ifndef RL_WINDOWS_HPP
  #define RL_WINDOWS_HPP
  #ifdef _MSC_VER
  #   pragma once
  #endif
  
  #include "mutex.hpp"
  #include "condition_variable.hpp"
  #include "semaphore.hpp"
  #include "event.hpp"
  
  
  namespace rl {
  
  typedef win_object* rl_HANDLE;
  unsigned long const rl_INFINITE = (unsigned long) -1;
  
  unsigned long const rl_WAIT_FAILED = (unsigned long) -1;
  unsigned long const rl_WAIT_OBJECT_0 = 100;
  unsigned long const rl_WAIT_TIMEOUT = 1;
  unsigned long const rl_WAIT_IO_COMPLETION = 2;
  unsigned long const rl_MAXIMUM_WAIT_OBJECTS = wfmo_max_objects;
  
  
  inline int rl_SwitchToThread(debug_info_param info) {
    yield(1, info);
    return 1;
  }
  
  inline void rl_Sleep(unsigned long milliseconds, debug_info_param info) {
    yield(milliseconds ? milliseconds : 1, info);
  }
  
  
  inline unsigned long
  rl_WaitForSingleObjectEx(rl_HANDLE obj, unsigned long timeout, int alertable, debug_info_param info) {
    (void) alertable; //!!! not yet supported � support it!
    //!!! support WAIT_IO_COMPLETION
    RL_VERIFY(false == alertable && "Alertable wait is not supported in WaitForSingleObject() yet");
  
    bool try_wait = (timeout == 0);
    bool is_timed = (timeout != rl_INFINITE);
    sema_wakeup_reason reason = static_cast<win_waitable_object*>(obj)->wait(try_wait, is_timed, info);
    if (reason == sema_wakeup_reason_success)
      return rl_WAIT_OBJECT_0;
    else if (reason == sema_wakeup_reason_timeout)
      return rl_WAIT_TIMEOUT;
    else if (reason == sema_wakeup_reason_failed)
      return rl_WAIT_TIMEOUT;
    RL_VERIFY(false);
    return rl_WAIT_FAILED;
  }
  
  inline unsigned long rl_WaitForSingleObject(rl_HANDLE obj, unsigned long timeout, debug_info_param info) {
    return rl_WaitForSingleObjectEx(obj, timeout, 0, info);
  }
  
  inline unsigned long
  rl_WaitForMultipleObjectsEx(unsigned long count, rl_HANDLE* objects, int wait_all, unsigned long timeout, int alertable,
                              debug_info_param info) {
    (void) alertable; //!!!
    //!!! support WAIT_IO_COMPLETION
    RL_VERIFY(false == alertable && "Alertable wait is not supported in WaitForMultipleObjects() yet");
  
    bool try_wait = (timeout == 0);
    bool is_timed = (timeout != rl_INFINITE);
    win_waitable_object** obj = reinterpret_cast<win_waitable_object**>(objects);
    size_t signaled = 0;
    sema_wakeup_reason reason = wait_for_multiple_objects(signaled, count, obj, !!wait_all, try_wait, is_timed, info);
    if (reason == sema_wakeup_reason_success)
      return rl_WAIT_OBJECT_0 + (int) signaled;
    else if (reason == sema_wakeup_reason_timeout)
      return rl_WAIT_TIMEOUT;
    RL_VERIFY(false);
    return rl_WAIT_FAILED;
  }
  
  inline unsigned long
  rl_WaitForMultipleObjects(unsigned long count, rl_HANDLE* objects, int wait_all, unsigned long timeout,
                            debug_info_param info) {
    return rl_WaitForMultipleObjectsEx(count, objects, wait_all, timeout, 0, info);
  }
  
  inline unsigned long rl_SignalObjectAndWait(rl_HANDLE obj_to_signal,
                                              rl_HANDLE obj_to_wait,
                                              unsigned long timeout,
                                              int alertable,
                                              debug_info_param info) {
    bool result = static_cast<win_waitable_object*>(obj_to_signal)->signal(info);
    if (false == result)
      return result ? 1 : 0;
    preemption_disabler pd(ctx());
    return rl_WaitForSingleObjectEx(obj_to_wait, timeout, alertable, info);
  }
  
  
  struct sem_tag_win;
  
  inline rl_HANDLE rl_CreateSemaphore(void* /*security*/, long initial_count, long max_count, void const* /*name*/,
                                      debug_info_param info) {
    void* mem = ctx().alloc(sizeof(semaphore<sem_tag_win>), false, info);
    semaphore<sem_tag_win>* sema = new(mem) semaphore<sem_tag_win>;
    sema->init(false, initial_count, max_count, info);
    return sema;
  }
  
  inline int rl_CloseHandle(rl_HANDLE h, debug_info_param info) {
    h->deinit(info);
    h->~win_object();
    (ctx().free)(h, false, info); //!!! rename free because of the define
    return 1;
  }
  
  inline int rl_ReleaseSemaphore(rl_HANDLE sema, long count, long* prev_count, debug_info_param info) {
    unsigned prev = 0;
    bool result = static_cast<semaphore<sem_tag_win>*>(sema)->post(count, prev, info);
    if (prev_count)
      prev_count[0] = prev;
    return result ? 1 : 0;
  }
  
  
  inline rl_HANDLE
  rl_CreateEvent(void* /*security*/, int manual_reset, int initial_state, void const* /*name*/, debug_info_param info) {
    void* mem = ctx().alloc(sizeof(generic_event), false, info);
    generic_event* ev = new(mem) generic_event;
    ev->init(!!manual_reset, !!initial_state, info);
    return ev;
  }
  
  inline int rl_SetEvent(rl_HANDLE ev, debug_info_param info) {
    static_cast<generic_event*>(ev)->set(info);
    return 1;
  }
  
  inline int rl_ResetEvent(rl_HANDLE ev, debug_info_param info) {
    static_cast<generic_event*>(ev)->reset(info);
    return 1;
  }
  
  inline int rl_PulseEvent(rl_HANDLE ev, debug_info_param info) {
    static_cast<generic_event*>(ev)->pulse(info);
    return 1;
  }
  
  
  struct mutex_tag_win_cs;
  typedef generic_mutex<mutex_tag_win_cs> rl_CRITICAL_SECTION;
  
  inline void rl_InitializeCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) {
    m->init(false, true, false, false, info);
  }
  
  inline int
  rl_InitializeCriticalSectionAndSpinCount(rl_CRITICAL_SECTION* m, unsigned long spin_count, debug_info_param info) {
    (void) spin_count;
    m->init(false, true, false, false, info);
    return 1;
  }
  
  inline int rl_InitializeCriticalSectionEx(rl_CRITICAL_SECTION* m, unsigned long spin_count, unsigned long flags,
                                            debug_info_param info) {
    (void) spin_count;
    (void) flags;
    m->init(false, true, false, false, info);
    return 1;
  }
  
  inline void rl_DeleteCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) {
    m->deinit(info);
  }
  
  inline void rl_EnterCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) {
    m->lock_exclusive(info);
  }
  
  inline int rl_TryEnterCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) {
    return m->try_lock_exclusive(info) ? 1 : 0;
  }
  
  inline void rl_LeaveCriticalSection(rl_CRITICAL_SECTION* m, debug_info_param info) {
    m->unlock_exclusive(info);
  }
  
  struct mutex_tag_win_srwl;
  typedef generic_mutex<mutex_tag_win_srwl> rl_SRWLOCK;
  
  inline void rl_InitializeSRWLock(rl_SRWLOCK* lock, debug_info_param info) {
    lock->init(true, false, false, false, info);
  }
  
  inline void rl_AcquireSRWLockExclusive(rl_SRWLOCK* lock, debug_info_param info) {
    lock->lock_exclusive(info);
  }
  
  inline void rl_AcquireSRWLockShared(rl_SRWLOCK* lock, debug_info_param info) {
    lock->lock_shared(info);
  }
  
  inline void rl_ReleaseSRWLockExclusive(rl_SRWLOCK* lock, debug_info_param info) {
    lock->unlock_exclusive(info);
  }
  
  inline void rl_ReleaseSRWLockShared(rl_SRWLOCK* lock, debug_info_param info) {
    lock->unlock_shared(info);
  }
  
  //!!!
  inline void rl_DeleteSRWLock(rl_SRWLOCK* lock, debug_info_param info) {
    lock->deinit(info);
  }
  
  
  struct mutex_tag_win_mutex;
  typedef generic_mutex<mutex_tag_win_mutex> rl_win_mutex;
  
  
  inline rl_HANDLE rl_CreateMutex(void* /*security*/, int initial_owner, void const* /*name*/, debug_info_param info) {
    void* mem = ctx().alloc(sizeof(rl_win_mutex), false, info);
    rl_win_mutex* mtx = new(mem) rl_win_mutex();
    mtx->init(false, true, false, false, info);
    if (initial_owner)
      mtx->lock_exclusive(info);
    return mtx;
  }
  
  inline int rl_ReleaseMutex(rl_HANDLE mtx, debug_info_param info) {
    static_cast<rl_win_mutex*>(mtx)->unlock_exclusive(info);
    return 1;
  
  }
  
  
  struct condvar_tag_win;
  typedef condvar<condvar_tag_win> rl_CONDITION_VARIABLE;
  unsigned long const rl_CONDITION_VARIABLE_LOCKMODE_SHARED = 1;
  
  inline void rl_InitializeConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) {
    cv->init(false, info);
  }
  
  inline int rl_SleepConditionVariableCS(rl_CONDITION_VARIABLE* cv, rl_CRITICAL_SECTION* cs, unsigned long ms,
                                         debug_info_param info) {
    cv->wait(*cs, ms != rl_INFINITE, info);
    return 0;
  }
  
  inline int
  rl_SleepConditionVariableSRW(rl_CONDITION_VARIABLE* cv, rl_SRWLOCK* lock, unsigned long ms, unsigned long flags,
                               debug_info_param info) {
    //!!! CONDITION_VARIABLE_LOCKMODE_SHARED
    (void) flags;
    cv->wait(*lock, ms != rl_INFINITE, info);
    return 0;
  }
  
  inline void rl_WakeAllConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) {
    cv->notify_all(info);
  }
  
  inline void rl_WakeConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) {
    cv->notify_one(info);
  }
  
  inline void rl_DeleteConditionVariable(rl_CONDITION_VARIABLE* cv, debug_info_param info) {
    cv->deinit(info);
  }
  
  
  typedef unsigned long (RL_STDCALL* rl_WIN_START_ROUTINE)(void* param);
  
  typedef unsigned (RL_STDCALL* rl_MSVCR_THREAD_ROUTINE)(void* param);
  
  template<typename thread_fn_t>
  struct win32_thread_helper {
    thread_fn_t fn;
    void* param;
  
    static void* thread(void* p) {
      win32_thread_helper* self = (win32_thread_helper*) p;
      void* result = (void*) (uintptr_t)(self->fn(self->param));
      delete_impl(self, $);
      return result;
    }
  };
  
  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) {
    (void) security;
    (void) stack_size;
    (void) creation_flags;
    (void) thread_id;
  
    void* mem =
        ctx().alloc(sizeof(win32_thread_helper<rl_WIN_START_ROUTINE>), false, info);
    win32_thread_helper<rl_WIN_START_ROUTINE>* arg =
        new(mem) win32_thread_helper<rl_WIN_START_ROUTINE>;
    arg->fn = fn;
    arg->param = param;
    win_waitable_object* handle = ctx().create_thread(&win32_thread_helper<rl_WIN_START_ROUTINE>::thread, arg);
    return handle;
  }
  
  
  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) {
    (void) security;
    (void) stack_size;
    (void) initflag;
    (void) thrdaddr;
  
    void* mem = ctx().alloc(sizeof(win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>), false, info);
    win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>* arg =
        new(mem) win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>;
    arg->fn = start_address;
    arg->param = arglist;
    win_waitable_object* handle = ctx().create_thread(&win32_thread_helper<rl_MSVCR_THREAD_ROUTINE>::thread, arg);
    return (uintptr_t) handle;
  }
  
  inline unsigned long rl_SetThreadAffinityMask(rl_HANDLE th, unsigned long affinity_mask, debug_info_param info) {
    (void) (th);
    (void) (affinity_mask);
    (void) info;
    return 0;
  }
  
  inline int rl_SuspendThread(rl_HANDLE th, debug_info_param info) {
    (void) th;
    (void) info;
    return 1;
  }
  
  inline int rl_ResumeThread(rl_HANDLE th, debug_info_param info) {
    (void) th;
    (void) info;
    return 1;
  }
  
  inline unsigned long GetLastError() {
    return (unsigned long) get_errno();
  }
  
  inline void SetLastError(unsigned long value) {
    set_errno((int) value);
  }
  
  inline void rl_FlushProcessWriteBuffers(debug_info_param info) {
    systemwide_fence(info);
  }
  
  }
  
  
  #ifdef HANDLE
  #   undef HANDLE
  #endif
  #define HANDLE rl::rl_HANDLE
  
  #ifdef INFINITE
  #   undef INFINITE
  #endif
  #define INFINITE rl::rl_INFINITE
  
  
  #ifdef WAIT_FAILED
  #   undef WAIT_FAILED
  #endif
  #define WAIT_FAILED rl::rl_WAIT_FAILED
  
  #ifdef WAIT_OBJECT_0
  #   undef WAIT_OBJECT_0
  #endif
  #define WAIT_OBJECT_0 rl::rl_WAIT_OBJECT_0
  
  #ifdef WAIT_TIMEOUT
  #   undef WAIT_TIMEOUT
  #endif
  #define WAIT_TIMEOUT rl::rl_WAIT_TIMEOUT
  
  #ifdef WAIT_IO_COMPLETION
  #   undef WAIT_IO_COMPLETION
  #endif
  #define WAIT_IO_COMPLETION rl::rl_WAIT_IO_COMPLETION
  
  #ifdef MAXIMUM_WAIT_OBJECTS
  #   undef MAXIMUM_WAIT_OBJECTS
  #endif
  #define MAXIMUM_WAIT_OBJECTS rl::rl_MAXIMUM_WAIT_OBJECTS
  
  
  #define SwitchToThread() \
   rl::rl_SwitchToThread($)
  
  #define Sleep(milliseconds) \
   rl::rl_Sleep(milliseconds, $)
  
  
  #define CloseHandle(obj) \
   rl::rl_CloseHandle(obj, $)
  
  #define WaitForSingleObject(obj, timeout) \
   rl::rl_WaitForSingleObject(obj, timeout, $)
  
  #define WaitForMultipleObjects(count, objects, wait_all, timeout) \
   rl::rl_WaitForMultipleObjects(count, objects, wait_all, timeout, $)
  
  #define WaitForMultipleObjectsEx(count, objects, wait_all, timeout, alertable)] \
   rl::rl_WaitForMultipleObjectsEx(count, objects, wait_all, timeout, alertable, $)
  
  #define SignalObjectAndWait(obj_to_signal, obj_to_wait, timeout, alertable) \
   rl::rl_SignalObjectAndWait(obj_to_signal, obj_to_wait, timeout, alertable, $)
  
  #ifdef CreateSemaphore
  #   undef CreateSemaphore
  #endif
  
  #ifdef CreateSemaphore
  #   undef ReleaseSemaphore
  #endif
  
  #define CreateSemaphoreA rl_CreateSemaphore
  #define CreateSemaphoreW rl_CreateSemaphore
  #define CreateSemaphore rl_CreateSemaphore
  #define rl_CreateSemaphore(security, initial_count, max_count, name) \
      rl::rl_CreateSemaphore(security, initial_count, max_count, name, $)\
  
  #define ReleaseSemaphore(sema, count, prev_count) \
   rl::rl_ReleaseSemaphore(sema, count, prev_count, $)
  
  
  #ifdef CreateEvent
  #   undef CreateEvent
  #endif
  #define CreateEventA rl_CreateEvent
  #define CreateEventW rl_CreateEvent
  #define CreateEvent rl_CreateEvent
  #define rl_CreateEvent(security, manual_reset, initial_state, name)\
      rl::rl_CreateEvent(security, manual_reset, initial_state, name, $)
  
  #define SetEvent(ev)\
   rl::rl_SetEvent(ev, $)
  
  #define ResetEvent(ev)\
   rl::rl_ResetEvent(ev, $)
  
  #define PulseEvent(ev)\
   rl::rl_PulseEvent(ev, $)
  
  
  #ifdef CreateMutex
  #   undef CreateMutex
  #endif
  #define CreateMutexA rl_CreateMutex
  #define CreateMutexW rl_CreateMutex
  #define CreateMutex rl_CreateMutex
  #define rl_CreateMutex(security, initial_owner, name)\
      rl::rl_CreateMutex(security, initial_owner, name, $)
  
  #define ReleaseMutex(mtx)\
   rl::rl_ReleaseMutex(mtx, $)
  
  
  #define CRITICAL_SECTION rl::rl_CRITICAL_SECTION
  
  #define InitializeCriticalSection(cs) \
   rl::rl_InitializeCriticalSection(cs, $)
  
  #define InitializeCriticalSectionAndSpinCount(cs, spin) \
   rl::rl_InitializeCriticalSectionAndSpinCount(cs, spin, $)
  
  #define InitializeCriticalSectionEx(cs, spin, flags) \
   rl::rl_InitializeCriticalSectionEx(cs, spin, flags, $)
  
  #define DeleteCriticalSection(cs) \
   rl::rl_DeleteCriticalSection(cs, $)
  
  #define EnterCriticalSection(cs) \
   rl::rl_EnterCriticalSection(cs, $)
  
  #define TryEnterCriticalSection(cs) \
   rl::rl_TryEnterCriticalSection(cs, $)
  
  #define LeaveCriticalSection(cs) \
   rl::rl_LeaveCriticalSection(cs, $)
  
  
  #define SRWLOCK rl::rl_SRWLOCK
  
  #define InitializeSRWLock(lock) \
   rl::rl_InitializeSRWLock(lock, $)
  
  #define AcquireSRWLockExclusive(lock) \
   rl::rl_AcquireSRWLockExclusive(lock, $)
  
  #define AcquireSRWLockShared(lock) \
   rl::rl_AcquireSRWLockShared(lock, $)
  
  #define ReleaseSRWLockExclusive(lock) \
   rl::rl_ReleaseSRWLockExclusive(lock, $)
  
  #define ReleaseSRWLockShared(lock) \
   rl::rl_ReleaseSRWLockShared(lock, $)
  
  //!!! no such function in WIN API
  #define DeleteSRWLock(lock) \
   rl::rl_DeleteSRWLock(lock, $)
  
  
  #define CONDITION_VARIABLE rl::rl_CONDITION_VARIABLE
  
  #ifdef CONDITION_VARIABLE_LOCKMODE_SHARED
  #   undef CONDITION_VARIABLE_LOCKMODE_SHARED
  #endif
  #define CONDITION_VARIABLE_LOCKMODE_SHARED rl::rl_CONDITION_VARIABLE_LOCKMODE_SHARED
  
  #define InitializeConditionVariable(cv) \
   rl::rl_InitializeConditionVariable(cv, $)
  
  #define SleepConditionVariableCS(cv, cs, ms) \
   rl::rl_SleepConditionVariableCS(cv, cs, ms, $)
  
  #define SleepConditionVariableSRW(cv, lock, ms, flags) \
   rl::rl_SleepConditionVariableSRW(cv, lock, ms, flags, $)
  
  #define WakeAllConditionVariable(cv) \
   rl::rl_WakeAllConditionVariable(cv, $)
  
  #define WakeConditionVariable(cv) \
   rl::rl_WakeConditionVariable(cv, $)
  
  //!!! no such function in WIN API
  #define DeleteConditionVariable(cv) \
   rl::rl_DeleteConditionVariable(cv, $)
  
  
  #define CreateThread(security, stack_size, fn, param, creation_flags, thread_id) \
   rl::rl_CreateThread(security, stack_size, fn, param, creation_flags, thread_id, $)
  
  #define _beginthreadex(security, stack_size, start_address, arglist, initflag, thrdaddr) \
    rl::rl_beginthreadex(security, stack_size, start_address, arglist, initflag, thrdaddr, $)
  
  #define SetThreadAffinityMask(th, affinity_mask) \
   rl::rl_SetThreadAffinityMask(th, affinity_mask, $)
  
  #define SuspendThread(th) \
   rl::rl_SuspendThread(th, $)
  
  #define ResumeThread(th) \
   rl::rl_ResumeThread(th, $)
  
  #define FlushProcessWriteBuffers() \
   rl::rl_FlushProcessWriteBuffers($)
  
  
  #endif
  