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