GraphRunner.cpp (5353B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 6 7 #include "GraphRunner.h" 8 9 #include "GraphDriver.h" 10 #include "MediaTrackGraph.h" 11 #include "MediaTrackGraphImpl.h" 12 #include "Tracing.h" 13 #include "audio_thread_priority.h" 14 #include "mozilla/dom/WorkletThread.h" 15 #include "nsISupportsImpl.h" 16 #include "nsISupportsPriority.h" 17 #include "prthread.h" 18 #ifdef MOZ_WIDGET_ANDROID 19 # include "AndroidProcess.h" 20 #endif // MOZ_WIDGET_ANDROID 21 22 namespace mozilla { 23 24 GraphRunner::GraphRunner(MediaTrackGraphImpl* aGraph, 25 already_AddRefed<nsIThread> aThread) 26 : Runnable("GraphRunner"), 27 mMonitor("GraphRunner::mMonitor"), 28 mGraph(aGraph), 29 mThreadState(ThreadState::Wait), 30 mThread(aThread) { 31 mThread->Dispatch(do_AddRef(this)); 32 } 33 34 GraphRunner::~GraphRunner() { 35 MOZ_ASSERT(mThreadState == ThreadState::Shutdown); 36 } 37 38 /* static */ 39 already_AddRefed<GraphRunner> GraphRunner::Create(MediaTrackGraphImpl* aGraph) { 40 nsCOMPtr<nsIThread> thread; 41 nsIThreadManager::ThreadCreationOptions options = { 42 .stackSize = mozilla::dom::WorkletThread::StackSize()}; 43 if (NS_WARN_IF(NS_FAILED(NS_NewNamedThread( 44 "GraphRunner", getter_AddRefs(thread), nullptr, options)))) { 45 return nullptr; 46 } 47 nsCOMPtr<nsISupportsPriority> supportsPriority = do_QueryInterface(thread); 48 MOZ_ASSERT(supportsPriority); 49 MOZ_ALWAYS_SUCCEEDS( 50 supportsPriority->SetPriority(nsISupportsPriority::PRIORITY_HIGHEST)); 51 52 return do_AddRef(new GraphRunner(aGraph, thread.forget())); 53 } 54 55 void GraphRunner::Shutdown() { 56 { 57 MonitorAutoLock lock(mMonitor); 58 MOZ_ASSERT(mThreadState == ThreadState::Wait); 59 mThreadState = ThreadState::Shutdown; 60 mMonitor.Notify(); 61 } 62 mThread->Shutdown(); 63 } 64 65 auto GraphRunner::OneIteration(GraphTime aStateTime, 66 MixerCallbackReceiver* aMixerReceiver) 67 -> IterationResult { 68 TRACE("GraphRunner::OneIteration"); 69 70 MonitorAutoLock lock(mMonitor); 71 MOZ_ASSERT(mThreadState == ThreadState::Wait); 72 mIterationState = Some(IterationState(aStateTime, aMixerReceiver)); 73 74 #ifdef DEBUG 75 if (const auto* audioDriver = 76 mGraph->CurrentDriver()->AsAudioCallbackDriver()) { 77 mAudioDriverThreadId = audioDriver->ThreadId(); 78 } else if (const auto* clockDriver = 79 mGraph->CurrentDriver()->AsSystemClockDriver()) { 80 mClockDriverThread = clockDriver->Thread(); 81 } else { 82 MOZ_CRASH("Unknown GraphDriver"); 83 } 84 #endif 85 // Signal that mIterationState was updated 86 mThreadState = ThreadState::Run; 87 mMonitor.Notify(); 88 // Wait for mIterationResult to update 89 do { 90 mMonitor.Wait(); 91 } while (mThreadState == ThreadState::Run); 92 93 #ifdef DEBUG 94 mAudioDriverThreadId = std::thread::id(); 95 mClockDriverThread = nullptr; 96 #endif 97 98 mIterationState = Nothing(); 99 100 IterationResult result = std::move(mIterationResult); 101 mIterationResult = IterationResult(); 102 return result; 103 } 104 105 #ifdef MOZ_WIDGET_ANDROID 106 namespace { 107 void PromoteRenderingThreadAndroid() { 108 MOZ_LOG(gMediaTrackGraphLog, LogLevel::Debug, 109 ("GraphRunner default thread priority: %d", 110 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid()))); 111 java::sdk::Process::SetThreadPriority( 112 java::sdk::Process::THREAD_PRIORITY_URGENT_AUDIO); 113 MOZ_LOG(gMediaTrackGraphLog, LogLevel::Debug, 114 ("GraphRunner promoted thread priority: %d", 115 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid()))); 116 } 117 }; // namespace 118 #endif // MOZ_WIDGET_ANDROID 119 120 NS_IMETHODIMP GraphRunner::Run() { 121 #ifndef XP_LINUX 122 atp_handle* handle = 123 atp_promote_current_thread_to_real_time(0, mGraph->GraphRate()); 124 #endif 125 126 #ifdef MOZ_WIDGET_ANDROID 127 PromoteRenderingThreadAndroid(); 128 #endif // MOZ_WIDGET_ANDROID 129 130 nsCOMPtr<nsIThreadInternal> threadInternal = do_QueryInterface(mThread); 131 threadInternal->SetObserver(mGraph); 132 133 MonitorAutoLock lock(mMonitor); 134 while (true) { 135 while (mThreadState == ThreadState::Wait) { 136 mMonitor.Wait(); // Wait for mIterationState to update or for shutdown 137 } 138 if (mThreadState == ThreadState::Shutdown) { 139 break; 140 } 141 MOZ_DIAGNOSTIC_ASSERT(mIterationState.isSome()); 142 TRACE("GraphRunner::Run"); 143 mIterationResult = mGraph->OneIterationImpl( 144 mIterationState->StateTime(), mIterationState->MixerReceiver()); 145 // Signal that mIterationResult was updated 146 mThreadState = ThreadState::Wait; 147 mMonitor.Notify(); 148 } 149 150 #ifndef XP_LINUX 151 if (handle) { 152 atp_demote_current_thread_from_real_time(handle); 153 } 154 #endif 155 156 return NS_OK; 157 } 158 159 bool GraphRunner::OnThread() const { return mThread->IsOnCurrentThread(); } 160 161 #ifdef DEBUG 162 bool GraphRunner::InDriverIteration(const GraphDriver* aDriver) const { 163 if (!OnThread()) { 164 return false; 165 } 166 167 if (const auto* audioDriver = aDriver->AsAudioCallbackDriver()) { 168 return audioDriver->ThreadId() == mAudioDriverThreadId; 169 } 170 171 if (const auto* clockDriver = aDriver->AsSystemClockDriver()) { 172 return clockDriver->Thread() == mClockDriverThread; 173 } 174 175 MOZ_CRASH("Unknown driver"); 176 } 177 #endif 178 179 } // namespace mozilla