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);
19d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com
20d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** Atomically adds inc to the int referenced by addr and returns the previous value.
21d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com *  No additional memory barrier is required; this must act as a compiler barrier.
22d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */
23d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic int32_t sk_atomic_add(int32_t* addr, int32_t inc);
24d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com
25d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** Atomically subtracts one from the int referenced by addr and returns the previous value.
26d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com *  This must act as a release (SL/S) memory barrier and as a compiler barrier.
27d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */
28d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic int32_t sk_atomic_dec(int32_t* addr);
29d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com
304b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org/** Atomic compare and set.
314b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org *  If *addr == before, set *addr to after and return true, otherwise return false.
324b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org *  This must act as a release (SL/S) memory barrier and as a compiler barrier.
334b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org */
344b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.orgstatic bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after);
354b5fba5a3cc29058088a9a62df1da83e1a3c7db0commit-bot@chromium.org
36d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** If sk_atomic_dec does not act as an acquire (L/SL) barrier,
37d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com *  this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
38d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */
39d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic void sk_membar_acquire__after_atomic_dec();
40d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com
41d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** If sk_atomic_conditional_inc does not act as an acquire (L/SL) barrier,
42d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com *  this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
43d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com */
44d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comstatic void sk_membar_acquire__after_atomic_conditional_inc();
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com#include SK_ATOMICS_PLATFORM_H
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4881da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org/** Atomically adds one to the int referenced by addr iff the referenced int was not 0
4981da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org *  and returns the previous value.
5081da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org *  No additional memory barrier is required; this must act as a compiler barrier.
5181da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org */
5281da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.orgstatic inline int32_t sk_atomic_conditional_inc(int32_t* addr) {
5381da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org    int32_t prev;
5481da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org    do {
5581da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org        prev = *addr;
5681da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org        if (0 == prev) {
5781da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org            break;
5881da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org        }
5981da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org    } while (!sk_atomic_cas(addr, prev, prev+1));
6081da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org    return prev;
6181da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org}
6281da061f7285bbcf0acc31142042a9cd0ab8f068commit-bot@chromium.org
63448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org// SK_BARRIERS_PLATFORM_H must provide implementations for the following declarations:
64448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org
65448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org/** Prevent the compiler from reordering across this barrier. */
66448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.orgstatic void sk_compiler_barrier();
67448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org
68448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org/** Read T*, with at least an acquire barrier.
69448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org *
70448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org *  Only needs to be implemented for T which can be atomically read.
71448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org */
72448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.orgtemplate <typename T> T sk_acquire_load(T*);
73448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org
74448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org/** Write T*, with at least a release barrier.
75448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org *
76448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org *  Only needs to be implemented for T which can be atomically written.
77448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org */
78448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.orgtemplate <typename T> void sk_release_store(T*, T);
79448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org
80448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org#include SK_BARRIERS_PLATFORM_H
81448e2a3b3935d91e7bf84dc5b0367b92d2e2a518commit-bot@chromium.org
82d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com/** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations.
83d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com
84d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comclass SkBaseMutex {
85d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.compublic:
86b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    void acquire();     // Block until this thread owns the mutex.
87b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    void release();     // Assuming this thread owns the mutex, release it.
88b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    void assertHeld();  // If SK_DEBUG, assert this thread owns the mutex.
89d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com};
90d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com
91d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.comclass SkMutex : SkBaseMutex {
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMutex();
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ~SkMutex();
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
97d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = ...
98d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com#define SK_DECLARE_GLOBAL_MUTEX(name) 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