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