blob: 91a5ceb7ec34e03a8a8109a92e340242cd7302e9 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2008 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
10#include <windows.h>
bungeman@google.comeee66612012-02-17 22:00:07 +000011#include <intrin.h>
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkThread.h"
reed@google.com48ca7e32012-05-07 20:23:27 +000013#include "SkTLS.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014
bungeman@google.comeee66612012-02-17 22:00:07 +000015//MSDN says in order to declare an interlocked function for use as an
16//intrinsic, include intrin.h and put the function in a #pragma intrinsic
17//directive.
18//The pragma appears to be unnecessary, but doesn't hurt.
scroggo@google.com50ccb0a2012-07-16 16:51:28 +000019#pragma intrinsic(_InterlockedIncrement, _InterlockedExchangeAdd, _InterlockedDecrement)
bungeman@google.coma02bc152012-05-16 18:21:56 +000020#pragma intrinsic(_InterlockedCompareExchange)
bungeman@google.comeee66612012-02-17 22:00:07 +000021
reed@google.comdcbd6e32012-01-12 15:21:16 +000022int32_t sk_atomic_inc(int32_t* addr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000023 // InterlockedIncrement returns the new value, we want to return the old.
bungeman@google.comeee66612012-02-17 22:00:07 +000024 return _InterlockedIncrement(reinterpret_cast<LONG*>(addr)) - 1;
reed@android.com8a1c16f2008-12-17 15:59:43 +000025}
26
scroggo@google.com50ccb0a2012-07-16 16:51:28 +000027int32_t sk_atomic_add(int32_t* addr, int32_t inc) {
28 return _InterlockedExchangeAdd(reinterpret_cast<LONG*>(addr),
29 static_cast<LONG>(inc));
30}
31
reed@google.comdcbd6e32012-01-12 15:21:16 +000032int32_t sk_atomic_dec(int32_t* addr) {
bungeman@google.comeee66612012-02-17 22:00:07 +000033 return _InterlockedDecrement(reinterpret_cast<LONG*>(addr)) + 1;
reed@android.com8a1c16f2008-12-17 15:59:43 +000034}
bungeman@google.coma02bc152012-05-16 18:21:56 +000035void sk_membar_aquire__after_atomic_dec() { }
36
37int32_t sk_atomic_conditional_inc(int32_t* addr) {
38 while (true) {
39 LONG value = static_cast<LONG const volatile&>(*addr);
40 if (value == 0) {
41 return 0;
42 }
43 if (_InterlockedCompareExchange(reinterpret_cast<LONG*>(addr),
44 value + 1,
45 value) == value) {
46 return value;
47 }
48 }
49}
50void sk_membar_aquire__after_atomic_conditional_inc() { }
reed@android.com8a1c16f2008-12-17 15:59:43 +000051
reed@google.comdcbd6e32012-01-12 15:21:16 +000052SkMutex::SkMutex() {
vandebo@chromium.org28be72b2010-11-11 21:37:00 +000053 SK_COMPILE_ASSERT(sizeof(fStorage) > sizeof(CRITICAL_SECTION),
54 NotEnoughSizeForCriticalSection);
reed@android.com8a1c16f2008-12-17 15:59:43 +000055 InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
56}
57
reed@google.comdcbd6e32012-01-12 15:21:16 +000058SkMutex::~SkMutex() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
60}
61
reed@google.comdcbd6e32012-01-12 15:21:16 +000062void SkMutex::acquire() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
64}
65
reed@google.comdcbd6e32012-01-12 15:21:16 +000066void SkMutex::release() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&fStorage));
68}
69
reed@google.com48ca7e32012-05-07 20:23:27 +000070///////////////////////////////////////////////////////////////////////////
71
72static bool gOnce;
73static DWORD gTlsIndex;
74SK_DECLARE_STATIC_MUTEX(gMutex);
75
reed@google.com331e2dc2012-05-08 21:45:03 +000076void* SkTLS::PlatformGetSpecific(bool forceCreateTheSlot) {
77 if (!forceCreateTheSlot && !gOnce) {
78 return NULL;
79 }
80
reed@google.com48ca7e32012-05-07 20:23:27 +000081 if (!gOnce) {
82 SkAutoMutexAcquire tmp(gMutex);
reed@google.com331e2dc2012-05-08 21:45:03 +000083 if (!gOnce) {
84 gTlsIndex = TlsAlloc();
85 gOnce = true;
86 }
reed@google.com48ca7e32012-05-07 20:23:27 +000087 }
88 return TlsGetValue(gTlsIndex);
89}
90
91void SkTLS::PlatformSetSpecific(void* ptr) {
92 SkASSERT(gOnce);
93 (void)TlsSetValue(gTlsIndex, ptr);
94}
95