Home | History | Annotate | Download | only in ports
      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 
     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 
     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 
     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