1 /* 2 * Copyright 2008 The Android Open Source Project 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 8 #include <windows.h> 9 #include <intrin.h> 10 #include "SkThread.h" 11 12 //MSDN says in order to declare an interlocked function for use as an 13 //intrinsic, include intrin.h and put the function in a #pragma intrinsic 14 //directive. 15 //The pragma appears to be unnecessary, but doesn't hurt. 16 #pragma intrinsic(_InterlockedIncrement, _InterlockedExchangeAdd, _InterlockedDecrement) 17 #pragma intrinsic(_InterlockedCompareExchange) 18 19 int32_t sk_atomic_inc(int32_t* addr) { 20 // InterlockedIncrement returns the new value, we want to return the old. 21 return _InterlockedIncrement(reinterpret_cast<LONG*>(addr)) - 1; 22 } 23 24 int32_t sk_atomic_add(int32_t* addr, int32_t inc) { 25 return _InterlockedExchangeAdd(reinterpret_cast<LONG*>(addr), 26 static_cast<LONG>(inc)); 27 } 28 29 int32_t sk_atomic_dec(int32_t* addr) { 30 return _InterlockedDecrement(reinterpret_cast<LONG*>(addr)) + 1; 31 } 32 void sk_membar_aquire__after_atomic_dec() { } 33 34 int32_t sk_atomic_conditional_inc(int32_t* addr) { 35 while (true) { 36 LONG value = static_cast<int32_t const volatile&>(*addr); 37 if (value == 0) { 38 return 0; 39 } 40 if (_InterlockedCompareExchange(reinterpret_cast<LONG*>(addr), 41 value + 1, 42 value) == value) { 43 return value; 44 } 45 } 46 } 47 void sk_membar_aquire__after_atomic_conditional_inc() { } 48 49 SkMutex::SkMutex() { 50 SK_COMPILE_ASSERT(sizeof(fStorage) > sizeof(CRITICAL_SECTION), 51 NotEnoughSizeForCriticalSection); 52 InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 53 } 54 55 SkMutex::~SkMutex() { 56 DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 57 } 58 59 void SkMutex::acquire() { 60 EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 61 } 62 63 void SkMutex::release() { 64 LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage)); 65 } 66