Commit faa97473 authored by Sadrul Habib Chowdhury's avatar Sadrul Habib Chowdhury Committed by Commit Bot

ozone: Workaround a start up race for OzonePlatform.

With mus, OzonePlatform is created in the mus-ws thread, and it can be
accessed from the IO thread in GpuProcessHost. There is a race here,
since the IO thread and the mus-ws thread do not know about each other.
So, instead of immediately talking to the OzonePlatform instance from
GpuProcessHost, register a callback that gets run once the instance is
created and initialized. This way, with regular chrome (where
OzonePlatform is created on the UI thread), the callback is run
immediately. But with mus, it waits until the OzonePlatform instance is
available.

BUG=786453

Change-Id: I9c4553333ef29d5541cf3b65fed475c3cc7ef2db
Reviewed-on: https://chromium-review.googlesource.com/794103
Commit-Queue: Sadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarMichael Spang <spang@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521353}
parent 74aed422
...@@ -631,13 +631,40 @@ bool GpuProcessHost::Init() { ...@@ -631,13 +631,40 @@ bool GpuProcessHost::Init() {
#if defined(USE_OZONE) #if defined(USE_OZONE)
// Ozone needs to send the primary DRM device to GPU process as early as // Ozone needs to send the primary DRM device to GPU process as early as
// possible to ensure the latter always has a valid device. crbug.com/608839 // possible to ensure the latter always has a valid device. crbug.com/608839
ui::OzonePlatform::GetInstance() // When running with mus, the OzonePlatform may not have been created yet. So
->GetGpuPlatformSupportHost() // defer the callback until OzonePlatform instance is created.
->OnGpuProcessLaunched( auto send_callback = base::BindRepeating(&SendGpuProcessMessage,
host_id_, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI), weak_ptr_factory_.GetWeakPtr());
base::ThreadTaskRunnerHandle::Get(), // Create the callback that should run on the current thread (i.e. IO thread).
base::Bind(&SendGpuProcessMessage, weak_ptr_factory_.GetWeakPtr())); auto io_callback = base::BindOnce(
#endif [](int host_id,
const base::RepeatingCallback<void(IPC::Message*)>& send_callback,
ui::OzonePlatform* platform) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
platform->GetGpuPlatformSupportHost()->OnGpuProcessLaunched(
host_id, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
send_callback);
},
host_id_, send_callback);
// The callback registered in ozone can be called in any thread. So use an
// intermediary callback that bounces to the IO thread if needed, before
// running the callback.
auto bounce_callback = base::BindOnce(
[](base::TaskRunner* task_runner,
base::OnceCallback<void(ui::OzonePlatform*)> callback,
ui::OzonePlatform* platform) {
if (task_runner->RunsTasksInCurrentSequence()) {
std::move(callback).Run(platform);
} else {
task_runner->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), platform));
}
},
base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
base::Passed(&io_callback));
ui::OzonePlatform::RegisterStartupCallback(std::move(bounce_callback));
#endif // defined(USE_OZONE)
return true; return true;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "ui/ozone/public/ozone_platform.h" #include "ui/ozone/public/ozone_platform.h"
#include "base/lazy_instance.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "ui/events/devices/device_data_manager.h" #include "ui/events/devices/device_data_manager.h"
...@@ -16,10 +17,18 @@ namespace { ...@@ -16,10 +17,18 @@ namespace {
bool g_platform_initialized_ui = false; bool g_platform_initialized_ui = false;
bool g_platform_initialized_gpu = false; bool g_platform_initialized_gpu = false;
base::LazyInstance<base::OnceCallback<void(OzonePlatform*)>>::Leaky
instance_callback = LAZY_INSTANCE_INITIALIZER;
base::Lock& GetOzoneInstanceLock() {
static base::Lock lock;
return lock;
}
} // namespace } // namespace
OzonePlatform::OzonePlatform() { OzonePlatform::OzonePlatform() {
GetOzoneInstanceLock().AssertAcquired();
DCHECK(!instance_) << "There should only be a single OzonePlatform."; DCHECK(!instance_) << "There should only be a single OzonePlatform.";
instance_ = this; instance_ = this;
g_platform_initialized_ui = false; g_platform_initialized_ui = false;
...@@ -38,6 +47,8 @@ void OzonePlatform::InitializeForUI(const InitParams& args) { ...@@ -38,6 +47,8 @@ void OzonePlatform::InitializeForUI(const InitParams& args) {
// This is deliberately created after initializing so that the platform can // This is deliberately created after initializing so that the platform can
// create its own version of DDM. // create its own version of DDM.
DeviceDataManager::CreateInstance(); DeviceDataManager::CreateInstance();
if (!instance_callback.Get().is_null())
std::move(instance_callback.Get()).Run(instance_);
} }
// static // static
...@@ -47,10 +58,13 @@ void OzonePlatform::InitializeForGPU(const InitParams& args) { ...@@ -47,10 +58,13 @@ void OzonePlatform::InitializeForGPU(const InitParams& args) {
return; return;
g_platform_initialized_gpu = true; g_platform_initialized_gpu = true;
instance_->InitializeGPU(args); instance_->InitializeGPU(args);
if (!args.single_process && !instance_callback.Get().is_null())
std::move(instance_callback.Get()).Run(instance_);
} }
// static // static
void OzonePlatform::Shutdown() { void OzonePlatform::Shutdown() {
base::AutoLock lock(GetOzoneInstanceLock());
auto* tmp = instance_; auto* tmp = instance_;
instance_ = nullptr; instance_ = nullptr;
delete tmp; delete tmp;
...@@ -58,12 +72,14 @@ void OzonePlatform::Shutdown() { ...@@ -58,12 +72,14 @@ void OzonePlatform::Shutdown() {
// static // static
OzonePlatform* OzonePlatform::GetInstance() { OzonePlatform* OzonePlatform::GetInstance() {
base::AutoLock lock(GetOzoneInstanceLock());
DCHECK(instance_) << "OzonePlatform is not initialized"; DCHECK(instance_) << "OzonePlatform is not initialized";
return instance_; return instance_;
} }
// static // static
OzonePlatform* OzonePlatform::EnsureInstance() { OzonePlatform* OzonePlatform::EnsureInstance() {
base::AutoLock lock(GetOzoneInstanceLock());
if (!instance_) { if (!instance_) {
TRACE_EVENT1("ozone", TRACE_EVENT1("ozone",
"OzonePlatform::Initialize", "OzonePlatform::Initialize",
...@@ -79,6 +95,21 @@ OzonePlatform* OzonePlatform::EnsureInstance() { ...@@ -79,6 +95,21 @@ OzonePlatform* OzonePlatform::EnsureInstance() {
return instance_; return instance_;
} }
// static
void OzonePlatform::RegisterStartupCallback(
base::OnceCallback<void(OzonePlatform*)> callback) {
OzonePlatform* inst = nullptr;
{
base::AutoLock lock(GetOzoneInstanceLock());
if (!instance_ || !g_platform_initialized_ui) {
instance_callback.Get() = std::move(callback);
return;
}
inst = instance_;
}
std::move(callback).Run(inst);
}
// static // static
OzonePlatform* OzonePlatform::instance_ = nullptr; OzonePlatform* OzonePlatform::instance_ = nullptr;
......
...@@ -96,6 +96,15 @@ class OZONE_EXPORT OzonePlatform { ...@@ -96,6 +96,15 @@ class OZONE_EXPORT OzonePlatform {
static OzonePlatform* GetInstance(); static OzonePlatform* GetInstance();
// Registers a callback to be run when the OzonePlatform is initialized. Note
// that if an instance already exists, then the callback is called
// immediately. If an instance does not exist, and is created later, then the
// callback is called once the instance is created and initialized, on the
// thread it is initialized on. If the caller requires the callback to run on
// a specific thread, then it needs to do ensure that by itself.
static void RegisterStartupCallback(
base::OnceCallback<void(OzonePlatform*)> callback);
// Factory getters to override in subclasses. The returned objects will be // Factory getters to override in subclasses. The returned objects will be
// injected into the appropriate layer at startup. Subclasses should not // injected into the appropriate layer at startup. Subclasses should not
// inject these objects themselves. Ownership is retained by OzonePlatform. // inject these objects themselves. Ownership is retained by OzonePlatform.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment