180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2008 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <windows.h> 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <intrin.h> 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThread.h" 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTLS.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//MSDN says in order to declare an interlocked function for use as an 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//intrinsic, include intrin.h and put the function in a #pragma intrinsic 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//directive. 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//The pragma appears to be unnecessary, but doesn't hurt. 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma intrinsic(_InterlockedIncrement, _InterlockedExchangeAdd, _InterlockedDecrement) 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#pragma intrinsic(_InterlockedCompareExchange) 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_inc(int32_t* addr) { 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // InterlockedIncrement returns the new value, we want to return the old. 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return _InterlockedIncrement(reinterpret_cast<LONG*>(addr)) - 1; 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_add(int32_t* addr, int32_t inc) { 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return _InterlockedExchangeAdd(reinterpret_cast<LONG*>(addr), 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static_cast<LONG>(inc)); 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_dec(int32_t* addr) { 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return _InterlockedDecrement(reinterpret_cast<LONG*>(addr)) + 1; 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_membar_aquire__after_atomic_dec() { } 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_conditional_inc(int32_t* addr) { 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (true) { 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru LONG value = static_cast<LONG const volatile&>(*addr); 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (value == 0) { 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (_InterlockedCompareExchange(reinterpret_cast<LONG*>(addr), 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru value + 1, 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru value) == value) { 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_membar_aquire__after_atomic_conditional_inc() { } 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex::SkMutex() { 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_COMPILE_ASSERT(sizeof(fStorage) > sizeof(CRITICAL_SECTION), 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NotEnoughSizeForCriticalSection); 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex::~SkMutex() { 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMutex::acquire() { 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMutex::release() { 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////// 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic bool gOnce; 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic DWORD gTlsIndex; 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_DECLARE_STATIC_MUTEX(gMutex); 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid* SkTLS::PlatformGetSpecific(bool forceCreateTheSlot) { 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!forceCreateTheSlot && !gOnce) { 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return NULL; 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!gOnce) { 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMutexAcquire tmp(gMutex); 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!gOnce) { 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gTlsIndex = TlsAlloc(); 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru gOnce = true; 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return TlsGetValue(gTlsIndex); 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkTLS::PlatformSetSpecific(void* ptr) { 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(gOnce); 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (void)TlsSetValue(gTlsIndex, ptr); 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// Call TLS destructors on thread exit. Code based on Chromium's 97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// base/threading/thread_local_storage_win.cc 98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifdef _WIN64 99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma comment(linker, "/INCLUDE:_tls_used") 101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma comment(linker, "/INCLUDE:skia_tls_callback") 102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#else 104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma comment(linker, "/INCLUDE:__tls_used") 106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma comment(linker, "/INCLUDE:_skia_tls_callback") 107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif 109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid NTAPI onTLSCallback(PVOID unused, DWORD reason, PVOID unused2) { 111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if ((DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) && gOnce) { 112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger void* ptr = TlsGetValue(gTlsIndex); 113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if (ptr != NULL) { 114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger SkTLS::Destructor(ptr); 115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger TlsSetValue(gTlsIndex, NULL); 116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger} 119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerextern "C" { 121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#ifdef _WIN64 123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma const_seg(".CRT$XLB") 125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerextern const PIMAGE_TLS_CALLBACK skia_tls_callback; 126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback; 127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma const_seg() 128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#else 130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma data_seg(".CRT$XLB") 132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerPIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback; 133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#pragma data_seg() 134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#endif 136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger} 137