drm_hwcomposer: Rework HwcDisplay disposal to avoid races
The code prior to this commit has a flaw:
HwcDisplay::~HwcDisplay() {
...
auto &main_lock = hwc2_->GetResMan().GetMainLock();
/* Unlock to allow pending vsync callbacks to finish */
main_lock.unlock();
At this point display is no longer in displays_[] list. After
lock is released, hwc2 API thread starts to process transactions
which may fail with BAD_SIAPLAY responce and cause SF to crash.
vsync_worker_.VSyncControl(false);
vsync_worker_.Exit();
main_lock.lock();
}
1. Rework the logic in order to avoid such scenariuos:
1.a. Temporary switch non-primary unplugged displays to headless state
allowing remaining transactions to succeed without impacting the
pipeline.
1.b. Give 100mSec delay before destroying / removing display from the
displays_[] list to allow all pending hwc2 transactions to complete.
2. Support hotswap of the DrmDisplayPipeline, which makes primary display
reattaching process smoother.
Now SF should be able to gracefully remove all layers.
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index ae5d980..98d8e9b 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -37,11 +37,13 @@
class HwcDisplay {
public:
- HwcDisplay(DrmDisplayPipeline *pipeline, hwc2_display_t handle,
- HWC2::DisplayType type, DrmHwcTwo *hwc2);
+ HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2);
HwcDisplay(const HwcDisplay &) = delete;
~HwcDisplay();
+ /* SetPipeline should be carefully used only by DrmHwcTwo hotplug handlers */
+ void SetPipeline(DrmDisplayPipeline *pipeline);
+
HWC2::Error CreateComposition(AtomicCommitArgs &a_args);
std::vector<HwcLayer *> GetOrderLayersByZPos();
@@ -199,7 +201,7 @@
int64_t staged_mode_change_time_{};
uint32_t staged_mode_config_id_{};
- DrmDisplayPipeline *const pipeline_;
+ DrmDisplayPipeline *pipeline_{};
std::unique_ptr<Backend> backend_;
@@ -212,8 +214,7 @@
const hwc2_display_t handle_;
HWC2::DisplayType type_;
- // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
- static uint32_t layer_idx_;
+ uint32_t layer_idx_{};
std::map<hwc2_layer_t, HwcLayer> layers_;
HwcLayer client_layer_;