Reactos
at master 60 lines 1.9 kB view raw
1/* 2 * PROJECT: ReactOS CRT library 3 * LICENSE: CC0-1.0 (https://spdx.org/licenses/CC0-1.0) 4 * PURPOSE: Thread safe initialization support routines for MSVC and Clang-CL 5 * COPYRIGHT: Copyright 2019 Timo Kreuzer (timo.kreuzer@reactos.org) 6 */ 7 8#include <intrin.h> 9 10int _stdcall SwitchToThread(void); 11 12unsigned int _tls_array; 13unsigned int _tls_index; 14long _Init_global_epoch; 15long _Init_thread_epoch; 16 17/* 18 This function tries to acquire a lock on the initialization for the static 19 variable by changing the value saved in *ptss to -1. If *ptss is 0, the 20 variable was not initialized yet and the function tries to set it to -1. 21 If that succeeds, the function will return. If the value is already -1, 22 another thread is in the process of doing the initialization and we 23 wait for it. If it is any other value the initialization is complete. 24 After returning the compiler generated code will check the value: 25 if it is -1 it will continue with the initialization, otherwise the 26 initialization must be complete and will be skipped. 27*/ 28void 29_Init_thread_header(volatile int* ptss) 30{ 31 while (1) 32 { 33 /* Try to acquire the first initialization lock */ 34 int oldTss = _InterlockedCompareExchange((long*)ptss, -1, 0); 35 if (oldTss == -1) 36 { 37 /* Busy, wait for the other thread to do the initialization */ 38 SwitchToThread(); 39 continue; 40 } 41 42 /* Either we acquired the lock and the caller will do the initializaion 43 or the initialization is complete and the caller will skip it */ 44 break; 45 } 46} 47 48void 49_Init_thread_footer(volatile int* ptss) 50{ 51 /* Initialization is complete */ 52 *ptss = _InterlockedIncrement(&_Init_global_epoch); 53} 54 55void 56_Init_thread_abort(volatile int* ptss) 57{ 58 /* Abort the initialization */ 59 _InterlockedAnd((volatile long*)ptss, 0); 60}