2019-03-06 23:12:25 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "GraphRunner.h"
|
|
|
|
|
|
|
|
#include "GraphDriver.h"
|
|
|
|
#include "MediaStreamGraph.h"
|
|
|
|
#include "MediaStreamGraphImpl.h"
|
2019-03-14 16:40:07 +03:00
|
|
|
#include "mozilla/dom/WorkletThread.h"
|
2019-03-06 23:12:25 +03:00
|
|
|
#include "nsISupportsImpl.h"
|
|
|
|
#include "prthread.h"
|
|
|
|
#include "Tracing.h"
|
2019-06-21 22:51:22 +03:00
|
|
|
#include "audio_thread_priority.h"
|
2019-03-06 23:12:25 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
static void Start(void* aArg) {
|
2019-06-07 00:07:29 +03:00
|
|
|
NS_SetCurrentThreadName("GraphRunner");
|
2019-03-06 23:12:25 +03:00
|
|
|
GraphRunner* th = static_cast<GraphRunner*>(aArg);
|
|
|
|
th->Run();
|
|
|
|
}
|
|
|
|
|
|
|
|
GraphRunner::GraphRunner(MediaStreamGraphImpl* aGraph)
|
|
|
|
: mMonitor("GraphRunner::mMonitor"),
|
|
|
|
mGraph(aGraph),
|
2019-03-11 16:18:04 +03:00
|
|
|
mStateEnd(0),
|
|
|
|
mStillProcessing(true),
|
2019-03-26 01:49:02 +03:00
|
|
|
mThreadState(ThreadState::Wait),
|
2019-03-11 16:18:04 +03:00
|
|
|
// Note that mThread needs to be initialized last, as it may pre-empt the
|
|
|
|
// thread running this ctor and enter Run() with uninitialized members.
|
2019-03-06 23:12:25 +03:00
|
|
|
mThread(PR_CreateThread(PR_SYSTEM_THREAD, &Start, this,
|
|
|
|
PR_PRIORITY_URGENT, PR_GLOBAL_THREAD,
|
|
|
|
PR_JOINABLE_THREAD, 0)) {
|
|
|
|
MOZ_COUNT_CTOR(GraphRunner);
|
|
|
|
}
|
|
|
|
|
|
|
|
GraphRunner::~GraphRunner() {
|
|
|
|
MOZ_COUNT_DTOR(GraphRunner);
|
2019-03-26 01:49:02 +03:00
|
|
|
MOZ_ASSERT(mThreadState == ThreadState::Shutdown);
|
2019-03-06 23:12:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void GraphRunner::Shutdown() {
|
2019-03-26 03:13:55 +03:00
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
MOZ_ASSERT(mThreadState == ThreadState::Wait);
|
|
|
|
mThreadState = ThreadState::Shutdown;
|
|
|
|
mMonitor.Notify();
|
|
|
|
}
|
|
|
|
// We need to wait for runner thread shutdown here for the sake of the
|
|
|
|
// xpcomWillShutdown case, so that the main thread is not shut down before
|
|
|
|
// cleanup messages are sent for objects destroyed in
|
|
|
|
// CycleCollectedJSContext shutdown.
|
|
|
|
PR_JoinThread(mThread);
|
|
|
|
mThread = nullptr;
|
2019-03-06 23:12:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphRunner::OneIteration(GraphTime aStateEnd) {
|
|
|
|
TRACE_AUDIO_CALLBACK();
|
|
|
|
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
2019-03-26 01:49:02 +03:00
|
|
|
MOZ_ASSERT(mThreadState == ThreadState::Wait);
|
2019-03-06 23:12:25 +03:00
|
|
|
mStateEnd = aStateEnd;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (auto audioDriver = mGraph->CurrentDriver()->AsAudioCallbackDriver()) {
|
|
|
|
mAudioDriverThreadId = audioDriver->ThreadId();
|
|
|
|
} else if (auto clockDriver =
|
|
|
|
mGraph->CurrentDriver()->AsSystemClockDriver()) {
|
|
|
|
mClockDriverThread = clockDriver->Thread();
|
|
|
|
} else {
|
|
|
|
MOZ_CRASH("Unknown GraphDriver");
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-26 01:49:02 +03:00
|
|
|
// Signal that mStateEnd was updated
|
|
|
|
mThreadState = ThreadState::Run;
|
|
|
|
mMonitor.Notify();
|
|
|
|
// Wait for mStillProcessing to update
|
|
|
|
do {
|
|
|
|
mMonitor.Wait();
|
|
|
|
} while (mThreadState == ThreadState::Run);
|
2019-03-06 23:12:25 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
mAudioDriverThreadId = std::thread::id();
|
|
|
|
mClockDriverThread = nullptr;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return mStillProcessing;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GraphRunner::Run() {
|
|
|
|
PR_SetCurrentThreadName("GraphRunner");
|
2019-06-21 22:51:22 +03:00
|
|
|
|
|
|
|
atp_handle* handle =
|
|
|
|
atp_promote_current_thread_to_real_time(0, mGraph->GraphRate());
|
|
|
|
|
2019-03-06 23:12:25 +03:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
while (true) {
|
2019-03-26 01:49:02 +03:00
|
|
|
while (mThreadState == ThreadState::Wait) {
|
|
|
|
mMonitor.Wait(); // Wait for mStateEnd to update or for shutdown
|
|
|
|
}
|
|
|
|
if (mThreadState == ThreadState::Shutdown) {
|
2019-03-06 23:12:25 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
TRACE();
|
|
|
|
mStillProcessing = mGraph->OneIterationImpl(mStateEnd);
|
2019-03-26 01:49:02 +03:00
|
|
|
// Signal that mStillProcessing was updated
|
|
|
|
mThreadState = ThreadState::Wait;
|
|
|
|
mMonitor.Notify();
|
2019-03-06 23:12:25 +03:00
|
|
|
}
|
2019-03-14 16:40:07 +03:00
|
|
|
|
2019-06-21 22:51:22 +03:00
|
|
|
if (handle) {
|
|
|
|
atp_demote_current_thread_from_real_time(handle);
|
|
|
|
}
|
|
|
|
|
2019-03-14 16:40:07 +03:00
|
|
|
dom::WorkletThread::DeleteCycleCollectedJSContext();
|
2019-03-06 23:12:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GraphRunner::OnThread() { return PR_GetCurrentThread() == mThread; }
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
bool GraphRunner::RunByGraphDriver(GraphDriver* aDriver) {
|
|
|
|
if (!OnThread()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto audioDriver = aDriver->AsAudioCallbackDriver()) {
|
|
|
|
return audioDriver->ThreadId() == mAudioDriverThreadId;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto clockDriver = aDriver->AsSystemClockDriver()) {
|
|
|
|
return clockDriver->Thread() == mClockDriverThread;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_CRASH("Unknown driver");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} // namespace mozilla
|