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_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