tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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