18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkThread_DEFINED 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkThread_DEFINED 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypes.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com// SK_ATOMICS_PLATFORM_H must provide inline implementations for the following declarations. 14d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 15d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** Atomically adds one to the int referenced by addr and returns the previous value. 16d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com * No additional memory barrier is required; this must act as a compiler barrier. 17d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */ 18d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic int32_t sk_atomic_inc(int32_t* addr); 1900a8fae0cee239181c9e4fc7775b01b661c72f5ebsalomonstatic int64_t sk_atomic_inc(int64_t* addr); 20d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 21d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** Atomically adds inc to the int referenced by addr and returns the previous value. 22d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com * No additional memory barrier is required; this must act as a compiler barrier. 23d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */ 24d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic int32_t sk_atomic_add(int32_t* addr, int32_t inc); 25d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 26d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** Atomically subtracts one from the int referenced by addr and returns the previous value. 27d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com * This must act as a release (SL/S) memory barrier and as a compiler barrier. 28d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */ 29d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic int32_t sk_atomic_dec(int32_t* addr); 30d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 314b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org/** Atomic compare and set. 324b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org * If *addr == before, set *addr to after and return true, otherwise return false. 334b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org * This must act as a release (SL/S) memory barrier and as a compiler barrier. 344b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org */ 354b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.orgstatic bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after); 364b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org 37d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** If sk_atomic_dec does not act as an acquire (L/SL) barrier, 38d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com * this must act as an acquire (L/SL) memory barrier and as a compiler barrier. 39d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */ 40d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic void sk_membar_acquire__after_atomic_dec(); 41d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 42d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** If sk_atomic_conditional_inc does not act as an acquire (L/SL) barrier, 43d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com * this must act as an acquire (L/SL) memory barrier and as a compiler barrier. 44d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */ 45d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic void sk_membar_acquire__after_atomic_conditional_inc(); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 47d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com#include SK_ATOMICS_PLATFORM_H 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4981da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org/** Atomically adds one to the int referenced by addr iff the referenced int was not 0 5081da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org * and returns the previous value. 5181da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org * No additional memory barrier is required; this must act as a compiler barrier. 5281da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org */ 5300a8fae0cee239181c9e4fc7775b01b661c72f5ebsalomontemplate<typename INT_TYPE> static inline INT_TYPE sk_atomic_conditional_inc(INT_TYPE* addr) { 5400a8fae0cee239181c9e4fc7775b01b661c72f5ebsalomon INT_TYPE prev; 5581da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org do { 5681da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org prev = *addr; 5781da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org if (0 == prev) { 5881da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org break; 5981da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org } 6081da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org } while (!sk_atomic_cas(addr, prev, prev+1)); 6181da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org return prev; 6281da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org} 6381da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org 64448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org// SK_BARRIERS_PLATFORM_H must provide implementations for the following declarations: 65448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org 66448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org/** Prevent the compiler from reordering across this barrier. */ 67448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.orgstatic void sk_compiler_barrier(); 68448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org 69448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org/** Read T*, with at least an acquire barrier. 70448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org * 71448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org * Only needs to be implemented for T which can be atomically read. 72448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org */ 73448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.orgtemplate <typename T> T sk_acquire_load(T*); 74448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org 75448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org/** Write T*, with at least a release barrier. 76448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org * 77448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org * Only needs to be implemented for T which can be atomically written. 78448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org */ 79448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.orgtemplate <typename T> void sk_release_store(T*, T); 80448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org 81448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org#include SK_BARRIERS_PLATFORM_H 82448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org 83d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations. 84d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 85d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comclass SkBaseMutex { 86d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.compublic: 87b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein void acquire(); // Block until this thread owns the mutex. 88b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein void release(); // Assuming this thread owns the mutex, release it. 89b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein void assertHeld(); // If SK_DEBUG, assert this thread owns the mutex. 90d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com}; 91d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 92d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comclass SkMutex : SkBaseMutex { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMutex(); 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkMutex(); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 98d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = ... 99d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com*/ 100d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 101d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com#include SK_MUTEX_PLATFORM_H 102d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoMutexAcquire : SkNoncopyable { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 106064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) { 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMutex != NULL); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutex.acquire(); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 111d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com explicit SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) { 112064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com if (mutex) { 113064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com mutex->acquire(); 114064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com } 115064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com } 116064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com 117d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com /** If the mutex has not been released, release it now. */ 118064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com ~SkAutoMutexAcquire() { 119064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com if (fMutex) { 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMutex->release(); 121064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com } 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 123064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com 124d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com /** If the mutex has not been released, release it now. */ 125064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com void release() { 126064e50d495786fcc6d1f81ddcac765ff862a750ereed@google.com if (fMutex) { 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMutex->release(); 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMutex = NULL; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 131fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 132b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein /** Assert that we're holding the mutex. */ 133b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein void assertHeld() { 134b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein SkASSERT(fMutex); 135b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein fMutex->assertHeld(); 136b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein } 137b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1391771cbf43d9a1334e3d870c635b4215bb888dd98digit@google.com SkBaseMutex* fMutex; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 141e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire) 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 144