Title: [277709] trunk/Source
Revision
277709
Author
cdu...@apple.com
Date
2021-05-18 18:51:47 -0700 (Tue, 18 May 2021)

Log Message

Use WTF::Locker for locking BaseAudioContext's graph lock
https://bugs.webkit.org/show_bug.cgi?id=225935

Reviewed by Sam Weinig.

Source/WebCore:

Use WTF::Locker for locking BaseAudioContext's graph lock instead of our own AutoLocker.
Also use WTF::RecursiveLock instead of duplicating the recursive locking logic inside
BaseAudioContext. This means we no longer need lock() / tryLock() / unlock() functions
on BaseAudioContext. We now expose the BaseAudioContext's RecursiveLock via a graphLock()
getter and the caller sites can just use a Locker.

* Modules/webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::setBuffer):
* Modules/webaudio/AudioNode.cpp:
(WebCore::AudioNode::connect):
(WebCore::AudioNode::disconnect):
(WebCore::AudioNode::setChannelCount):
(WebCore::AudioNode::setChannelCountMode):
(WebCore::AudioNode::setChannelInterpretation):
(WebCore::AudioNode::enableOutputsIfNecessary):
(WebCore::AudioNode::decrementConnectionCount):
(WebCore::AudioNode::deref):
* Modules/webaudio/AudioWorkletNode.cpp:
(WebCore::AudioWorkletNode::create):
* Modules/webaudio/BaseAudioContext.cpp:
(WebCore::BaseAudioContext::uninitialize):
(WebCore::BaseAudioContext::refSourceNode):
(WebCore::BaseAudioContext::addDeferredDecrementConnectionCount):
(WebCore::BaseAudioContext::handlePreRenderTasks):
(WebCore::BaseAudioContext::outputPosition):
(WebCore::BaseAudioContext::handlePostRenderTasks):
(WebCore::BaseAudioContext::deleteMarkedNodes):
(WebCore::BaseAudioContext::removeMarkedSummingJunction):
(WebCore::BaseAudioContext::handleDirtyAudioSummingJunctions):
(WebCore::BaseAudioContext::handleDirtyAudioNodeOutputs):
* Modules/webaudio/BaseAudioContext.h:
(WebCore::BaseAudioContext::graphLock):
(WebCore::BaseAudioContext::isGraphOwner const):
* Modules/webaudio/ChannelMergerNode.cpp:
(WebCore::ChannelMergerNode::ChannelMergerNode):
* Modules/webaudio/ConvolverNode.cpp:
(WebCore::ConvolverNode::setBuffer):
* Modules/webaudio/MediaElementAudioSourceNode.cpp:
(WebCore::MediaElementAudioSourceNode::setFormat):
* Modules/webaudio/MediaStreamAudioSourceNode.cpp:
(WebCore::MediaStreamAudioSourceNode::setFormat):
* Modules/webaudio/OfflineAudioContext.cpp:
(WebCore::OfflineAudioContext::suspendRendering):
(WebCore::OfflineAudioContext::shouldSuspend):
(WebCore::OfflineAudioContext::didSuspendRendering):
* Modules/webaudio/OfflineAudioContext.h:
* Modules/webaudio/WaveShaperNode.cpp:
(WebCore::WaveShaperNode::setOversample):

Source/WTF:

* wtf/RecursiveLockAdapter.h:
(WTF::RecursiveLockAdapter::isOwner const):
Add isOwner() function that returns true if the current thread is holding the lock.
This is needed for WebAudio purposes.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (277708 => 277709)


--- trunk/Source/WTF/ChangeLog	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WTF/ChangeLog	2021-05-19 01:51:47 UTC (rev 277709)
@@ -1,3 +1,15 @@
+2021-05-18  Chris Dumez  <cdu...@apple.com>
+
+        Use WTF::Locker for locking BaseAudioContext's graph lock
+        https://bugs.webkit.org/show_bug.cgi?id=225935
+
+        Reviewed by Sam Weinig.
+
+        * wtf/RecursiveLockAdapter.h:
+        (WTF::RecursiveLockAdapter::isOwner const):
+        Add isOwner() function that returns true if the current thread is holding the lock.
+        This is needed for WebAudio purposes.
+
 2021-05-18  Aditya Keerthi  <akeer...@apple.com>
 
         [macOS] Titlebar separator doesn't show when WKWebView is scrolled

Modified: trunk/Source/WTF/wtf/RecursiveLockAdapter.h (277708 => 277709)


--- trunk/Source/WTF/wtf/RecursiveLockAdapter.h	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WTF/wtf/RecursiveLockAdapter.h	2021-05-19 01:51:47 UTC (rev 277709)
@@ -80,6 +80,8 @@
     {
         return m_lock.isLocked();
     }
+
+    bool isOwner() const { return m_owner == &Thread::current(); }
     
 private:
     Thread* m_owner { nullptr }; // Use Thread* instead of RefPtr<Thread> since m_owner thread is always alive while m_onwer is set.

Modified: trunk/Source/WebCore/ChangeLog (277708 => 277709)


--- trunk/Source/WebCore/ChangeLog	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/ChangeLog	2021-05-19 01:51:47 UTC (rev 277709)
@@ -1,3 +1,59 @@
+2021-05-18  Chris Dumez  <cdu...@apple.com>
+
+        Use WTF::Locker for locking BaseAudioContext's graph lock
+        https://bugs.webkit.org/show_bug.cgi?id=225935
+
+        Reviewed by Sam Weinig.
+
+        Use WTF::Locker for locking BaseAudioContext's graph lock instead of our own AutoLocker.
+        Also use WTF::RecursiveLock instead of duplicating the recursive locking logic inside
+        BaseAudioContext. This means we no longer need lock() / tryLock() / unlock() functions
+        on BaseAudioContext. We now expose the BaseAudioContext's RecursiveLock via a graphLock()
+        getter and the caller sites can just use a Locker.
+
+        * Modules/webaudio/AudioBufferSourceNode.cpp:
+        (WebCore::AudioBufferSourceNode::setBuffer):
+        * Modules/webaudio/AudioNode.cpp:
+        (WebCore::AudioNode::connect):
+        (WebCore::AudioNode::disconnect):
+        (WebCore::AudioNode::setChannelCount):
+        (WebCore::AudioNode::setChannelCountMode):
+        (WebCore::AudioNode::setChannelInterpretation):
+        (WebCore::AudioNode::enableOutputsIfNecessary):
+        (WebCore::AudioNode::decrementConnectionCount):
+        (WebCore::AudioNode::deref):
+        * Modules/webaudio/AudioWorkletNode.cpp:
+        (WebCore::AudioWorkletNode::create):
+        * Modules/webaudio/BaseAudioContext.cpp:
+        (WebCore::BaseAudioContext::uninitialize):
+        (WebCore::BaseAudioContext::refSourceNode):
+        (WebCore::BaseAudioContext::addDeferredDecrementConnectionCount):
+        (WebCore::BaseAudioContext::handlePreRenderTasks):
+        (WebCore::BaseAudioContext::outputPosition):
+        (WebCore::BaseAudioContext::handlePostRenderTasks):
+        (WebCore::BaseAudioContext::deleteMarkedNodes):
+        (WebCore::BaseAudioContext::removeMarkedSummingJunction):
+        (WebCore::BaseAudioContext::handleDirtyAudioSummingJunctions):
+        (WebCore::BaseAudioContext::handleDirtyAudioNodeOutputs):
+        * Modules/webaudio/BaseAudioContext.h:
+        (WebCore::BaseAudioContext::graphLock):
+        (WebCore::BaseAudioContext::isGraphOwner const):
+        * Modules/webaudio/ChannelMergerNode.cpp:
+        (WebCore::ChannelMergerNode::ChannelMergerNode):
+        * Modules/webaudio/ConvolverNode.cpp:
+        (WebCore::ConvolverNode::setBuffer):
+        * Modules/webaudio/MediaElementAudioSourceNode.cpp:
+        (WebCore::MediaElementAudioSourceNode::setFormat):
+        * Modules/webaudio/MediaStreamAudioSourceNode.cpp:
+        (WebCore::MediaStreamAudioSourceNode::setFormat):
+        * Modules/webaudio/OfflineAudioContext.cpp:
+        (WebCore::OfflineAudioContext::suspendRendering):
+        (WebCore::OfflineAudioContext::shouldSuspend):
+        (WebCore::OfflineAudioContext::didSuspendRendering):
+        * Modules/webaudio/OfflineAudioContext.h:
+        * Modules/webaudio/WaveShaperNode.cpp:
+        (WebCore::WaveShaperNode::setOversample):
+
 2021-05-18  Alan Bujtas  <za...@apple.com>
 
         The containing block for a fixed renderer has to be a type of RenderBlock

Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -416,7 +416,7 @@
         return Exception { InvalidStateError, "The buffer was already set"_s };
 
     // The context must be locked since changing the buffer can re-configure the number of channels that are output.
