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