1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #include "SkTypes.h" 8 #if defined(SK_BUILD_FOR_WIN32) 9 10 #include "SkTLS.h" 11 #include "SkMutex.h" 12 13 static bool gOnce = false; 14 static DWORD gTlsIndex; 15 SK_DECLARE_STATIC_MUTEX(gMutex); 16 17 void* SkTLS::PlatformGetSpecific(bool forceCreateTheSlot) { 18 if (!forceCreateTheSlot && !gOnce) { 19 return nullptr; 20 } 21 22 if (!gOnce) { 23 SkAutoMutexAcquire tmp(gMutex); 24 if (!gOnce) { 25 gTlsIndex = TlsAlloc(); 26 gOnce = true; 27 } 28 } 29 return TlsGetValue(gTlsIndex); 30 } 31 32 void SkTLS::PlatformSetSpecific(void* ptr) { 33 SkASSERT(gOnce); 34 (void)TlsSetValue(gTlsIndex, ptr); 35 } 36 37 // Call TLS destructors on thread exit. Code based on Chromium's 38 // base/threading/thread_local_storage_win.cc 39 #ifdef _WIN64 40 41 #pragma comment(linker, "/INCLUDE:_tls_used") 42 #pragma comment(linker, "/INCLUDE:skia_tls_callback") 43 44 #else 45 46 #pragma comment(linker, "/INCLUDE:__tls_used") 47 #pragma comment(linker, "/INCLUDE:_skia_tls_callback") 48 49 #endif 50 51 void NTAPI onTLSCallback(PVOID unused, DWORD reason, PVOID unused2) { 52 if ((DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) && gOnce) { 53 void* ptr = TlsGetValue(gTlsIndex); 54 if (ptr != nullptr) { 55 SkTLS::Destructor(ptr); 56 TlsSetValue(gTlsIndex, nullptr); 57 } 58 } 59 } 60 61 extern "C" { 62 63 #ifdef _WIN64 64 65 #pragma const_seg(".CRT$XLB") 66 extern const PIMAGE_TLS_CALLBACK skia_tls_callback; 67 const PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback; 68 #pragma const_seg() 69 70 #else 71 72 #pragma data_seg(".CRT$XLB") 73 PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback; 74 #pragma data_seg() 75 76 #endif 77 } 78 79 #endif//defined(SK_BUILD_FOR_WIN32) 80