medfall

A super great game engine
Log | Files | Refs

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