diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-01-08 21:15:56 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2014-01-08 21:15:56 +0000 |
commit | 4b5fba5a3cc29058088a9a62df1da83e1a3c7db0 (patch) | |
tree | f50e71f9e8f93b6649b36aecd13068e8e1ae6a83 /include/core/SkThread.h | |
parent | d4ba6e778122df9b52dc68a2f41210d33fd43471 (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/core/SkThread.h')
-rw-r--r-- | include/core/SkThread.h | 34 |
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. |