Bug 1445662 - Ensure UpdateZoomConstraints runs on the sampler thread. r=rhunt

Without this patch, UpdateZoomConstraints can get called on:
a) the compositor/sampler thread (over PAPZCTreeManager)
b) the controller thread which is also the UI process main thread (on
   desktop platforms without a GPU process)
c) the UI process main thread when it's *not* the controller thread (on
   Android).
Instead of having to reason about all these scenarios separately, we can
try to unify them a little bit by ensuring the function contents always
run on the sampler thread, which is the thread that seems to make the
most sense for it.
This commit is contained in:
Kartikaya Gupta 2018-03-15 15:25:10 -04:00
Родитель cfbe8bb66a
Коммит bb580f89fa
4 изменённых файлов: 73 добавлений и 17 удалений

Просмотреть файл

@ -1935,6 +1935,24 @@ void
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
const Maybe<ZoomConstraints>& aConstraints)
{
if (!APZThreadUtils::IsSamplerThread()) {
// This can happen if we're in the UI process and got a call directly from
// nsBaseWidget (as opposed to over PAPZCTreeManager). We want this function
// to run on the sampler thread, so bounce it over.
MOZ_ASSERT(XRE_IsParentProcess());
APZThreadUtils::RunOnSamplerThread(
NewRunnableMethod<ScrollableLayerGuid, Maybe<ZoomConstraints>>(
"APZCTreeManager::UpdateZoomConstraints",
this,
&APZCTreeManager::UpdateZoomConstraints,
aGuid,
aConstraints));
return;
}
APZThreadUtils::AssertOnSamplerThread();
RecursiveMutexAutoLock lock(mTreeLock);
RefPtr<HitTestingTreeNode> node = GetTargetNode(aGuid, nullptr);
MOZ_ASSERT(!node || node->GetApzc()); // any node returned must have an APZC

Просмотреть файл

@ -691,12 +691,13 @@ private:
* isolation (that is, if its tree pointers are not being accessed or mutated). The
* lock also needs to be held when accessing the mRootNode instance variable, as that
* is considered part of the APZC tree management state.
* Finally, the lock needs to be held when accessing mZoomConstraints.
* IMPORTANT: See the note about lock ordering at the top of this file. */
mutable mozilla::RecursiveMutex mTreeLock;
RefPtr<HitTestingTreeNode> mRootNode;
/* Holds the zoom constraints for scrollable layers, as determined by the
* the main-thread gecko code. */
* the main-thread gecko code. This can only be accessed on the sampler
* thread. */
std::unordered_map<ScrollableLayerGuid, ZoomConstraints, ScrollableLayerGuidHash> mZoomConstraints;
/* A list of keyboard shortcuts to use for translating keyboard inputs into
* keyboard actions. This is gathered on the main thread from XBL bindings.

Просмотреть файл

@ -42,14 +42,6 @@ APZThreadUtils::AssertOnControllerThread() {
MOZ_ASSERT(sControllerThread == MessageLoop::current());
}
/*static*/ void
APZThreadUtils::AssertOnSamplerThread()
{
if (GetThreadAssertionsEnabled()) {
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
}
}
/*static*/ void
APZThreadUtils::RunOnControllerThread(already_AddRefed<Runnable> aTask)
{
@ -74,6 +66,39 @@ APZThreadUtils::IsControllerThread()
return sControllerThread == MessageLoop::current();
}
/*static*/ void
APZThreadUtils::AssertOnSamplerThread()
{
if (GetThreadAssertionsEnabled()) {
MOZ_ASSERT(IsSamplerThread());
}
}
/*static*/ void
APZThreadUtils::RunOnSamplerThread(already_AddRefed<Runnable> aTask)
{
RefPtr<Runnable> task = aTask;
MessageLoop* loop = CompositorThreadHolder::Loop();
if (!loop) {
// Could happen during startup
NS_WARNING("Dropping task posted to sampler thread");
return;
}
if (IsSamplerThread()) {
task->Run();
} else {
loop->PostTask(task.forget());
}
}
/*static*/ bool
APZThreadUtils::IsSamplerThread()
{
return CompositorThreadHolder::IsInCompositorThread();
}
NS_IMPL_ISUPPORTS(GenericNamedTimerCallbackBase, nsITimerCallback, nsINamed)
} // namespace layers

Просмотреть файл

@ -40,13 +40,6 @@ public:
*/
static void AssertOnControllerThread();
/**
* This can be used to assert that the current thread is the
* sampler thread (which samples the async transform).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnSamplerThread();
/**
* Run the given task on the APZ "controller thread" for this platform. If
* this function is called from the controller thread itself then the task is
@ -58,6 +51,25 @@ public:
* Returns true if currently on APZ "controller thread".
*/
static bool IsControllerThread();
/**
* This can be used to assert that the current thread is the
* sampler thread (which samples the async transform).
* This does nothing if thread assertions are disabled.
*/
static void AssertOnSamplerThread();
/**
* Runs the given task on the APZ "sampler thread" for this platform. If
* this function is called from the sampler thread itself then the task is
* run immediately without getting queued.
*/
static void RunOnSamplerThread(already_AddRefed<Runnable> aTask);
/**
* Returns true if currently on the APZ "sampler thread".
*/
static bool IsSamplerThread();
};
// A base class for GenericNamedTimerCallback<Function>.