drm_hwcomposer: Introduce main lock
Further development will require more asynchronous processing.
Introduce project-wide single mutex for these purposes.
Use it instead for callback handling instead of callback_lock.
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h
index 773b350..f54d682 100644
--- a/drm/ResourceManager.h
+++ b/drm/ResourceManager.h
@@ -48,6 +48,10 @@
return &uevent_listener_;
}
+ auto &GetMainLock() {
+ return main_lock_;
+ }
+
private:
int AddDrmDevice(std::string const &path);
@@ -57,6 +61,8 @@
bool scale_with_gpu_{};
UEventListener uevent_listener_;
+
+ std::mutex main_lock_;
};
} // namespace android
diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp
index 5bbb48a..42e131a 100644
--- a/hwc2_device/DrmHwcTwo.cpp
+++ b/hwc2_device/DrmHwcTwo.cpp
@@ -66,8 +66,11 @@
}
}
- resource_manager_.GetUEventListener()->RegisterHotplugHandler(
- [this] { HandleHotplugUEvent(); });
+ resource_manager_.GetUEventListener()->RegisterHotplugHandler([this] {
+ const std::lock_guard<std::mutex> lock(GetResMan().GetMainLock());
+
+ HandleHotplugUEvent();
+ });
return ret;
}
@@ -111,12 +114,9 @@
HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
hwc2_callback_data_t data,
hwc2_function_pointer_t function) {
- std::unique_lock<std::mutex> lock(callback_lock_);
-
switch (static_cast<HWC2::Callback>(descriptor)) {
case HWC2::Callback::Hotplug: {
hotplug_callback_ = std::make_pair(HWC2_PFN_HOTPLUG(function), data);
- lock.unlock();
const auto &drm_devices = resource_manager_.GetDrmDevices();
for (const auto &device : drm_devices)
HandleInitialHotplugState(device.get());
@@ -143,14 +143,23 @@
}
void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
- const std::lock_guard<std::mutex> lock(callback_lock_);
+ auto &mutex = GetResMan().GetMainLock();
+ if (mutex.try_lock()) {
+ ALOGE("FIXME!!!: Main mutex must be locked in %s", __func__);
+ mutex.unlock();
+ return;
+ }
- if (hotplug_callback_.first != nullptr &&
- hotplug_callback_.second != nullptr) {
- hotplug_callback_.first(hotplug_callback_.second, displayid,
- state == DRM_MODE_CONNECTED
- ? HWC2_CONNECTION_CONNECTED
- : HWC2_CONNECTION_DISCONNECTED);
+ auto hc = hotplug_callback_;
+ if (hc.first != nullptr && hc.second != nullptr) {
+ /* For some reason CLIENT will call HWC2 API in hotplug callback handler,
+ * which will cause deadlock . Unlock main mutex to prevent this.
+ */
+ mutex.unlock();
+ hc.first(hc.second, displayid,
+ state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED
+ : HWC2_CONNECTION_DISCONNECTED);
+ mutex.lock();
}
}
diff --git a/hwc2_device/DrmHwcTwo.h b/hwc2_device/DrmHwcTwo.h
index d096160..f38ba05 100644
--- a/hwc2_device/DrmHwcTwo.h
+++ b/hwc2_device/DrmHwcTwo.h
@@ -37,8 +37,6 @@
#endif
std::pair<HWC2_PFN_REFRESH, hwc2_callback_data_t> refresh_callback_{};
- std::mutex callback_lock_;
-
static HwcDisplay *GetDisplay(DrmHwcTwo *hwc, hwc2_display_t display_handle) {
auto it = hwc->displays_.find(display_handle);
if (it == hwc->displays_.end())
@@ -57,6 +55,10 @@
hwc2_function_pointer_t function);
HWC2::Error CreateDisplay(hwc2_display_t displ, HWC2::DisplayType type);
+ auto &GetResMan() {
+ return resource_manager_;
+ }
+
private:
void HandleDisplayHotplug(hwc2_display_t displayid, int state);
void HandleInitialHotplugState(DrmDevice *drmDevice);
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index 9f7bcd8..c8f5e69 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -136,7 +136,7 @@
}
ret = vsync_worker_.Init(drm_, display, [this](int64_t timestamp) {
- const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
+ const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock());
/* vsync callback */
#if PLATFORM_SDK_VERSION > 29
if (hwc2_->vsync_2_4_callback_.first != nullptr &&
@@ -160,7 +160,8 @@
ret = flattening_vsync_worker_
.Init(drm_, display, [this](int64_t /*timestamp*/) {
- const std::lock_guard<std::mutex> lock(hwc2_->callback_lock_);
+ const std::lock_guard<std::mutex> lock(
+ hwc2_->GetResMan().GetMainLock());
/* Frontend flattening */
if (flattenning_state_ >
ClientFlattenningState::ClientRefreshRequested &&
diff --git a/hwc2_device/hwc2_device.cpp b/hwc2_device/hwc2_device.cpp
index ebf7eeb..6d258e8 100644
--- a/hwc2_device/hwc2_device.cpp
+++ b/hwc2_device/hwc2_device.cpp
@@ -63,15 +63,18 @@
static T DeviceHook(hwc2_device_t *dev, Args... args) {
ALOGV("Device hook: %s", GetFuncName(__PRETTY_FUNCTION__).c_str());
DrmHwcTwo *hwc = ToDrmHwcTwo(dev);
+ const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock());
return static_cast<T>(((*hwc).*func)(std::forward<Args>(args)...));
}
template <typename HookType, HookType func, typename... Args>
static int32_t DisplayHook(hwc2_device_t *dev, hwc2_display_t display_handle,
Args... args) {
- HwcDisplay *display = DrmHwcTwo::GetDisplay(ToDrmHwcTwo(dev), display_handle);
ALOGV("Display #%" PRIu64 " hook: %s", display_handle,
GetFuncName(__PRETTY_FUNCTION__).c_str());
+ DrmHwcTwo *hwc = ToDrmHwcTwo(dev);
+ const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock());
+ HwcDisplay *display = DrmHwcTwo::GetDisplay(hwc, display_handle);
if (!display)
return static_cast<int32_t>(HWC2::Error::BadDisplay);
@@ -81,9 +84,11 @@
template <typename HookType, HookType func, typename... Args>
static int32_t LayerHook(hwc2_device_t *dev, hwc2_display_t display_handle,
hwc2_layer_t layer_handle, Args... args) {
- HwcDisplay *display = DrmHwcTwo::GetDisplay(ToDrmHwcTwo(dev), display_handle);
ALOGV("Display #%" PRIu64 " Layer: #%" PRIu64 " hook: %s", display_handle,
layer_handle, GetFuncName(__PRETTY_FUNCTION__).c_str());
+ DrmHwcTwo *hwc = ToDrmHwcTwo(dev);
+ const std::lock_guard<std::mutex> lock(hwc->GetResMan().GetMainLock());
+ HwcDisplay *display = DrmHwcTwo::GetDisplay(hwc, display_handle);
if (!display)
return static_cast<int32_t>(HWC2::Error::BadDisplay);