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
PlatformGetSpecific(bool forceCreateTheSlot)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
PlatformSetSpecific(void * ptr)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
onTLSCallback(PVOID unused,DWORD reason,PVOID unused2)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