1 /*
2 * Copyright 2006 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 #ifndef SkThread_DEFINED
9 #define SkThread_DEFINED
10
11 #include "SkTypes.h"
12
13 // SK_ATOMICS_PLATFORM_H must provide inline implementations for the following declarations.
14
15 /** Atomically adds one to the int referenced by addr and returns the previous value.
16 * No additional memory barrier is required; this must act as a compiler barrier.
17 */
18 static int32_t sk_atomic_inc(int32_t* addr);
19
20 /** Atomically adds inc to the int referenced by addr and returns the previous value.
21 * No additional memory barrier is required; this must act as a compiler barrier.
22 */
23 static int32_t sk_atomic_add(int32_t* addr, int32_t inc);
24
25 /** Atomically subtracts one from the int referenced by addr and returns the previous value.
26 * This must act as a release (SL/S) memory barrier and as a compiler barrier.
27 */
28 static int32_t sk_atomic_dec(int32_t* addr);
29
30 /** Atomic compare and set.
31 * If *addr == before, set *addr to after and return true, otherwise return false.
32 * This must act as a release (SL/S) memory barrier and as a compiler barrier.
33 */
34 static bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after);
35
36 /** If sk_atomic_dec does not act as an acquire (L/SL) barrier,
37 * this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
38 */
39 static void sk_membar_acquire__after_atomic_dec();
40
41 /** If sk_atomic_conditional_inc does not act as an acquire (L/SL) barrier,
42 * this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
43 */
44 static void sk_membar_acquire__after_atomic_conditional_inc();
45
46 #include SK_ATOMICS_PLATFORM_H
47
48 /** Atomically adds one to the int referenced by addr iff the referenced int was not 0
49 * and returns the previous value.
50 * No additional memory barrier is required; this must act as a compiler barrier.
51 */
sk_atomic_conditional_inc(int32_t * addr)52 static inline int32_t sk_atomic_conditional_inc(int32_t* addr) {
53 int32_t prev;
54 do {
55 prev = *addr;
56 if (0 == prev) {
57 break;
58 }
59 } while (!sk_atomic_cas(addr, prev, prev+1));
60 return prev;
61 }
62
63 // SK_BARRIERS_PLATFORM_H must provide implementations for the following declarations:
64
65 /** Prevent the compiler from reordering across this barrier. */
66 static void sk_compiler_barrier();
67
68 /** Read T*, with at least an acquire barrier.
69 *
70 * Only needs to be implemented for T which can be atomically read.
71 */
72 template <typename T> T sk_acquire_load(T*);
73
74 /** Write T*, with at least a release barrier.
75 *
76 * Only needs to be implemented for T which can be atomically written.
77 */
78 template <typename T> void sk_release_store(T*, T);
79
80 #include SK_BARRIERS_PLATFORM_H
81
82 /** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations.
83
84 class SkBaseMutex {
85 public:
86 void acquire(); // Block until this thread owns the mutex.
87 void release(); // Assuming this thread owns the mutex, release it.
88 void assertHeld(); // If SK_DEBUG, assert this thread owns the mutex.
89 };
90
91 class SkMutex : SkBaseMutex {
92 public:
93 SkMutex();
94 ~SkMutex();
95 };
96
97 #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = ...
98 #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = ...
99 */
100
101 #include SK_MUTEX_PLATFORM_H
102
103
104 class SkAutoMutexAcquire : SkNoncopyable {
105 public:
SkAutoMutexAcquire(SkBaseMutex & mutex)106 explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) {
107 SkASSERT(fMutex != NULL);
108 mutex.acquire();
109 }
110
SkAutoMutexAcquire(SkBaseMutex * mutex)111 explicit SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) {
112 if (mutex) {
113 mutex->acquire();
114 }
115 }
116
117 /** If the mutex has not been released, release it now. */
~SkAutoMutexAcquire()118 ~SkAutoMutexAcquire() {
119 if (fMutex) {
120 fMutex->release();
121 }
122 }
123
124 /** If the mutex has not been released, release it now. */
release()125 void release() {
126 if (fMutex) {
127 fMutex->release();
128 fMutex = NULL;
129 }
130 }
131
132 /** Assert that we're holding the mutex. */
assertHeld()133 void assertHeld() {
134 SkASSERT(fMutex);
135 fMutex->assertHeld();
136 }
137
138 private:
139 SkBaseMutex* fMutex;
140 };
141 #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
142
143 #endif
144