aboutsummaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-08 21:15:56 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-01-08 21:15:56 +0000
commit4b5fba5a3cc29058088a9a62df1da83e1a3c7db0 (patch)
treef50e71f9e8f93b6649b36aecd13068e8e1ae6a83 /include
parentd4ba6e778122df9b52dc68a2f41210d33fd43471 (diff)
Use a spinlock in SkOnce.
SkOnceFlag is now statically initializable on all platforms. Also adds sk_atomic_cas, used to implement new SkSpinlock. Going to punt on making SkOnceFlag any smaller (for now, it's 8 bytes). We could conceivably get it down to two bits, one for done and one for a one-bit spinlock (we'd need atomic-& and atomic-| to make that work, but they appear to be available everywhere). BUG=skia:1929 R=bungeman@google.com, reed@google.com Author: mtklein@google.com Review URL: https://codereview.chromium.org/123093002 git-svn-id: http://skia.googlecode.com/svn/trunk@12968 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include')
-rw-r--r--include/core/SkThread.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/include/core/SkThread.h b/include/core/SkThread.h
index 412ace31eb..160b40ce29 100644
--- a/include/core/SkThread.h
+++ b/include/core/SkThread.h
@@ -33,6 +33,12 @@ static int32_t sk_atomic_dec(int32_t* addr);
*/
static int32_t sk_atomic_conditional_inc(int32_t* addr);
+/** Atomic compare and set.
+ * If *addr == before, set *addr to after and return true, otherwise return false.
+ * This must act as a release (SL/S) memory barrier and as a compiler barrier.
+ */
+static bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after);
+
/** If sk_atomic_dec does not act as an acquire (L/SL) barrier,
* this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
*/
@@ -45,6 +51,34 @@ static void sk_membar_acquire__after_atomic_conditional_inc();
#include SK_ATOMICS_PLATFORM_H
+// This is POD and must be zero-initialized.
+struct SkSpinlock {
+ void acquire() {
+ SkASSERT(shouldBeZero == 0);
+ // No memory barrier needed, but sk_atomic_cas gives us at least release anyway.
+ while (!sk_atomic_cas(&thisIsPrivate, 0, 1)) {
+ // spin
+ }
+ }
+
+ void release() {
+ SkASSERT(shouldBeZero == 0);
+ // This requires a release memory barrier before storing, which sk_atomic_cas guarantees.
+ SkAssertResult(sk_atomic_cas(&thisIsPrivate, 1, 0));
+ }
+
+ int32_t thisIsPrivate;
+ SkDEBUGCODE(int32_t shouldBeZero;)
+};
+
+class SkAutoSpinlock : SkNoncopyable {
+public:
+ explicit SkAutoSpinlock(SkSpinlock* lock) : fLock(lock) { fLock->acquire(); }
+ ~SkAutoSpinlock() { fLock->release(); }
+private:
+ SkSpinlock* fLock;
+};
+#define SkAutoSpinlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoSpinlock)
/** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations.