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_WIN)
9
10 #include "SkLeanWindows.h"
11 #include "SkMutex.h"
12 #include "SkTLS.h"
13
14 static bool gOnce = false;
15 static DWORD gTlsIndex;
16 SK_DECLARE_STATIC_MUTEX(gMutex);
17
PlatformGetSpecific(bool forceCreateTheSlot)18 void* SkTLS::PlatformGetSpecific(bool forceCreateTheSlot) {
19 if (!forceCreateTheSlot && !gOnce) {
20 return nullptr;
21 }
22
23 if (!gOnce) {
24 SkAutoMutexAcquire tmp(gMutex);
25 if (!gOnce) {
26 gTlsIndex = TlsAlloc();
27 gOnce = true;
28 }
29 }
30 return TlsGetValue(gTlsIndex);
31 }
32
PlatformSetSpecific(void * ptr)33 void SkTLS::PlatformSetSpecific(void* ptr) {
34 SkASSERT(gOnce);
35 (void)TlsSetValue(gTlsIndex, ptr);
36 }
37
38 // Call TLS destructors on thread exit. Code based on Chromium's
39 // base/threading/thread_local_storage_win.cc
40 #ifdef _WIN64
41
42 #pragma comment(linker, "/INCLUDE:_tls_used")
43 #pragma comment(linker, "/INCLUDE:skia_tls_callback")
44
45 #else
46
47 #pragma comment(linker, "/INCLUDE:__tls_used")
48 #pragma comment(linker, "/INCLUDE:_skia_tls_callback")
49
50 #endif
51
onTLSCallback(PVOID unused,DWORD reason,PVOID unused2)52 void NTAPI onTLSCallback(PVOID unused, DWORD reason, PVOID unused2) {
53 if ((DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) && gOnce) {
54 void* ptr = TlsGetValue(gTlsIndex);
55 if (ptr != nullptr) {
56 SkTLS::Destructor(ptr);
57 TlsSetValue(gTlsIndex, nullptr);
58 }
59 }
60 }
61
62 extern "C" {
63
64 #ifdef _WIN64
65
66 #pragma const_seg(".CRT$XLB")
67 extern const PIMAGE_TLS_CALLBACK skia_tls_callback;
68 const PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback;
69 #pragma const_seg()
70
71 #else
72
73 #pragma data_seg(".CRT$XLB")
74 PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback;
75 #pragma data_seg()
76
77 #endif
78 }
79
80 #endif//defined(SK_BUILD_FOR_WIN)
81