Bug 1772053 - Enable dynamic code disable mitigations only on Windows 10 1703+ r...
[gecko.git] / dom / media / GraphRunner.cpp
blob0cb7135d8b03e1e4e1595a26f51213bcacd39e20
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 "audio_thread_priority.h"
17 #ifdef MOZ_WIDGET_ANDROID
18 # include "AndroidProcess.h"
19 #endif // MOZ_WIDGET_ANDROID
21 namespace mozilla {
23 GraphRunner::GraphRunner(MediaTrackGraphImpl* aGraph,
24 already_AddRefed<nsIThread> aThread)
25 : Runnable("GraphRunner"),
26 mMonitor("GraphRunner::mMonitor"),
27 mGraph(aGraph),
28 mThreadState(ThreadState::Wait),
29 mThread(aThread) {
30 mThread->Dispatch(do_AddRef(this));
33 GraphRunner::~GraphRunner() {
34 MOZ_ASSERT(mThreadState == ThreadState::Shutdown);
37 /* static */
38 already_AddRefed<GraphRunner> GraphRunner::Create(MediaTrackGraphImpl* aGraph) {
39 nsCOMPtr<nsIThread> thread;
40 if (NS_WARN_IF(NS_FAILED(
41 NS_NewNamedThread("GraphRunner", getter_AddRefs(thread))))) {
42 return nullptr;
44 nsCOMPtr<nsISupportsPriority> supportsPriority = do_QueryInterface(thread);
45 MOZ_ASSERT(supportsPriority);
46 MOZ_ALWAYS_SUCCEEDS(
47 supportsPriority->SetPriority(nsISupportsPriority::PRIORITY_HIGHEST));
49 return do_AddRef(new GraphRunner(aGraph, thread.forget()));
52 void GraphRunner::Shutdown() {
54 MonitorAutoLock lock(mMonitor);
55 MOZ_ASSERT(mThreadState == ThreadState::Wait);
56 mThreadState = ThreadState::Shutdown;
57 mMonitor.Notify();
59 mThread->Shutdown();
62 auto GraphRunner::OneIteration(GraphTime aStateTime, GraphTime aIterationEnd,
63 AudioMixer* aMixer) -> IterationResult {
64 TRACE("GraphRunner::OneIteration");
66 MonitorAutoLock lock(mMonitor);
67 MOZ_ASSERT(mThreadState == ThreadState::Wait);
68 mIterationState = Some(IterationState(aStateTime, aIterationEnd, aMixer));
70 #ifdef DEBUG
71 if (const auto* audioDriver =
72 mGraph->CurrentDriver()->AsAudioCallbackDriver()) {
73 mAudioDriverThreadId = audioDriver->ThreadId();
74 } else if (const auto* clockDriver =
75 mGraph->CurrentDriver()->AsSystemClockDriver()) {
76 mClockDriverThread = clockDriver->Thread();
77 } else {
78 MOZ_CRASH("Unknown GraphDriver");
80 #endif
81 // Signal that mIterationState was updated
82 mThreadState = ThreadState::Run;
83 mMonitor.Notify();
84 // Wait for mIterationResult to update
85 do {
86 mMonitor.Wait();
87 } while (mThreadState == ThreadState::Run);
89 #ifdef DEBUG
90 mAudioDriverThreadId = std::thread::id();
91 mClockDriverThread = nullptr;
92 #endif
94 mIterationState = Nothing();
96 IterationResult result = std::move(mIterationResult);
97 mIterationResult = IterationResult();
98 return result;
101 #ifdef MOZ_WIDGET_ANDROID
102 namespace {
103 void PromoteRenderingThreadAndroid() {
104 MOZ_LOG(gMediaTrackGraphLog, LogLevel::Debug,
105 ("GraphRunner default thread priority: %d",
106 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
107 java::sdk::Process::SetThreadPriority(
108 java::sdk::Process::THREAD_PRIORITY_URGENT_AUDIO);
109 MOZ_LOG(gMediaTrackGraphLog, LogLevel::Debug,
110 ("GraphRunner promoted thread priority: %d",
111 java::sdk::Process::GetThreadPriority(java::sdk::Process::MyTid())));
113 }; // namespace
114 #endif // MOZ_WIDGET_ANDROID
116 NS_IMETHODIMP GraphRunner::Run() {
117 #ifndef XP_LINUX
118 atp_handle* handle =
119 atp_promote_current_thread_to_real_time(0, mGraph->GraphRate());
120 #endif
122 #ifdef MOZ_WIDGET_ANDROID
123 PromoteRenderingThreadAndroid();
124 #endif // MOZ_WIDGET_ANDROID
126 nsCOMPtr<nsIThreadInternal> threadInternal = do_QueryInterface(mThread);
127 threadInternal->SetObserver(mGraph);
129 MonitorAutoLock lock(mMonitor);
130 while (true) {
131 while (mThreadState == ThreadState::Wait) {
132 mMonitor.Wait(); // Wait for mIterationState to update or for shutdown
134 if (mThreadState == ThreadState::Shutdown) {
135 break;
137 MOZ_DIAGNOSTIC_ASSERT(mIterationState.isSome());
138 TRACE("GraphRunner::Run");
139 mIterationResult = mGraph->OneIterationImpl(mIterationState->StateTime(),
140 mIterationState->IterationEnd(),
141 mIterationState->Mixer());
142 // Signal that mIterationResult was updated
143 mThreadState = ThreadState::Wait;
144 mMonitor.Notify();
147 #ifndef XP_LINUX
148 if (handle) {
149 atp_demote_current_thread_from_real_time(handle);
151 #endif
153 return NS_OK;
156 bool GraphRunner::OnThread() const {
157 return mThread->EventTarget()->IsOnCurrentThread();
160 #ifdef DEBUG
161 bool GraphRunner::InDriverIteration(const GraphDriver* aDriver) const {
162 if (!OnThread()) {
163 return false;
166 if (const auto* audioDriver = aDriver->AsAudioCallbackDriver()) {
167 return audioDriver->ThreadId() == mAudioDriverThreadId;
170 if (const auto* clockDriver = aDriver->AsSystemClockDriver()) {
171 return clockDriver->Thread() == mClockDriverThread;
174 MOZ_CRASH("Unknown driver");
176 #endif
178 } // namespace mozilla