minigbm: cros_gralloc: fix initialization race condition
On Android M, since we don't hold a lock during cros_gralloc_driver::init(),
another thread would sometimes access data before the driver was initialized.
This would lead to dEQP crashes. We don't experience this issue on Android
N since the framework has it's own layer of locks in the Gralloc1On0Adapter.
This patch makes the module initialization during (*registerBuffer) and
gralloc_open re-entrant.
BUG=b:63511976
TEST=run cts --package com.drawelements.deqp.gles2 on veyron_tiger has no
crashes
Change-Id: I2b72f2f8ed5e4a5afbacb291ed8cd928beb2a3b3
Reviewed-on: https://chromium-review.googlesource.com/597015
Commit-Ready: Gurchetan Singh <gurchetansingh@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Tomasz Figa <tfiga@chromium.org>
diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc
index ec897be..e62c670 100644
--- a/cros_gralloc/gralloc0/gralloc0.cc
+++ b/cros_gralloc/gralloc0/gralloc0.cc
@@ -13,6 +13,8 @@
gralloc_module_t base;
std::unique_ptr<alloc_device_t> alloc;
std::unique_ptr<cros_gralloc_driver> driver;
+ bool initialized;
+ std::mutex initialization_mutex;
};
/* This enumeration must match the one in <gralloc_drm.h>.
@@ -128,11 +130,38 @@
return 0;
}
+static int gralloc0_init(struct gralloc0_module *mod, bool initialize_alloc)
+{
+ std::lock_guard<std::mutex> lock(mod->initialization_mutex);
+
+ if (mod->initialized)
+ return 0;
+
+ mod->driver = std::make_unique<cros_gralloc_driver>();
+ if (mod->driver->init()) {
+ cros_gralloc_error("Failed to initialize driver.");
+ return -ENODEV;
+ }
+
+ if (initialize_alloc) {
+ mod->alloc = std::make_unique<alloc_device_t>();
+ mod->alloc->alloc = gralloc0_alloc;
+ mod->alloc->free = gralloc0_free;
+ mod->alloc->common.tag = HARDWARE_DEVICE_TAG;
+ mod->alloc->common.version = 0;
+ mod->alloc->common.module = (hw_module_t *)mod;
+ mod->alloc->common.close = gralloc0_close;
+ }
+
+ mod->initialized = true;
+ return 0;
+}
+
static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev)
{
auto module = (struct gralloc0_module *)mod;
- if (module->alloc) {
+ if (module->initialized) {
*dev = &module->alloc->common;
return 0;
}
@@ -142,20 +171,8 @@
return -EINVAL;
}
- module->driver = std::make_unique<cros_gralloc_driver>();
- if (module->driver->init()) {
- cros_gralloc_error("Failed to initialize driver.");
- return -ENOMEM;
- }
-
- module->alloc = std::make_unique<alloc_device_t>();
-
- module->alloc->alloc = gralloc0_alloc;
- module->alloc->free = gralloc0_free;
- module->alloc->common.tag = HARDWARE_DEVICE_TAG;
- module->alloc->common.version = 0;
- module->alloc->common.module = (hw_module_t *)mod;
- module->alloc->common.close = gralloc0_close;
+ if (gralloc0_init(module, true))
+ return -ENODEV;
*dev = &module->alloc->common;
return 0;
@@ -165,13 +182,9 @@
{
auto mod = (struct gralloc0_module *)module;
- if (!mod->driver) {
- mod->driver = std::make_unique<cros_gralloc_driver>();
- if (mod->driver->init()) {
- cros_gralloc_error("Failed to initialize driver.");
- return -ENOMEM;
- }
- }
+ if (!mod->initialized)
+ if (gralloc0_init(mod, false))
+ return -ENODEV;
return mod->driver->retain(handle);
}
@@ -380,4 +393,5 @@
.alloc = nullptr,
.driver = nullptr,
+ .initialized = false,
};