Changeset 278307 in webkit
- Timestamp:
- Jun 1, 2021, 8:09:47 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 9 edited
-
ChangeLog (modified) (1 diff)
-
Modules/webaudio/AudioBasicProcessorNode.h (modified) (1 diff)
-
Modules/webaudio/WaveShaperDSPKernel.cpp (modified) (3 diffs)
-
Modules/webaudio/WaveShaperDSPKernel.h (modified) (2 diffs)
-
Modules/webaudio/WaveShaperNode.cpp (modified) (6 diffs)
-
Modules/webaudio/WaveShaperNode.h (modified) (2 diffs)
-
Modules/webaudio/WaveShaperNode.idl (modified) (1 diff)
-
Modules/webaudio/WaveShaperProcessor.cpp (modified) (4 diffs)
-
Modules/webaudio/WaveShaperProcessor.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r278306 r278307 1 2021-06-01 Chris Dumez <cdumez@apple.com> 2 3 Fix thread safety issues in WaveShaperProcessor 4 https://bugs.webkit.org/show_bug.cgi?id=226478 5 6 Reviewed by Youenn Fablet. 7 8 Adopt thread safety analysis annotations in WaveShaperProcessor and fix bugs 9 found by clang. In particular, the following issues were fixed: 10 - WaveShaperDSPKernel::latencyTime() was failing to grab the lock before accessing 11 the WaveShaperProcessor's oversample on the rendering thread, even though 12 oversample gets modified on the main thread. 13 - WaveShaperNode::propagatesSilence() was failing to grab the lock before accessing 14 the WaveShaperProcessor's curve on the rendering thread, even though the curve 15 gets modified on the main thread. 16 17 * Modules/webaudio/AudioBasicProcessorNode.h: 18 (WebCore::AudioBasicProcessorNode::processor const): 19 * Modules/webaudio/WaveShaperDSPKernel.cpp: 20 (WebCore::WaveShaperDSPKernel::process): 21 (WebCore::WaveShaperDSPKernel::processCurve): 22 (WebCore::WaveShaperDSPKernel::latencyTime const): 23 * Modules/webaudio/WaveShaperDSPKernel.h: 24 * Modules/webaudio/WaveShaperNode.cpp: 25 (WebCore::WaveShaperNode::create): 26 (WebCore::WaveShaperNode::setCurveForBindings): 27 (WebCore::WaveShaperNode::curveForBindings): 28 (WebCore::WaveShaperNode::setOversampleForBindings): 29 (WebCore::WaveShaperNode::oversampleForBindings const): 30 (WebCore::WaveShaperNode::propagatesSilence const): 31 * Modules/webaudio/WaveShaperNode.h: 32 * Modules/webaudio/WaveShaperNode.idl: 33 * Modules/webaudio/WaveShaperProcessor.cpp: 34 (WebCore::WaveShaperProcessor::setCurveForBindings): 35 (WebCore::WaveShaperProcessor::setOversampleForBindings): 36 (WebCore::WaveShaperProcessor::process): 37 * Modules/webaudio/WaveShaperProcessor.h: 38 1 39 2021-06-01 Chris Dumez <cdumez@apple.com> 2 40 -
trunk/Source/WebCore/Modules/webaudio/AudioBasicProcessorNode.h
r267604 r278307 59 59 60 60 AudioProcessor* processor() { return m_processor.get(); } 61 const AudioProcessor* processor() const { return m_processor.get(); } 62 61 63 std::unique_ptr<AudioProcessor> m_processor; 62 64 }; -
trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.cpp
r267541 r278307 60 60 void WaveShaperDSPKernel::process(const float* source, float* destination, size_t framesToProcess) 61 61 { 62 assertIsHeld(waveShaperProcessor()->processLock()); 62 63 switch (waveShaperProcessor()->oversample()) { 63 64 case WaveShaperProcessor::OverSampleNone: … … 80 81 ASSERT(source && destination && waveShaperProcessor()); 81 82 83 assertIsHeld(waveShaperProcessor()->processLock()); 82 84 Float32Array* curve = waveShaperProcessor()->curve(); 83 85 if (!curve) { … … 164 166 double WaveShaperDSPKernel::latencyTime() const 165 167 { 168 if (!waveShaperProcessor()->processLock().tryLock()) 169 return std::numeric_limits<double>::infinity(); 170 171 Locker locker { AdoptLock, waveShaperProcessor()->processLock() }; 172 166 173 size_t latencyFrames = 0; 167 WaveShaperDSPKernel* kernel = const_cast<WaveShaperDSPKernel*>(this); 168 169 switch (kernel->waveShaperProcessor()->oversample()) { 174 switch (waveShaperProcessor()->oversample()) { 170 175 case WaveShaperProcessor::OverSampleNone: 171 176 break; -
trunk/Source/WebCore/Modules/webaudio/WaveShaperDSPKernel.h
r266417 r278307 41 41 42 42 // AudioDSPKernel 43 void process(const float* source, float* dest, size_t framesToProcess) override;44 void reset() override;45 double tailTime() const override{ return 0; }46 double latencyTime() const override;43 void process(const float* source, float* dest, size_t framesToProcess) final; 44 void reset() final; 45 double tailTime() const final { return 0; } 46 double latencyTime() const final; 47 47 48 48 // Oversampling requires more resources, so let's only allocate them if needed. … … 60 60 61 61 WaveShaperProcessor* waveShaperProcessor() { return static_cast<WaveShaperProcessor*>(processor()); } 62 const WaveShaperProcessor* waveShaperProcessor() const { return static_cast<const WaveShaperProcessor*>(processor()); } 62 63 63 64 // Oversampling. -
trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.cpp
r277709 r278307 54 54 55 55 if (curve) { 56 result = node->setCurve (WTFMove(curve));56 result = node->setCurveForBindings(WTFMove(curve)); 57 57 if (result.hasException()) 58 58 return result.releaseException(); 59 59 } 60 60 61 node->setOversample (options.oversample);61 node->setOversampleForBindings(options.oversample); 62 62 63 63 return node; … … 72 72 } 73 73 74 ExceptionOr<void> WaveShaperNode::setCurve (RefPtr<Float32Array>&& curve)74 ExceptionOr<void> WaveShaperNode::setCurveForBindings(RefPtr<Float32Array>&& curve) 75 75 { 76 76 ASSERT(isMainThread()); … … 86 86 } 87 87 88 waveShaperProcessor()->setCurve (curve.get());88 waveShaperProcessor()->setCurveForBindings(curve.get()); 89 89 return { }; 90 90 } 91 91 92 Float32Array* WaveShaperNode::curve ()92 Float32Array* WaveShaperNode::curveForBindings() 93 93 { 94 return waveShaperProcessor()->curve(); 94 ASSERT(isMainThread()); 95 return waveShaperProcessor()->curveForBindings(); 95 96 } 96 97 … … 109 110 } 110 111 111 void WaveShaperNode::setOversample (OverSampleType type)112 void WaveShaperNode::setOversampleForBindings(OverSampleType type) 112 113 { 113 114 ASSERT(isMainThread()); … … 116 117 // Synchronize with any graph changes or changes to channel configuration. 117 118 Locker contextLocker { context().graphLock() }; 118 waveShaperProcessor()->setOversample (processorType(type));119 waveShaperProcessor()->setOversampleForBindings(processorType(type)); 119 120 } 120 121 121 auto WaveShaperNode::oversample () const -> OverSampleType122 auto WaveShaperNode::oversampleForBindings() const -> OverSampleType 122 123 { 123 switch (const_cast<WaveShaperNode*>(this)->waveShaperProcessor()->oversample()) { 124 ASSERT(isMainThread()); 125 switch (waveShaperProcessor()->oversampleForBindings()) { 124 126 case WaveShaperProcessor::OverSampleNone: 125 127 return OverSampleType::None; … … 135 137 bool WaveShaperNode::propagatesSilence() const 136 138 { 137 auto curve = const_cast<WaveShaperNode*>(this)->curve(); 139 if (!waveShaperProcessor()->processLock().tryLock()) 140 return false; 141 142 Locker locker { AdoptLock, waveShaperProcessor()->processLock() }; 143 auto curve = waveShaperProcessor()->curve(); 138 144 return !curve || !curve->length(); 139 145 } -
trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.h
r265765 r278307 41 41 42 42 // setCurve() is called on the main thread. 43 ExceptionOr<void> setCurve (RefPtr<Float32Array>&&);44 Float32Array* curve ();43 ExceptionOr<void> setCurveForBindings(RefPtr<Float32Array>&&); 44 Float32Array* curveForBindings(); 45 45 46 void setOversample (OverSampleType);47 OverSampleType oversample () const;46 void setOversampleForBindings(OverSampleType); 47 OverSampleType oversampleForBindings() const; 48 48 49 49 double latency() const { return latencyTime(); } … … 55 55 56 56 WaveShaperProcessor* waveShaperProcessor() { return static_cast<WaveShaperProcessor*>(processor()); } 57 const WaveShaperProcessor* waveShaperProcessor() const { return static_cast<const WaveShaperProcessor*>(processor()); } 57 58 }; 58 59 -
trunk/Source/WebCore/Modules/webaudio/WaveShaperNode.idl
r276715 r278307 30 30 [EnabledBySetting=WebAudio] constructor(BaseAudioContext context, optional WaveShaperOptions options); 31 31 32 attribute Float32Array? curve;33 attribute OverSampleType oversample;32 [ImplementedAs=curveForBindings] attribute Float32Array? curve; 33 [ImplementedAs=oversampleForBindings] attribute OverSampleType oversample; 34 34 }; -
trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.cpp
r277932 r278307 49 49 } 50 50 51 void WaveShaperProcessor::setCurve (Float32Array* curve)51 void WaveShaperProcessor::setCurveForBindings(Float32Array* curve) 52 52 { 53 ASSERT(isMainThread()); 53 54 // This synchronizes with process(). 54 55 Locker locker { m_processLock }; … … 57 58 } 58 59 59 void WaveShaperProcessor::setOversample (OverSampleType oversample)60 void WaveShaperProcessor::setOversampleForBindings(OverSampleType oversample) 60 61 { 62 ASSERT(isMainThread()); 61 63 // This synchronizes with process(). 62 64 Locker locker { m_processLock }; … … 64 66 m_oversample = oversample; 65 67 66 if (oversample != OverSampleNone) { 67 for (auto& audioDSPKernel : m_kernels) { 68 WaveShaperDSPKernel& kernel = static_cast<WaveShaperDSPKernel&>(*audioDSPKernel); 69 kernel.lazyInitializeOversampling(); 70 } 71 } 68 if (oversample == OverSampleNone) 69 return; 70 71 for (auto& audioDSPKernel : m_kernels) 72 static_cast<WaveShaperDSPKernel&>(*audioDSPKernel).lazyInitializeOversampling(); 72 73 } 73 74 … … 93 94 94 95 // For each channel of our input, process using the corresponding WaveShaperDSPKernel into the output channel. 95 for ( unsignedi = 0; i < m_kernels.size(); ++i)96 m_kernels[i]->process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess);96 for (size_t i = 0; i < m_kernels.size(); ++i) 97 static_cast<WaveShaperDSPKernel&>(*m_kernels[i]).process(source->channel(i)->data(), destination->channel(i)->mutableData(), framesToProcess); 97 98 } 98 99 -
trunk/Source/WebCore/Modules/webaudio/WaveShaperProcessor.h
r268001 r278307 49 49 virtual ~WaveShaperProcessor(); 50 50 51 std::unique_ptr<AudioDSPKernel> createKernel() override;51 std::unique_ptr<AudioDSPKernel> createKernel() final; 52 52 53 void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) override;53 void process(const AudioBus* source, AudioBus* destination, size_t framesToProcess) final; 54 54 55 void setCurve(Float32Array*); 56 Float32Array* curve() { return m_curve.get(); } 55 void setCurveForBindings(Float32Array*); 56 Float32Array* curveForBindings() WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_curve.get(); } // Doesn't grab the lock, only safe to call on the main thread. 57 Float32Array* curve() const WTF_REQUIRES_LOCK(m_processLock) { return m_curve.get(); } 57 58 58 void setOversample(OverSampleType); 59 OverSampleType oversample() const { return m_oversample; } 59 void setOversampleForBindings(OverSampleType); 60 OverSampleType oversampleForBindings() const WTF_IGNORES_THREAD_SAFETY_ANALYSIS { ASSERT(isMainThread()); return m_oversample; } // Doesn't grab the lock, only safe to call on the main thread. 61 OverSampleType oversample() const WTF_REQUIRES_LOCK(m_processLock) { return m_oversample; } 62 63 Lock& processLock() const WTF_RETURNS_LOCK(m_processLock) { return m_processLock; } 60 64 61 65 private: 62 66 // m_curve represents the non-linear shaping curve. 63 RefPtr<Float32Array> m_curve ;67 RefPtr<Float32Array> m_curve WTF_GUARDED_BY_LOCK(m_processLock); 64 68 65 OverSampleType m_oversample { OverSampleNone };69 OverSampleType m_oversample WTF_GUARDED_BY_LOCK(m_processLock) { OverSampleNone }; 66 70 67 71 // This synchronizes process() with setCurve().
Note:
See TracChangeset
for help on using the changeset viewer.