Backed out changeset e22428605dbb (bug 1875661) for causing bp-nu bustages in RefPtr.h and for causing mochitests assertion failures in WeakPtr.h. CLOSED TREE

This commit is contained in:
Stanca Serban 2024-01-24 21:11:11 +02:00
parent 221d7acc5b
commit c8b4d1c3b8
9 changed files with 102 additions and 143 deletions

View File

@ -173,13 +173,8 @@ CanvasManagerParent::AllocPCanvasParent() {
MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent without ID");
return nullptr;
}
RefPtr<TaskQueue> taskQueue = CanvasRenderThread::CreateWorkerTaskQueue();
if (NS_WARN_IF(!taskQueue)) {
MOZ_ASSERT_UNREACHABLE("AllocPCanvasParent failed to create task queue!");
return nullptr;
}
return MakeAndAddRef<layers::CanvasTranslator>(
std::move(taskQueue), mSharedSurfacesHolder, mContentId, mId);
return MakeAndAddRef<layers::CanvasTranslator>(mSharedSurfacesHolder,
mContentId, mId);
}
mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot(

View File

@ -34,8 +34,7 @@ static bool sCanvasRenderThreadEverStarted = false;
CanvasRenderThread::CanvasRenderThread(nsCOMPtr<nsIThread>&& aThread,
nsCOMPtr<nsIThreadPool>&& aWorkers,
bool aCreatedThread)
: mMutex("CanvasRenderThread::mMutex"),
mThread(std::move(aThread)),
: mThread(std::move(aThread)),
mWorkers(std::move(aWorkers)),
mCreatedThread(aCreatedThread) {}
@ -149,27 +148,8 @@ void CanvasRenderThread::Shutdown() {
return;
}
// This closes all of the IPDL actors with possibly active task queues.
CanvasManagerParent::Shutdown();
// Any task queues that are in the process of shutting down are tracked in
// mPendingShutdownTaskQueues. We need to block on each one until all events
// are flushed so that we can safely teardown RemoteTextureMap afterwards.
while (true) {
RefPtr<TaskQueue> taskQueue;
{
MutexAutoLock lock(sCanvasRenderThread->mMutex);
auto& pendingQueues = sCanvasRenderThread->mPendingShutdownTaskQueues;
if (pendingQueues.IsEmpty()) {
break;
}
taskQueue = pendingQueues.PopLastElement();
}
taskQueue->AwaitShutdownAndIdle();
}
// Null out sCanvasRenderThread before we enter synchronous Shutdown,
// from here on we are to be considered shut down for our consumers.
nsCOMPtr<nsIThreadPool> oldWorkers = sCanvasRenderThread->mWorkers;
@ -227,43 +207,15 @@ already_AddRefed<nsIThread> CanvasRenderThread::GetCanvasRenderThread() {
/* static */ already_AddRefed<TaskQueue>
CanvasRenderThread::CreateWorkerTaskQueue() {
if (!sCanvasRenderThread) {
if (!sCanvasRenderThread || !sCanvasRenderThread->mWorkers) {
return nullptr;
}
if (sCanvasRenderThread->mWorkers) {
return TaskQueue::Create(do_AddRef(sCanvasRenderThread->mWorkers),
"CanvasWorker")
.forget();
}
return TaskQueue::Create(do_AddRef(sCanvasRenderThread->mThread),
return TaskQueue::Create(do_AddRef(sCanvasRenderThread->mWorkers),
"CanvasWorker")
.forget();
}
/* static */ void CanvasRenderThread::ShutdownWorkerTaskQueue(
TaskQueue* aTaskQueue) {
if (!sCanvasRenderThread) {
MOZ_ASSERT_UNREACHABLE("No CanvasRenderThread!");
return;
}
MutexAutoLock lock(sCanvasRenderThread->mMutex);
auto& pendingQueues = sCanvasRenderThread->mPendingShutdownTaskQueues;
pendingQueues.AppendElement(aTaskQueue);
}
/* static */ void CanvasRenderThread::FinishShutdownWorkerTaskQueue(
TaskQueue* aTaskQueue) {
if (!sCanvasRenderThread) {
return;
}
MutexAutoLock lock(sCanvasRenderThread->mMutex);
sCanvasRenderThread->mPendingShutdownTaskQueues.RemoveElement(aTaskQueue);
}
/* static */ void CanvasRenderThread::Dispatch(
already_AddRefed<nsIRunnable> aRunnable) {
if (!sCanvasRenderThread) {

View File

@ -8,10 +8,8 @@
#define _include_gfx_ipc_CanvasRenderThread_h__
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
class nsIRunnable;
class nsIThread;
@ -55,10 +53,6 @@ class CanvasRenderThread final {
static already_AddRefed<TaskQueue> CreateWorkerTaskQueue();
static void ShutdownWorkerTaskQueue(TaskQueue* aTaskQueue);
static void FinishShutdownWorkerTaskQueue(TaskQueue* aTaskQueue);
static void Dispatch(already_AddRefed<nsIRunnable> aRunnable);
private:
@ -66,17 +60,13 @@ class CanvasRenderThread final {
nsCOMPtr<nsIThreadPool>&& aWorkers, bool aCreatedThread);
~CanvasRenderThread();
Mutex mMutex;
nsCOMPtr<nsIThread> const mThread;
nsCOMPtr<nsIThreadPool> const mWorkers;
nsTArray<RefPtr<TaskQueue>> mPendingShutdownTaskQueues MOZ_GUARDED_BY(mMutex);
// True if mThread points to CanvasRender thread, false if mThread points to
// Compositor/Render thread.
const bool mCreatedThread;
bool mCreatedThread;
};
} // namespace gfx

View File

@ -98,7 +98,8 @@ bool CanvasDrawEventRecorder::Init(TextureType aTextureType,
if (!mHelpers->InitTranslator(aTextureType, aBackendType,
std::move(header->handle),
std::move(bufferHandles), mDefaultBufferSize,
std::move(readerSem), std::move(writerSem))) {
std::move(readerSem), std::move(writerSem),
/* aUseIPDLThread */ false)) {
return false;
}

View File

@ -67,13 +67,11 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate,
public:
virtual ~Helpers() = default;
virtual bool InitTranslator(TextureType aTextureType,
gfx::BackendType aBackendType,
Handle&& aReadHandle,
nsTArray<Handle>&& aBufferHandles,
uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) = 0;
virtual bool InitTranslator(
TextureType aTextureType, gfx::BackendType aBackendType,
Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem, bool aUseIPDLThread) = 0;
virtual bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) = 0;

View File

@ -37,7 +37,8 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) override {
CrossProcessSemaphoreHandle&& aWriterSem,
bool aUseIPDLThread) override {
NS_ASSERT_OWNINGTHREAD(RecorderHelpers);
if (NS_WARN_IF(!mCanvasChild)) {
return false;
@ -45,7 +46,7 @@ class RecorderHelpers final : public CanvasDrawEventRecorder::Helpers {
return mCanvasChild->SendInitTranslator(
aTextureType, aBackendType, std::move(aReadHandle),
std::move(aBufferHandles), aBufferSize, std::move(aReaderSem),
std::move(aWriterSem));
std::move(aWriterSem), aUseIPDLThread);
}
bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) override {

View File

@ -64,11 +64,9 @@ UniquePtr<TextureData> CanvasTranslator::CreateTextureData(
}
CanvasTranslator::CanvasTranslator(
RefPtr<TaskQueue>&& aTaskQueue,
layers::SharedSurfacesHolder* aSharedSurfacesHolder,
const dom::ContentParentId& aContentId, uint32_t aManagerId)
: mTranslationTaskQueue(std::move(aTaskQueue)),
mSharedSurfacesHolder(aSharedSurfacesHolder),
: mSharedSurfacesHolder(aSharedSurfacesHolder),
mMaxSpinCount(StaticPrefs::gfx_canvas_remote_max_spin_count()),
mContentId(aContentId),
mManagerId(aManagerId) {
@ -81,6 +79,22 @@ CanvasTranslator::CanvasTranslator(
CanvasTranslator::~CanvasTranslator() = default;
void CanvasTranslator::DispatchToTaskQueue(
already_AddRefed<nsIRunnable> aRunnable) {
if (mTranslationTaskQueue) {
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(std::move(aRunnable)));
} else {
gfx::CanvasRenderThread::Dispatch(std::move(aRunnable));
}
}
bool CanvasTranslator::IsInTaskQueue() const {
if (mTranslationTaskQueue) {
return mTranslationTaskQueue->IsCurrentThreadIn();
}
return gfx::CanvasRenderThread::IsInCanvasRenderThread();
}
static bool CreateAndMapShmem(RefPtr<ipc::SharedMemoryBasic>& aShmem,
Handle&& aHandle,
ipc::SharedMemory::OpenRights aOpenRights,
@ -119,7 +133,7 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
TextureType aTextureType, gfx::BackendType aBackendType,
Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem) {
CrossProcessSemaphoreHandle&& aWriterSem, bool aUseIPDLThread) {
if (mHeaderShmem) {
return IPC_FAIL(this, "RecvInitTranslator called twice.");
}
@ -153,6 +167,10 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
<< "GFX: CanvasTranslator failed creating WebGL shared context";
}
if (!aUseIPDLThread) {
mTranslationTaskQueue = gfx::CanvasRenderThread::CreateWorkerTaskQueue();
}
// Use the first buffer as our current buffer.
mDefaultBufferSize = aBufferSize;
auto handleIter = aBufferHandles.begin();
@ -174,9 +192,9 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
mCanvasShmems.emplace(std::move(newShmem));
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
NewRunnableMethod("CanvasTranslator::TranslateRecording", this,
&CanvasTranslator::TranslateRecording)));
DispatchToTaskQueue(NewRunnableMethod("CanvasTranslator::TranslateRecording",
this,
&CanvasTranslator::TranslateRecording));
return IPC_OK();
}
@ -186,9 +204,9 @@ ipc::IPCResult CanvasTranslator::RecvRestartTranslation() {
return IPC_OK();
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
NewRunnableMethod("CanvasTranslator::TranslateRecording", this,
&CanvasTranslator::TranslateRecording)));
DispatchToTaskQueue(NewRunnableMethod("CanvasTranslator::TranslateRecording",
this,
&CanvasTranslator::TranslateRecording));
return IPC_OK();
}
@ -200,17 +218,17 @@ ipc::IPCResult CanvasTranslator::RecvAddBuffer(
return IPC_OK();
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
DispatchToTaskQueue(
NewRunnableMethod<ipc::SharedMemoryBasic::Handle&&, size_t>(
"CanvasTranslator::AddBuffer", this, &CanvasTranslator::AddBuffer,
std::move(aBufferHandle), aBufferSize)));
std::move(aBufferHandle), aBufferSize));
return IPC_OK();
}
void CanvasTranslator::AddBuffer(ipc::SharedMemoryBasic::Handle&& aBufferHandle,
size_t aBufferSize) {
MOZ_ASSERT(mTranslationTaskQueue->IsCurrentThreadIn());
MOZ_ASSERT(IsInTaskQueue());
if (mHeader->readerState == State::Failed) {
// We failed before we got to the pause event.
return;
@ -254,18 +272,18 @@ ipc::IPCResult CanvasTranslator::RecvSetDataSurfaceBuffer(
return IPC_OK();
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
DispatchToTaskQueue(
NewRunnableMethod<ipc::SharedMemoryBasic::Handle&&, size_t>(
"CanvasTranslator::SetDataSurfaceBuffer", this,
&CanvasTranslator::SetDataSurfaceBuffer, std::move(aBufferHandle),
aBufferSize)));
aBufferSize));
return IPC_OK();
}
void CanvasTranslator::SetDataSurfaceBuffer(
ipc::SharedMemoryBasic::Handle&& aBufferHandle, size_t aBufferSize) {
MOZ_ASSERT(mTranslationTaskQueue->IsCurrentThreadIn());
MOZ_ASSERT(IsInTaskQueue());
if (mHeader->readerState == State::Failed) {
// We failed before we got to the pause event.
return;
@ -288,7 +306,7 @@ void CanvasTranslator::SetDataSurfaceBuffer(
}
void CanvasTranslator::GetDataSurface(uint64_t aSurfaceRef) {
MOZ_ASSERT(mTranslationTaskQueue->IsCurrentThreadIn());
MOZ_ASSERT(IsInTaskQueue());
ReferencePtr surfaceRef = reinterpret_cast<void*>(aSurfaceRef);
gfx::SourceSurface* surface = LookupSourceSurface(surfaceRef);
@ -347,27 +365,20 @@ void CanvasTranslator::NextBuffer() {
void CanvasTranslator::ActorDestroy(ActorDestroyReason why) {
MOZ_ASSERT(gfx::CanvasRenderThread::IsInCanvasRenderThread());
// Since we might need to access the actor status off the owning IPDL thread,
// we need to cache it here.
mIPDLClosed = true;
if (!mTranslationTaskQueue) {
gfx::CanvasRenderThread::Dispatch(
NewRunnableMethod("CanvasTranslator::FinishShutdown", this,
&CanvasTranslator::FinishShutdown));
return;
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(NewRunnableMethod(
"CanvasTranslator::Shutdown", this, &CanvasTranslator::Shutdown)));
gfx::CanvasRenderThread::ShutdownWorkerTaskQueue(mTranslationTaskQueue);
}
void CanvasTranslator::Shutdown() {
MOZ_ASSERT(mTranslationTaskQueue->IsCurrentThreadIn());
// By clearing our texture dependencies in the TaskQueue as the last runnable,
// we can ensure we actually run this before advancing process shutdown.
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
NewRunnableMethod("CanvasTranslator::ClearTextureInfo", this,
&CanvasTranslator::ClearTextureInfo)));
mTranslationTaskQueue->BeginShutdown();
mTranslationTaskQueue->AwaitShutdownAndIdle();
FinishShutdown();
}
void CanvasTranslator::FinishShutdown() { ClearTextureInfo(); }
bool CanvasTranslator::CheckDeactivated() {
if (mDeactivated) {
return true;
@ -460,7 +471,7 @@ void CanvasTranslator::CheckAndSignalWriter() {
// The writer is making a decision about whether to wait. So, we must
// wait until it has decided to avoid races. Check if the writer is
// closed to avoid hangs.
if (mIPDLClosed) {
if (!CanSend()) {
return;
}
continue;
@ -536,7 +547,7 @@ bool CanvasTranslator::ReadNextEvent(EventType& aEventType) {
}
void CanvasTranslator::TranslateRecording() {
MOZ_ASSERT(mTranslationTaskQueue->IsCurrentThreadIn());
MOZ_ASSERT(IsInTaskQueue());
if (mSharedContext && EnsureSharedContextWebgl()) {
mSharedContext->EnterTlsScope();
@ -555,7 +566,7 @@ void CanvasTranslator::TranslateRecording() {
[&](RecordedEvent* recordedEvent) -> bool {
// Make sure that the whole event was read from the stream.
if (!mCurrentMemReader.good()) {
if (mIPDLClosed) {
if (!CanSend()) {
// The other side has closed only warn about read failure.
gfxWarning() << "Failed to read event type: "
<< recordedEvent->GetType();
@ -594,7 +605,7 @@ void CanvasTranslator::TranslateRecording() {
case _typeenum: { \
auto e = _class(mCurrentMemReader); \
if (!mCurrentMemReader.good()) { \
if (mIPDLClosed) { \
if (!CanSend()) { \
/* The other side has closed only warn about read failure. */ \
gfxWarning() << "Failed to read event type: " << _typeenum; \
} else { \
@ -755,10 +766,9 @@ void CanvasTranslator::NotifyRequiresRefresh(int64_t aTextureId,
auto& info = mTextureInfo[aTextureId];
if (!info.mNotifiedRequiresRefresh) {
info.mNotifiedRequiresRefresh = true;
MOZ_ALWAYS_SUCCEEDS(
mTranslationTaskQueue->Dispatch(NewRunnableMethod<int64_t, bool>(
"CanvasTranslator::NotifyRequiresRefresh", this,
&CanvasTranslator::NotifyRequiresRefresh, aTextureId, false)));
DispatchToTaskQueue(NewRunnableMethod<int64_t, bool>(
"CanvasTranslator::NotifyRequiresRefresh", this,
&CanvasTranslator::NotifyRequiresRefresh, aTextureId, false));
}
return;
}
@ -770,10 +780,9 @@ void CanvasTranslator::NotifyRequiresRefresh(int64_t aTextureId,
void CanvasTranslator::CacheSnapshotShmem(int64_t aTextureId, bool aDispatch) {
if (aDispatch) {
MOZ_ALWAYS_SUCCEEDS(
mTranslationTaskQueue->Dispatch(NewRunnableMethod<int64_t, bool>(
"CanvasTranslator::CacheSnapshotShmem", this,
&CanvasTranslator::CacheSnapshotShmem, aTextureId, false)));
DispatchToTaskQueue(NewRunnableMethod<int64_t, bool>(
"CanvasTranslator::CacheSnapshotShmem", this,
&CanvasTranslator::CacheSnapshotShmem, aTextureId, false));
return;
}
@ -837,9 +846,9 @@ ipc::IPCResult CanvasTranslator::RecvClearCachedResources() {
return IPC_OK();
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
DispatchToTaskQueue(
NewRunnableMethod("CanvasTranslator::ClearCachedResources", this,
&CanvasTranslator::ClearCachedResources)));
&CanvasTranslator::ClearCachedResources));
return IPC_OK();
}
@ -1111,7 +1120,6 @@ void CanvasTranslator::ClearTextureInfo() {
mRemoteTextureOwner->UnregisterAllTextureOwners();
mRemoteTextureOwner = nullptr;
}
gfx::CanvasRenderThread::FinishShutdownWorkerTaskQueue(mTranslationTaskQueue);
}
already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupExternalSurface(

View File

@ -44,14 +44,26 @@ class CanvasTranslator final : public gfx::InlineTranslator,
friend class PProtocolParent;
CanvasTranslator(RefPtr<TaskQueue>&& aTaskQueue,
layers::SharedSurfacesHolder* aSharedSurfacesHolder,
CanvasTranslator(layers::SharedSurfacesHolder* aSharedSurfacesHolder,
const dom::ContentParentId& aContentId, uint32_t aManagerId);
const dom::ContentParentId& GetContentId() const { return mContentId; }
uint32_t GetManagerId() const { return mManagerId; }
/**
* Dispatches a runnable to the preferred task queue or thread.
*
* @param aRunnable the runnable to dispatch
*/
void DispatchToTaskQueue(already_AddRefed<nsIRunnable> aRunnable);
/**
* @returns true if running in the preferred task queue or thread for
* translation.
*/
bool IsInTaskQueue() const;
/**
* Initialize the canvas translator for a particular TextureType and
* CanvasEventRingBuffer.
@ -63,14 +75,14 @@ class CanvasTranslator final : public gfx::InlineTranslator,
* @param aBufferSize size of buffers and the default size
* @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
* @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
* @param aUseIPDLThread if true, use the IPDL thread instead of the worker
* pool for translation requests
*/
ipc::IPCResult RecvInitTranslator(TextureType aTextureType,
gfx::BackendType aBackendType,
Handle&& aReadHandle,
nsTArray<Handle>&& aBufferHandles,
uint64_t aBufferSize,
CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem);
ipc::IPCResult RecvInitTranslator(
TextureType aTextureType, gfx::BackendType aBackendType,
Handle&& aReadHandle, nsTArray<Handle>&& aBufferHandles,
uint64_t aBufferSize, CrossProcessSemaphoreHandle&& aReaderSem,
CrossProcessSemaphoreHandle&& aWriterSem, bool aUseIPDLThread);
/**
* Restart the translation from a Stopped state.
@ -273,6 +285,8 @@ class CanvasTranslator final : public gfx::InlineTranslator,
bool ReadPendingEvent(EventType& aEventType);
void FinishShutdown();
bool CheckDeactivated();
void Deactivate();
@ -296,8 +310,6 @@ class CanvasTranslator final : public gfx::InlineTranslator,
RemoteTextureOwnerId aTextureOwnerId, const gfx::IntSize& aSize,
gfx::SurfaceFormat aFormat);
void Shutdown();
void ClearTextureInfo();
bool HandleExtensionEvent(int32_t aType);
@ -314,8 +326,8 @@ class CanvasTranslator final : public gfx::InlineTranslator,
void ClearCachedResources();
const RefPtr<TaskQueue> mTranslationTaskQueue;
const RefPtr<SharedSurfacesHolder> mSharedSurfacesHolder;
RefPtr<TaskQueue> mTranslationTaskQueue;
RefPtr<SharedSurfacesHolder> mSharedSurfacesHolder;
#if defined(XP_WIN)
RefPtr<ID3D11Device> mDevice;
#endif
@ -372,7 +384,6 @@ class CanvasTranslator final : public gfx::InlineTranslator,
UniquePtr<gfx::DataSourceSurface::ScopedMap> mPreparedMap;
Atomic<bool> mDeactivated{false};
Atomic<bool> mBlocked{false};
Atomic<bool> mIPDLClosed{false};
bool mIsInTransaction = false;
bool mDeviceResetInProgress = false;
};

View File

@ -31,12 +31,15 @@ parent:
* handles for the initial buffers for translation. aBufferSize is the size of
* each aBufferHandles' memory and the default size. aReaderSem and aWriterSem
* are handles for the semaphores to handle waiting on either side.
* aUseIPDLThread if true, use the IPDL thread instead of the worker pool for
* translation requests
*/
async InitTranslator(TextureType aTextureType, BackendType aBackendType,
Handle aHeaderHandle, Handle[] aBufferHandles,
uint64_t aBufferSize,
CrossProcessSemaphoreHandle aReaderSem,
CrossProcessSemaphoreHandle aWriterSem);
CrossProcessSemaphoreHandle aWriterSem,
bool aUseIPDLThread);
/**
* Restart the translation from a Stopped state.