medfall

A super great game engine
Log | Files | Refs

platform.hpp (5468B)


      1 /*  Relacy Race Detector
      2  *  Copyright (c) 2008-2013, 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 in this distribution.
      8  */
      9 
     10 #ifndef RL_PLATFORM_HPP
     11 #define RL_PLATFORM_HPP
     12 #ifdef _MSC_VER
     13 #   pragma once
     14 #endif
     15 
     16 #include "pch.hpp"
     17 
     18 
     19 #if defined(RL_WIN) || defined(_CYGWIN)
     20 
     21 typedef void* fiber_t;
     22 
     23 inline unsigned get_tick_count()
     24 {
     25     return GetTickCount();
     26 }
     27 
     28 inline void set_low_thread_prio()
     29 {
     30     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
     31 }
     32 
     33 inline void create_main_fiber(fiber_t& fib)
     34 {
     35     fib = ConvertThreadToFiber(0);
     36     if (0 == fib)
     37     {
     38         unsigned long err = ::GetLastError(); (void)err;
     39         throw std::logic_error("you must start simulation inside a thread (not a fiber)");
     40     }
     41 }
     42 
     43 inline void delete_main_fiber(fiber_t& fib)
     44 {
     45     (void)fib;
     46     HMODULE lib = LoadLibraryW(L"kernel32.dll");
     47     if (lib)
     48     {
     49         void* proc = (void*)GetProcAddress(lib, "ConvertFiberToThread");
     50         if (proc)
     51         {
     52             typedef BOOL (WINAPI * ConvertFiberToThreadT)();
     53             ConvertFiberToThreadT ConvertFiberToThread = (ConvertFiberToThreadT)proc;
     54             ConvertFiberToThread();
     55         }
     56         FreeLibrary(lib);
     57     }
     58 }
     59 
     60 inline void create_fiber(fiber_t& fib, void(*fiber_proc)(void*), void* ctx)
     61 {
     62     size_t const stack_size = 64*1024;
     63     fib = CreateFiberEx(4*1024, stack_size, 0, (LPFIBER_START_ROUTINE)fiber_proc, ctx);
     64     if (fib == 0)
     65         throw std::runtime_error("error creating fiber");
     66 }
     67 
     68 inline void delete_fiber(fiber_t& fib)
     69 {
     70     DeleteFiber(fib);
     71 }
     72 
     73 inline void switch_to_fiber(fiber_t fib, fiber_t)
     74 {
     75     SwitchToFiber(fib);
     76 }
     77 
     78 // work-around for some versions of cygwin
     79 extern "C" inline int __gxx_personality_v0()
     80 {
     81     return 0;
     82 }
     83 
     84 #ifdef RL_WIN
     85 #else
     86 
     87 /*
     88 inline unsigned get_tick_count()
     89 {
     90     return GetTickCount();
     91 }
     92 
     93 typedef void* fiber_t;
     94 
     95 struct ucontext_t
     96 {
     97     struct stack_t
     98     {
     99         void* ss_sp;
    100         size_t ss_size;
    101     };
    102     stack_t uc_stack;
    103     void* uc_link;
    104 
    105 };
    106 void getcontext(void*) {}
    107 void makecontext(void*, void(*)(), int, void*) {}
    108 void swapcontext(void*, void*) {}
    109 
    110 */
    111 
    112 #endif
    113 
    114 #else
    115 
    116 inline unsigned get_tick_count()
    117 {
    118     struct tms tms;
    119     return ((unsigned)(times (&tms) * (1000 / sysconf(_SC_CLK_TCK))));
    120 }
    121 
    122 inline void set_low_thread_prio()
    123 {
    124 }
    125 
    126 #if 0
    127 
    128 typedef ucontext_t fiber_t;
    129 
    130 inline void create_main_fiber(fiber_t& fib)
    131 {
    132     ucontext_t f = {};
    133     fib = f;
    134 }
    135 
    136 inline void delete_main_fiber(fiber_t& fib)
    137 {
    138     (void)fib;
    139 }
    140 
    141 inline void create_fiber(fiber_t& fib, void(*fiber_proc)(void*), void* ctx)
    142 {
    143     size_t const stack_size = 64*1024;
    144     getcontext(&fib);
    145     fib.uc_stack.ss_sp = (::malloc)(stack_size);
    146     fib.uc_stack.ss_size = stack_size;
    147     fib.uc_link = 0;
    148     typedef void(*fn_t)();
    149     fn_t fn = (fn_t)fiber_proc;
    150     makecontext(&fib, fn, 1, ctx);
    151 }
    152 
    153 inline void delete_fiber(fiber_t& fib)
    154 {
    155     //(::free)(fib.uc_stack.ss_sp);
    156 }
    157 
    158 inline void switch_to_fiber(fiber_t& fib, fiber_t& prev)
    159 {
    160     swapcontext(&prev, &fib);
    161 }
    162 
    163 #else
    164 
    165 struct fiber_t
    166 {
    167     ucontext_t  fib;
    168     jmp_buf     jmp;
    169 };
    170 
    171 struct fiber_ctx_t
    172 {
    173     void(*      fnc)(void*);
    174     void*       ctx;
    175     jmp_buf*    cur;
    176     ucontext_t* prv;
    177 };
    178 
    179 static void fiber_start_fnc(void* p)
    180 {
    181     fiber_ctx_t* ctx = (fiber_ctx_t*)p;
    182     void (*volatile ufnc)(void*) = ctx->fnc;
    183     void* volatile uctx = ctx->ctx;
    184     if (_setjmp(*ctx->cur) == 0)
    185     {
    186         ucontext_t tmp;
    187         swapcontext(&tmp, ctx->prv);
    188     }
    189     ufnc(uctx);
    190 }
    191 
    192 inline void create_main_fiber(fiber_t& fib)
    193 {
    194     memset(&fib, 0, sizeof(fib));
    195 }
    196 
    197 inline void delete_main_fiber(fiber_t& fib)
    198 {
    199     (void)fib;
    200 }
    201 
    202 inline void create_fiber(fiber_t& fib, void(*ufnc)(void*), void* uctx)
    203 {
    204     size_t const stack_size = 64*1024;
    205     getcontext(&fib.fib);
    206     fib.fib.uc_stack.ss_sp = (::malloc)(stack_size);
    207     fib.fib.uc_stack.ss_size = stack_size;
    208     fib.fib.uc_link = 0;
    209     ucontext_t tmp;
    210     fiber_ctx_t ctx = {ufnc, uctx, &fib.jmp, &tmp};
    211     makecontext(&fib.fib, (void(*)())fiber_start_fnc, 1, &ctx);
    212     swapcontext(&tmp, &fib.fib);
    213 }
    214 
    215 inline void delete_fiber(fiber_t& fib)
    216 {
    217     //(::free)(fib.uc_stack.ss_sp);
    218 }
    219 
    220 inline void switch_to_fiber(fiber_t& fib, fiber_t& prv)
    221 {
    222     if (_setjmp(prv.jmp) == 0)
    223         _longjmp(fib.jmp, 1);
    224 }
    225 
    226 #endif
    227 
    228 #endif
    229 
    230 
    231 
    232 #ifdef _MSC_VER
    233     typedef unsigned __int64 uint64_t;
    234 #   define RL_INLINE __forceinline
    235 #   define RL_NOINLINE __declspec(noinline)
    236 #   define RL_STRINGIZE(text) RL_STRINGIZE_A((text))
    237 #   define RL_STRINGIZE_I(text) #text
    238 #   define RL_STRINGIZE_A(arg) RL_STRINGIZE_I arg
    239 #   define RL_STDCALL __stdcall
    240 #   define RL_THROW_SPEC(ex)
    241 #else
    242 #   define RL_INLINE inline
    243 #   define RL_NOINLINE
    244 #   define RL_STRINGIZE_I(text) #text
    245 #   define RL_STRINGIZE(text) RL_STRINGIZE_I(text)
    246 #   define RL_STDCALL
    247 #   define RL_THROW_SPEC(ex) throw(ex)
    248 #endif
    249 
    250 
    251 #if defined (_MSC_VER) && (_MSC_VER >= 1400)
    252 #   define RL_RESTRICT __restrict
    253 #else
    254 #   define RL_RESTRICT
    255 #endif
    256 
    257 
    258 
    259 #endif