Backed out changeset f594e6f00208 (bug 1940883) for causing crashes in bug 1941164.
[gecko.git] / dom / media / GraphRunner.cpp
blob28fe538157984e37083ebc5b089bec7bde34fb14
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/. */
7 #include "GraphRunner.h"
9 #include "GraphDriver.h"
10 #include "MediaTrackGraph.h"
11 #include "MediaTrackGraphImpl.h"
12 #include "nsISupportsImpl.h"
13 #include "nsISupportsPriority.h"
14 #include "prthread.h"
15 #include "Tracing.h"
16 #include "mozilla/dom/WorkletThread.h"
17 #include "audio_thread_priority.h"
18 #ifdef MOZ_WIDGET_ANDROID
19 # include "AndroidProcess.h"
20 #endif // MOZ_WIDGET_ANDROID
22 namespace mozilla {
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));
34 GraphRunner::~GraphRunner() {
35 MOZ_ASSERT(mThreadState == ThreadState::Shutdown);
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;
47 nsCOMPtr<nsISupportsPriority> supportsPriority = do_QueryInterface(thread);
48 MOZ_ASSERT(supportsPriority);
49 MOZ_ALWAYS_SUCCEEDS(
50 supportsPriority->SetPriority(nsISupportsPriority::PRIORITY_HIGHEST));
52 return do_AddRef(new GraphRunner(aGraph, thread.forget()));
55 void GraphRunner::Shutdown() {
57 MonitorAutoLock lock(mMonitor);
58 MOZ_ASSERT(mThreadState == ThreadState::Wait);
59 mThreadState = ThreadState::Shutdown;
60 mMonitor.Notify();
62 mThread->Shutdown();
65 auto GraphRunner::OneIteration(GraphTime aStateTime, GraphTime aIterationEnd,
66 MixerCallbackReceiver* aMixerReceiver)
67 -> IterationResult {
68 TRACE("GraphRunner::OneIteration");
70 MonitorAutoLock lock(mMonitor);
71 MOZ_ASSERT(mThreadState == ThreadState::Wait);
72 mIterationState =
73 Some(IterationState(aStateTime, aIterationEnd, aMixerReceiver));
75 #ifdef DEBUG
76 if (const auto* audioDriver =
77 mGraph->CurrentDriver()->AsAudioCallbackDriver()) {
78 mAudioDriverThreadId = audioDriver->ThreadId();
79 } else if (const auto* clockDriver =
80 mGraph->CurrentDriver()->AsSystemClockDriver()) {
81 mClockDriverThread = clockDriver->Thread();
82 } else {
83 MOZ_CRASH("Unknown GraphDriver");
85 #endif
86 // Signal that mIterationState was updated
87 mThreadState = ThreadState::Run;
88 mMonitor.Notify();
89 // Wait for mIterationResult to update
90 do {
91 mMonitor.Wait();
92 } while (mThreadState == ThreadState::Run);
94 #ifdef DEBUG
95 mAudioDriverThreadId = std::thread::id();
96 mClockDriverThread = nullptr;
97 #endif
99 mIterationState = Nothing();
101 IterationResult result = std::move(mIterationResult);
102 mIterationResult = IterationResult();
103 return result;
106 #ifdef MOZ_WIDGET_ANDROID
107 namespace {
108 void PromoteRenderingThreadAndroid() {
109 MOZ_LOG(gMediaTrackGraphLog, LogLevel::Debug,
110 ("GraphRunner default thread priority: %d",
111 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
112 java::sdk::Process::SetThreadPriority(
113 java::sdk::Process::THREAD_PRIORITY_URGENT_AUDIO);
114 MOZ_LOG(gMediaTrackGraphLog, LogLevel::Debug,
115 ("GraphRunner promoted thread priority: %d",
116 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
118 }; // namespace
119 #endif // MOZ_WIDGET_ANDROID
121 NS_IMETHODIMP GraphRunner::Run() {
122 #ifndef XP_LINUX
123 atp_handle* handle =
124 atp_promote_current_thread_to_real_time(0, mGraph->GraphRate());
125 #endif
127 #ifdef MOZ_WIDGET_ANDROID
128 PromoteRenderingThreadAndroid();
129 #endif // MOZ_WIDGET_ANDROID
131 nsCOMPtr<nsIThreadInternal> threadInternal = do_QueryInterface(mThread);
132 threadInternal->SetObserver(mGraph);
134 MonitorAutoLock lock(mMonitor);
135 while (true) {
136 while (mThreadState == ThreadState::Wait) {
137 mMonitor.Wait(); // Wait for mIterationState to update or for shutdown
139 if (mThreadState == ThreadState::Shutdown) {
140 break;
142 MOZ_DIAGNOSTIC_ASSERT(mIterationState.isSome());
143 TRACE("GraphRunner::Run");
144 mIterationResult = mGraph->OneIterationImpl(
145 mIterationState->StateTime(), mIterationState->IterationEnd(),
146 mIterationState->MixerReceiver());
147 // Signal that mIterationResult was updated
148 mThreadState = ThreadState::Wait;
149 mMonitor.Notify();
152 #ifndef XP_LINUX
153 if (handle) {
154 atp_demote_current_thread_from_real_time(handle);
156 #endif
158 return NS_OK;
161 bool GraphRunner::OnThread() const { return mThread->IsOnCurrentThread(); }
163 #ifdef DEBUG
164 bool GraphRunner::InDriverIteration(const GraphDriver* aDriver) const {
165 if (!OnThread()) {
166 return false;
169 if (const auto* audioDriver = aDriver->AsAudioCallbackDriver()) {
170 return audioDriver->ThreadId() == mAudioDriverThreadId;
173 if (const auto* clockDriver = aDriver->AsSystemClockDriver()) {
174 return clockDriver->Thread() == mClockDriverThread;
177 MOZ_CRASH("Unknown driver");
179 #endif
181 } // namespace mozilla