-    BaseAudioContext::AutoLocker contextLocker(context());
+    Locker contextLocker { context().graphLock() };
     
     // This synchronizes with process().
     auto locker = holdLock(m_processLock);

Modified: trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -181,7 +181,7 @@
 ExceptionOr<void> AudioNode::connect(AudioNode& destination, unsigned outputIndex, unsigned inputIndex)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     ALWAYS_LOG(LOGIDENTIFIER, destination.nodeType(), ", output = ", outputIndex, ", input = ", inputIndex);
     
@@ -213,7 +213,7 @@
 
 ExceptionOr<void> AudioNode::connect(AudioParam& param, unsigned outputIndex)
 {
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     ASSERT(isMainThread());
 
@@ -234,7 +234,7 @@
 void AudioNode::disconnect()
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     for (unsigned outputIndex = 0; outputIndex < numberOfOutputs(); ++outputIndex) {
         auto* output = this->output(outputIndex);
@@ -248,7 +248,7 @@
 ExceptionOr<void> AudioNode::disconnect(unsigned outputIndex)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     if (outputIndex >= numberOfOutputs())
         return Exception { IndexSizeError, "output index is out of bounds"_s };
@@ -265,7 +265,7 @@
 ExceptionOr<void> AudioNode::disconnect(AudioNode& destinationNode)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     bool didDisconnection = false;
     for (unsigned outputIndex = 0; outputIndex < numberOfOutputs(); ++outputIndex) {
@@ -289,7 +289,7 @@
 ExceptionOr<void> AudioNode::disconnect(AudioNode& destinationNode, unsigned outputIndex)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     if (outputIndex >= numberOfOutputs())
         return Exception { IndexSizeError, "output index is out of bounds"_s };
@@ -314,7 +314,7 @@
 ExceptionOr<void> AudioNode::disconnect(AudioNode& destinationNode, unsigned outputIndex, unsigned inputIndex)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     if (outputIndex >= numberOfOutputs())
         return Exception { IndexSizeError, "output index is out of bounds"_s };
@@ -336,7 +336,7 @@
 ExceptionOr<void> AudioNode::disconnect(AudioParam& destinationParam)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     bool didDisconnection = false;
     for (unsigned outputIndex = 0; outputIndex < numberOfOutputs(); ++outputIndex) {
@@ -357,7 +357,7 @@
 ExceptionOr<void> AudioNode::disconnect(AudioParam& destinationParam, unsigned outputIndex)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     if (outputIndex >= numberOfOutputs())
         return Exception { IndexSizeError, "output index is out of bounds"_s };
@@ -380,7 +380,7 @@
 ExceptionOr<void> AudioNode::setChannelCount(unsigned channelCount)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     ALWAYS_LOG(LOGIDENTIFIER, channelCount);
 
@@ -402,7 +402,7 @@
 ExceptionOr<void> AudioNode::setChannelCountMode(ChannelCountMode mode)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     ALWAYS_LOG(LOGIDENTIFIER, mode);
     
@@ -418,7 +418,7 @@
 ExceptionOr<void> AudioNode::setChannelInterpretation(ChannelInterpretation interpretation)
 {
     ASSERT(isMainThread());
-    BaseAudioContext::AutoLocker locker(context());
+    Locker locker { context().graphLock() };
 
     ALWAYS_LOG(LOGIDENTIFIER, interpretation);
     
@@ -523,7 +523,7 @@
 {
     if (m_isDisabled && m_connectionRefCount > 0) {
         ASSERT(isMainThread());
-        BaseAudioContext::AutoLocker locker(context());
+        Locker locker { context().graphLock() };
 
         m_isDisabled = false;
         for (auto& output : m_outputs)
@@ -578,23 +578,9 @@
 {
     // The actually work for deref happens completely within the audio context's graph lock.
     // In the case of the audio thread, we must use a tryLock to avoid glitches.
-    bool hasLock = false;
-    bool mustReleaseLock = false;
-
-    if (context().isAudioThread()) {
-        // Real-time audio thread must not contend lock (to avoid glitches).
-        hasLock = context().tryLock(mustReleaseLock);
-    } else {
-        context().lock(mustReleaseLock);
-        hasLock = true;
-    }
-
-    if (hasLock) {
+    if (auto locker = context().isAudioThread() ? Locker<RecursiveLock>::tryLock(context().graphLock()) : Locker { context().graphLock() }) {
         // This is where the real deref work happens.
         decrementConnectionCountWithLock();
-
-        if (mustReleaseLock)
-            context().unlock();
     } else {
         // We were unable to get the lock, so put this in a list to finish up later.
         ASSERT(context().isAudioThread());
@@ -660,7 +646,7 @@
     ASSERT(!context().isAudioThread());
 
     {
-        BaseAudioContext::AutoLocker locker(context());
+        Locker locker { context().graphLock() };
         // This is where the real deref work happens.
         derefWithLock();
     }

Modified: trunk/Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/AudioWorkletNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -113,7 +113,7 @@
 
     {
         // The node should be manually added to the automatic pull node list, even without a connect() call.
-        BaseAudioContext::AutoLocker contextLocker(context);
+        Locker contextLocker { context.graphLock() };
         node->updatePullStatus();
     }
 

Modified: trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -199,7 +199,7 @@
     m_isAudioThreadFinished = true;
 
     {
-        AutoLocker locker(*this);
+        Locker locker { graphLock() };
         // This should have been called from handlePostRenderTasks() at the end of rendering.
         // However, in case of lock contention, the tryLock() call could have failed in handlePostRenderTasks(),
         // leaving nodes in m_referencedSourceNodes. Now that the audio thread is gone, make sure we deref those nodes
@@ -524,7 +524,7 @@
 void BaseAudioContext::refSourceNode(AudioNode& node)
 {
     ASSERT(isMainThread());
-    AutoLocker locker(*this);
+    Locker locker { graphLock() };
 
     ASSERT(!m_referencedSourceNodes.contains(&node));
     // Reference source node to keep it alive and playing even if its JS wrapper gets garbage collected.
@@ -545,70 +545,12 @@
     m_referencedSourceNodes.clear();
 }
 
-void BaseAudioContext::lock(bool& mustReleaseLock)
-{
-    // Don't allow regular lock in real-time audio thread.
-    ASSERT(isMainThread());
-
-    lockInternal(mustReleaseLock);
-}
-
-void BaseAudioContext::lockInternal(bool& mustReleaseLock)
-{
-    Thread& thisThread = Thread::current();
-
-    if (&thisThread == m_graphOwnerThread) {
-        // We already have the lock.
-        mustReleaseLock = false;
-    } else {
-        // Acquire the lock.
-        m_contextGraphLock.lock();
-        m_graphOwnerThread = &thisThread;
-        mustReleaseLock = true;
-    }
-}
-
-bool BaseAudioContext::tryLock(bool& mustReleaseLock)
-{
-    // Try to catch cases of using try lock on main thread - it should use regular lock.
-    ASSERT(isAudioThread() || isAudioThreadFinished());
-    
-    if (!isAudioThread()) {
-        // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do.
-        lock(mustReleaseLock);
-        return true;
-    }
-    
-    bool hasLock;
-    
-    if (isGraphOwner()) {
-        // Thread already has the lock.
-        hasLock = true;
-        mustReleaseLock = false;
-    } else {
-        // Don't already have the lock - try to acquire it.
-        hasLock = m_contextGraphLock.tryLock();
-        
-        if (hasLock)
-            m_graphOwnerThread = &Thread::current();
-
-        mustReleaseLock = hasLock;
-    }
-    
-    return hasLock;
-}
-
-void BaseAudioContext::unlock()
-{
-    ASSERT(m_graphOwnerThread == &Thread::current());
-
-    m_graphOwnerThread = nullptr;
-    m_contextGraphLock.unlock();
-}
-
 void BaseAudioContext::addDeferredDecrementConnectionCount(AudioNode* node)
 {
     ASSERT(isAudioThread());
+    // Heap allocations are forbidden on the audio thread for performance reasons so we need to
+    // explicitly allow the following allocation(s).
+    DisableMallocRestrictionsForCurrentThreadScope disableMallocRestrictions;
     m_deferredBreakConnectionList.append(node);
 }
 
@@ -618,8 +560,7 @@
 
     // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
     // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
-    bool mustReleaseLock;
-    if (tryLock(mustReleaseLock)) {
+    if (auto locker = Locker<RecursiveLock>::tryLock(graphLock())) {
         // Fixup the state of any dirty AudioSummingJunctions and AudioNodeOutputs.
         handleDirtyAudioSummingJunctions();
         handleDirtyAudioNodeOutputs();
@@ -626,9 +567,6 @@
 
         updateAutomaticPullNodes();
         m_outputPosition = outputPosition;
-
-        if (mustReleaseLock)
-            unlock();
     }
 }
 
@@ -635,7 +573,7 @@
 AudioIOPosition BaseAudioContext::outputPosition()
 {
     ASSERT(isMainThread());
-    AutoLocker locker(*this);
+    Locker locker { graphLock() };
     return m_outputPosition;
 }
 
@@ -646,8 +584,8 @@
     // Must use a tryLock() here too. Don't worry, the lock will very rarely be contended and this method is called frequently.
     // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
     // from the render graph (in which case they'll render silence).
-    bool mustReleaseLock;
-    if (!tryLock(mustReleaseLock))
+    auto locker = Locker<RecursiveLock>::tryLock(graphLock());
+    if (!locker)
         return;
 
     // Take care of finishing any derefs where the tryLock() failed previously.
@@ -665,9 +603,6 @@
     handleDirtyAudioNodeOutputs();
 
     updateAutomaticPullNodes();
-
-    if (mustReleaseLock)
-        unlock();
 }
 
 void BaseAudioContext::handleDeferredDecrementConnectionCounts()
@@ -727,10 +662,10 @@
 {
     ASSERT(isMainThread());
 
-    // Protect this object from being deleted before we release the mutex locked by AutoLocker.
+    // Protect this object from being deleted before we release the lock.
     auto protectedThis = makeRef(*this);
 
-    AutoLocker locker(*this);
+    Locker locker { graphLock() };
 
     while (m_nodesToDelete.size()) {
         AudioNode* node = m_nodesToDelete.takeLast();
@@ -765,7 +700,7 @@
 void BaseAudioContext::removeMarkedSummingJunction(AudioSummingJunction* summingJunction)
 {
     ASSERT(isMainThread());
-    AutoLocker locker(*this);
+    Locker locker { graphLock() };
     m_dirtySummingJunctions.remove(summingJunction);
 }
 
@@ -782,7 +717,7 @@
 
 void BaseAudioContext::handleDirtyAudioSummingJunctions()
 {
-    ASSERT(isGraphOwner());    
+    ASSERT(isGraphOwner());
 
     for (auto& junction : m_dirtySummingJunctions)
         junction->updateRenderingState();
@@ -792,7 +727,7 @@
 
 void BaseAudioContext::handleDirtyAudioNodeOutputs()
 {
-    ASSERT(isGraphOwner());    
+    ASSERT(isGraphOwner());
 
     for (auto& output : m_dirtyAudioNodeOutputs)
         output->updateRenderingState();

Modified: trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h	2021-05-19 01:51:47 UTC (rev 277709)
@@ -38,6 +38,7 @@
 #include <wtf/Forward.h>
 #include <wtf/LoggerHelper.h>
 #include <wtf/MainThread.h>
+#include <wtf/RecursiveLockAdapter.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/Threading.h>
 
@@ -186,17 +187,10 @@
     // Returns true only after the audio thread has been started and then shutdown.
     bool isAudioThreadFinished() const { return m_isAudioThreadFinished; }
 
-    // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
-    void lock(bool& mustReleaseLock);
+    RecursiveLock& graphLock() { return m_graphLock; }
 
-    // Returns true if we own the lock.
-    // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
-    bool tryLock(bool& mustReleaseLock);
-
-    void unlock();
-
     // Returns true if this thread owns the context's lock.
-    bool isGraphOwner() const { return m_graphOwnerThread == &Thread::current(); }
+    bool isGraphOwner() const { return m_graphLock.isOwner(); }
 
     // This is considering 32 is large enough for multiple channels audio.
     // It is somewhat arbitrary and could be increased if necessary.
@@ -232,25 +226,6 @@
     const SecurityOrigin* origin() const;
     void addConsoleMessage(MessageSource, MessageLevel, const String& message);
 
-    class AutoLocker {
-    public:
-        explicit AutoLocker(BaseAudioContext& context)
-            : m_context(context)
-        {
-            m_context.lock(m_mustReleaseLock);
-        }
-
-        ~AutoLocker()
-        {
-            if (m_mustReleaseLock)
-                m_context.unlock();
-        }
-
-    private:
-        BaseAudioContext& m_context;
-        bool m_mustReleaseLock;
-    };
-
     virtual void lazyInitialize();
 
     static bool isSupportedSampleRate(float sampleRate);
@@ -266,8 +241,6 @@
     void clearPendingActivity();
     void setPendingActivity();
 
-    void lockInternal(bool& mustReleaseLock);
-
     virtual void uninitialize();
 
 #if !RELEASE_LOG_DISABLED
@@ -351,8 +324,9 @@
     Ref<AudioListener> m_listener;
 
     std::atomic<Thread*> m_audioThread;
-    std::atomic<Thread*> m_graphOwnerThread; // if the lock is held then this is the thread which owns it, otherwise == nullptr.
 
+    RecursiveLock m_graphLock;
+
     std::unique_ptr<AsyncAudioDecoder> m_audioDecoder;
 
     RefPtr<PendingActivity<BaseAudioContext>> m_pendingActivity;
@@ -373,7 +347,6 @@
 
     unsigned m_connectionCount { 0 };
     State m_state { State::Suspended };
-    Lock m_contextGraphLock;
     bool m_isDeletionScheduled { false };
     bool m_isStopScheduled { false };
     bool m_isInitialized { false };

Modified: trunk/Source/WebCore/Modules/webaudio/ChannelMergerNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/ChannelMergerNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/ChannelMergerNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -66,7 +66,7 @@
     
     initialize();
 
-    BaseAudioContext::AutoLocker contextLocker(context);
+    Locker contextLocker { context.graphLock() };
     disableOutputs();
 }
 

Modified: trunk/Source/WebCore/Modules/webaudio/ConvolverNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/ConvolverNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/ConvolverNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -144,7 +144,7 @@
 
     {
         // The context must be locked since changing the buffer can re-configure the number of channels that are output.
-        BaseAudioContext::AutoLocker contextLocker(context());
+        Locker contextLocker { context().graphLock() };
 
         // Synchronize with process().
         auto locker = holdLock(m_processLock);

Modified: trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/MediaElementAudioSourceNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -110,7 +110,7 @@
 
         {
             // The context must be locked when changing the number of output channels.
-            BaseAudioContext::AutoLocker contextLocker(context());
+            Locker contextLocker { context().graphLock() };
 
             // Do any necesssary re-configuration to the output's number of channels.
             output(0)->setNumberOfChannels(numberOfChannels);

Modified: trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -118,7 +118,7 @@
 
     {
         // The context must be locked when changing the number of output channels.
-        AudioContext::AutoLocker contextLocker(context());
+        Locker contextLocker { context().graphLock() };
 
         // Do any necesssary re-configuration to the output's number of channels.
         output(0)->setNumberOfChannels(numberOfChannels);

Modified: trunk/Source/WebCore/Modules/webaudio/OfflineAudioContext.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/OfflineAudioContext.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/OfflineAudioContext.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -144,7 +144,7 @@
         return;
     }
 
-    AutoLocker locker(*this);
+    Locker locker { graphLock() };
     auto addResult = m_suspendRequests.add(frame, promise.ptr());
     if (!addResult.isNewEntry) {
         promise->reject(Exception { InvalidStateError, "There is already a pending suspend request at this frame"_s });
@@ -183,9 +183,10 @@
 bool OfflineAudioContext::shouldSuspend()
 {
     ASSERT(!isMainThread());
-    // Note that OfflineAutoLocker uses lock() instead of tryLock(). We usually avoid blocking the AudioThread
+    // Note that we are not using a tryLock() here. We usually avoid blocking the AudioThread
     // on lock() but we don't have a choice here since the suspension need to be exact.
-    OfflineAutoLocker locker(*this);
+    // Also, this not a real-time AudioContext so blocking the AudioThread is not as harmful.
+    Locker locker { graphLock() };
     return m_suspendRequests.contains(currentSampleFrame());
 }
 
@@ -197,7 +198,7 @@
 
     RefPtr<DeferredPromise> promise;
     {
-        AutoLocker locker(*this);
+        Locker locker { graphLock() };
         promise = m_suspendRequests.take(frame);
     }
     ASSERT(promise);
@@ -244,12 +245,6 @@
     promise->resolve<IDLInterface<AudioBuffer>>(result.releaseReturnValue());
 }
 
-void OfflineAudioContext::offlineLock(bool& mustReleaseLock)
-{
-    ASSERT(!isMainThread());
-    lockInternal(mustReleaseLock);
-}
-
 void OfflineAudioContext::dispatchEvent(Event& event)
 {
     BaseAudioContext::dispatchEvent(event);

Modified: trunk/Source/WebCore/Modules/webaudio/OfflineAudioContext.h (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/OfflineAudioContext.h	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/OfflineAudioContext.h	2021-05-19 01:51:47 UTC (rev 277709)
@@ -57,28 +57,6 @@
 
     AudioBuffer* renderTarget() const { return destination().renderTarget(); }
 
-    // mustReleaseLock is set to true if we acquired the lock in this method call and caller must unlock(), false if it was previously acquired.
-    void offlineLock(bool& mustReleaseLock);
-
-    class OfflineAutoLocker {
-    public:
-        explicit OfflineAutoLocker(OfflineAudioContext& context)
-            : m_context(context)
-        {
-            m_context.offlineLock(m_mustReleaseLock);
-        }
-
-        ~OfflineAutoLocker()
-        {
-            if (m_mustReleaseLock)
-                m_context.unlock();
-        }
-
-    private:
-        OfflineAudioContext& m_context;
-        bool m_mustReleaseLock;
-    };
-
     // ActiveDOMObject
     const char* activeDOMObjectName() const final;
 

Modified: trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp (277708 => 277709)


--- trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp	2021-05-19 01:47:54 UTC (rev 277708)
+++ trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp	2021-05-19 01:51:47 UTC (rev 277709)
@@ -114,7 +114,7 @@
     INFO_LOG(LOGIDENTIFIER, type);
 
     // Synchronize with any graph changes or changes to channel configuration.
-    AudioContext::AutoLocker contextLocker(context());
+    Locker contextLocker { context().graphLock() };
     waveShaperProcessor()->setOversample(processorType(type));
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to