1c782b2a046763dc427fa47d4e33afca59c994d60herb/*
2c782b2a046763dc427fa47d4e33afca59c994d60herb * Copyright 2015 Google Inc.
3c782b2a046763dc427fa47d4e33afca59c994d60herb *
4c782b2a046763dc427fa47d4e33afca59c994d60herb * Use of this source code is governed by a BSD-style license that can be
5c782b2a046763dc427fa47d4e33afca59c994d60herb * found in the LICENSE file.
6c782b2a046763dc427fa47d4e33afca59c994d60herb */
7c782b2a046763dc427fa47d4e33afca59c994d60herb
8c782b2a046763dc427fa47d4e33afca59c994d60herb#include "SkSharedMutex.h"
9c782b2a046763dc427fa47d4e33afca59c994d60herb
10b906daf112416c1698a79cf51aa70fe11aa19d0aherb#include "SkAtomics.h"
11c782b2a046763dc427fa47d4e33afca59c994d60herb#include "SkTypes.h"
12e4c17356b6c819df8effb29dfb4bb903520b8c2bherb#include "SkSemaphore.h"
13c782b2a046763dc427fa47d4e33afca59c994d60herb
143b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#if !defined(__has_feature)
153b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define __has_feature(x) 0
163b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#endif
173b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
183b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#if __has_feature(thread_sanitizer)
193b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
203b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    /* Report that a lock has been created at address "lock". */
213b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_CREATE(lock) \
223b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        AnnotateRWLockCreate(__FILE__, __LINE__, lock)
233b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
243b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    /* Report that the lock at address "lock" is about to be destroyed. */
253b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_DESTROY(lock) \
263b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
273b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
283b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    /* Report that the lock at address "lock" has been acquired.
293b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein       is_w=1 for writer lock, is_w=0 for reader lock. */
303b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
313b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
323b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
333b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    /* Report that the lock at address "lock" is about to be released. */
343b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
353b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein      AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
363b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
373b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #if defined(DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK)
383b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        #if defined(__GNUC__)
393b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein            #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak))
403b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        #else
413b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein            /* TODO(glider): for Windows support we may want to change this macro in order
423b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein               to prepend __declspec(selectany) to the annotations' declarations. */
433b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein            #error weak annotations are not supported for your compiler
443b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        #endif
453b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #else
463b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK
473b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #endif
483b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
493b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    extern "C" {
503b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    void AnnotateRWLockCreate(
513b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const char *file, int line,
523b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
533b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    void AnnotateRWLockDestroy(
543b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const char *file, int line,
553b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
563b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    void AnnotateRWLockAcquired(
573b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const char *file, int line,
583b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
593b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    void AnnotateRWLockReleased(
603b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const char *file, int line,
613b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein        const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
623b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    }
633b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
643b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#else
653b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
663b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_CREATE(lock)
673b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_DESTROY(lock)
683b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)
693b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein    #define ANNOTATE_RWLOCK_RELEASED(lock, is_w)
703b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
713b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein#endif
723b7658a4752e1332c684ad757686ce9ee0e5fbd1Mike Klein
73966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb#ifdef SK_DEBUG
74966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
75e4c17356b6c819df8effb29dfb4bb903520b8c2bherb    #include "SkThreadID.h"
76966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    #include "SkTDArray.h"
77966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
78966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    class SkSharedMutex::ThreadIDSet {
79966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    public:
80966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // Returns true if threadID is in the set.
81e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        bool find(SkThreadID threadID) const {
82966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            for (auto& t : fThreadIDs) {
83966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                if (t == threadID) return true;
84966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
85966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            return false;
86966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
87966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
88966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // Returns true if did not already exist.
89e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        bool tryAdd(SkThreadID threadID) {
90966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            for (auto& t : fThreadIDs) {
91966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                if (t == threadID) return false;
92966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
93966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fThreadIDs.append(1, &threadID);
94966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            return true;
95966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
96966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // Returns true if already exists in Set.
97e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        bool tryRemove(SkThreadID threadID) {
98966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            for (int i = 0; i < fThreadIDs.count(); ++i) {
99966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                if (fThreadIDs[i] == threadID) {
100966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                    fThreadIDs.remove(i);
101966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                    return true;
102966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                }
103966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
104966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            return false;
105966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
106966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
107966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        void swap(ThreadIDSet& other) {
108966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fThreadIDs.swap(other.fThreadIDs);
109966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
110966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
111966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int count() const {
112966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            return fThreadIDs.count();
113966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
114966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
115966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    private:
116e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkTDArray<SkThreadID> fThreadIDs;
117966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    };
118966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
119966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    SkSharedMutex::SkSharedMutex()
120966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        : fCurrentShared(new ThreadIDSet)
121966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        , fWaitingExclusive(new ThreadIDSet)
122966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        , fWaitingShared(new ThreadIDSet){
123966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_CREATE(this);
124c782b2a046763dc427fa47d4e33afca59c994d60herb    }
125c782b2a046763dc427fa47d4e33afca59c994d60herb
126966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    SkSharedMutex::~SkSharedMutex() {  ANNOTATE_RWLOCK_DESTROY(this); }
127dec1afcf34dfb91f3bf0552feffc46b8865fcb36herb
128966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::acquire() {
129e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkThreadID threadID(SkGetThreadID());
130966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int currentSharedCount;
131966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int waitingExclusiveCount;
132966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        {
133966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            SkAutoMutexAcquire l(&fMu);
134c782b2a046763dc427fa47d4e33afca59c994d60herb
135966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if (!fWaitingExclusive->tryAdd(threadID)) {
136966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                SkDEBUGFAILF("Thread %lx already has an exclusive lock\n", threadID);
137966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
138c782b2a046763dc427fa47d4e33afca59c994d60herb
139966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            currentSharedCount = fCurrentShared->count();
140966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            waitingExclusiveCount = fWaitingExclusive->count();
141966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
142c782b2a046763dc427fa47d4e33afca59c994d60herb
143966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if (currentSharedCount > 0 || waitingExclusiveCount > 1) {
144966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fExclusiveQueue.wait();
145966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
146c782b2a046763dc427fa47d4e33afca59c994d60herb
147966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_ACQUIRED(this, 1);
148966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
149c782b2a046763dc427fa47d4e33afca59c994d60herb
150966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // Implementation Detail:
151966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // The shared threads need two seperate queues to keep the threads that were added after the
152966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // exclusive lock separate from the threads added before.
153966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::release() {
154966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_RELEASED(this, 1);
155e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkThreadID threadID(SkGetThreadID());
156966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int sharedWaitingCount;
157966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int exclusiveWaitingCount;
158966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int sharedQueueSelect;
159966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        {
160966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            SkAutoMutexAcquire l(&fMu);
161966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            SkASSERT(0 == fCurrentShared->count());
162966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if (!fWaitingExclusive->tryRemove(threadID)) {
163966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                SkDEBUGFAILF("Thread %lx did not have the lock held.\n", threadID);
164966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
165966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            exclusiveWaitingCount = fWaitingExclusive->count();
166966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            sharedWaitingCount = fWaitingShared->count();
167966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fWaitingShared.swap(fCurrentShared);
168966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            sharedQueueSelect = fSharedQueueSelect;
169966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if (sharedWaitingCount > 0) {
170966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                fSharedQueueSelect = 1 - fSharedQueueSelect;
171966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
172c782b2a046763dc427fa47d4e33afca59c994d60herb        }
173c782b2a046763dc427fa47d4e33afca59c994d60herb
174966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if (sharedWaitingCount > 0) {
175966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fSharedQueue[sharedQueueSelect].signal(sharedWaitingCount);
176966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        } else if (exclusiveWaitingCount > 0) {
177966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fExclusiveQueue.signal();
178966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
179966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
180c782b2a046763dc427fa47d4e33afca59c994d60herb
181966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::assertHeld() const {
182e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkThreadID threadID(SkGetThreadID());
183966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        SkAutoMutexAcquire l(&fMu);
184966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        SkASSERT(0 == fCurrentShared->count());
185966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        SkASSERT(fWaitingExclusive->find(threadID));
186c782b2a046763dc427fa47d4e33afca59c994d60herb    }
187c782b2a046763dc427fa47d4e33afca59c994d60herb
188966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::acquireShared() {
189e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkThreadID threadID(SkGetThreadID());
190966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int exclusiveWaitingCount;
191966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int sharedQueueSelect;
192966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        {
193966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            SkAutoMutexAcquire l(&fMu);
194966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            exclusiveWaitingCount = fWaitingExclusive->count();
195966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if (exclusiveWaitingCount > 0) {
196966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                if (!fWaitingShared->tryAdd(threadID)) {
197966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                    SkDEBUGFAILF("Thread %lx was already waiting!\n", threadID);
198966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                }
199966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            } else {
200966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                if (!fCurrentShared->tryAdd(threadID)) {
201966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                    SkDEBUGFAILF("Thread %lx already holds a shared lock!\n", threadID);
202966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                }
203966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
204966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            sharedQueueSelect = fSharedQueueSelect;
205966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
206ab42ec79d5dbf38b81394c55670b495cdf78b243herb
207966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if (exclusiveWaitingCount > 0) {
208966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fSharedQueue[sharedQueueSelect].wait();
209c782b2a046763dc427fa47d4e33afca59c994d60herb        }
210c782b2a046763dc427fa47d4e33afca59c994d60herb
211966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_ACQUIRED(this, 0);
212966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
213966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
214966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::releaseShared() {
215966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_RELEASED(this, 0);
216e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkThreadID threadID(SkGetThreadID());
217966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
218966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int currentSharedCount;
219966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int waitingExclusiveCount;
220966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        {
221966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            SkAutoMutexAcquire l(&fMu);
222966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if (!fCurrentShared->tryRemove(threadID)) {
223966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                SkDEBUGFAILF("Thread %lx does not hold a shared lock.\n", threadID);
224966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
225966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            currentSharedCount = fCurrentShared->count();
226966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            waitingExclusiveCount = fWaitingExclusive->count();
227966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
228966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
229966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if (0 == currentSharedCount && waitingExclusiveCount > 0) {
230966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fExclusiveQueue.signal();
231966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
232c782b2a046763dc427fa47d4e33afca59c994d60herb    }
233c782b2a046763dc427fa47d4e33afca59c994d60herb
234966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::assertHeldShared() const {
235e4c17356b6c819df8effb29dfb4bb903520b8c2bherb        SkThreadID threadID(SkGetThreadID());
236966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        SkAutoMutexAcquire l(&fMu);
237966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        SkASSERT(fCurrentShared->find(threadID));
238966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
239dec1afcf34dfb91f3bf0552feffc46b8865fcb36herb
240966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb#else
241c782b2a046763dc427fa47d4e33afca59c994d60herb
242966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // The fQueueCounts fields holds many counts in an int32_t in order to make managing them atomic.
243966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // These three counts must be the same size, so each gets 10 bits. The 10 bits represent
244966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // the log of the count which is 1024.
245966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    //
246966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // The three counts held in fQueueCounts are:
247966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // * Shared - the number of shared lock holders currently running.
248966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // * WaitingExclusive - the number of threads waiting for an exclusive lock.
249966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    // * WaitingShared - the number of threads waiting to run while waiting for an exclusive thread
250966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    //   to finish.
251966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    static const int kLogThreadCount = 10;
252966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
253966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    enum {
254966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        kSharedOffset          = (0 * kLogThreadCount),
255966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        kWaitingExlusiveOffset = (1 * kLogThreadCount),
256966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        kWaitingSharedOffset   = (2 * kLogThreadCount),
257966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        kSharedMask            = ((1 << kLogThreadCount) - 1) << kSharedOffset,
258966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        kWaitingExclusiveMask  = ((1 << kLogThreadCount) - 1) << kWaitingExlusiveOffset,
259966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        kWaitingSharedMask     = ((1 << kLogThreadCount) - 1) << kWaitingSharedOffset,
260966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    };
261966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
262966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    SkSharedMutex::SkSharedMutex() : fQueueCounts(0) { ANNOTATE_RWLOCK_CREATE(this); }
263966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    SkSharedMutex::~SkSharedMutex() {  ANNOTATE_RWLOCK_DESTROY(this); }
264966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::acquire() {
265966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // Increment the count of exclusive queue waiters.
266966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t oldQueueCounts = fQueueCounts.fetch_add(1 << kWaitingExlusiveOffset,
267966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                                                        sk_memory_order_acquire);
268966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
269966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // If there are no other exclusive waiters and no shared threads are running then run
270966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // else wait.
271966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if ((oldQueueCounts & kWaitingExclusiveMask) > 0 || (oldQueueCounts & kSharedMask) > 0) {
272966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fExclusiveQueue.wait();
273966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
274966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_ACQUIRED(this, 1);
275c782b2a046763dc427fa47d4e33afca59c994d60herb    }
276ab42ec79d5dbf38b81394c55670b495cdf78b243herb
277966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::release() {
278966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_RELEASED(this, 1);
279966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
280966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed);
281966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t waitingShared;
282966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t newQueueCounts;
283966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        do {
284966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            newQueueCounts = oldQueueCounts;
285966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
286966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // Decrement exclusive waiters.
287966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            newQueueCounts -= 1 << kWaitingExlusiveOffset;
288966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
289966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // The number of threads waiting to acquire a shared lock.
290966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            waitingShared = (oldQueueCounts & kWaitingSharedMask) >> kWaitingSharedOffset;
291966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
292966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // If there are any move the counts of all the shared waiters to actual shared. They are
293966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // going to run next.
294966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if (waitingShared > 0) {
295966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
296966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                // Set waiting shared to zero.
297966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                newQueueCounts &= ~kWaitingSharedMask;
298966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
299966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                // Because this is the exclusive release, then there are zero readers. So, the bits
300966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                // for shared locks should be zero. Since those bits are zero, we can just |= in the
301966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                // waitingShared count instead of clearing with an &= and then |= the count.
302966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                newQueueCounts |= waitingShared << kSharedOffset;
303966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
304966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
305966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        } while (!fQueueCounts.compare_exchange(&oldQueueCounts, newQueueCounts,
306966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                                                sk_memory_order_release, sk_memory_order_relaxed));
307966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
308966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if (waitingShared > 0) {
309966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // Run all the shared.
310966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fSharedQueue.signal(waitingShared);
311966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        } else if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
312966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // Run a single exclusive waiter.
313966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fExclusiveQueue.signal();
314966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
315966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
316966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
317966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::acquireShared() {
318966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed);
319966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t newQueueCounts;
320966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        do {
321966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            newQueueCounts = oldQueueCounts;
322966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            // If there are waiting exclusives then this shared lock waits else it runs.
323966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
324966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                newQueueCounts += 1 << kWaitingSharedOffset;
325966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            } else {
326966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                newQueueCounts += 1 << kSharedOffset;
327966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            }
328966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        } while (!fQueueCounts.compare_exchange(&oldQueueCounts, newQueueCounts,
329966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                                                sk_memory_order_acquire, sk_memory_order_relaxed));
330966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
331966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // If there are waiting exclusives, then this shared waits until after it runs.
332966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
333966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fSharedQueue.wait();
334966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
335966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_ACQUIRED(this, 0);
336966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
337966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
338966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
339966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    void SkSharedMutex::releaseShared() {
340966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        ANNOTATE_RWLOCK_RELEASED(this, 0);
341966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
342966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // Decrement the shared count.
343966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        int32_t oldQueueCounts = fQueueCounts.fetch_sub(1 << kSharedOffset,
344966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb                                                        sk_memory_order_release);
345966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb
346966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // If shared count is going to zero (because the old count == 1) and there are exclusive
347966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        // waiters, then run a single exclusive waiter.
348966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        if (((oldQueueCounts & kSharedMask) >> kSharedOffset) == 1
349966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            && (oldQueueCounts & kWaitingExclusiveMask) > 0) {
350966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb            fExclusiveQueue.signal();
351966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb        }
352966e3d30baf676dc399dc9c97ef15cc2c4f8d461herb    }
353ab42ec79d5dbf38b81394c55670b495cdf78b243herb
354ab42ec79d5dbf38b81394c55670b495cdf78b243herb#endif
355