From 7fc04cb5ec799e4f8a09a094955276c5c9707a25 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 7 Aug 2023 16:07:22 +0200 Subject: [PATCH] ngui: clarify and handle concurrency during screen sleep/standby the screen.sleep fn was actually called in concurrent-unsafe mode, i.e without acquiring UI mutex. in conjuction with commThreadLoopCycle this would have eventually led to LVGL primitives concurrent access. so, screen.sleep now takes UI mutex to hold during LVGL calls. a bit ugly but certainly better than relying on luck. --- src/ngui.zig | 1 - src/ui/screen.zig | 17 ++++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/ngui.zig b/src/ngui.zig index 1b8e2de..6f8936d 100644 --- a/src/ngui.zig +++ b/src/ngui.zig @@ -220,7 +220,6 @@ fn uiThreadLoop() void { comm.write(gpa, stdout, comm.Message.standby) catch |err| { logger.err("comm.write standby: {any}", .{err}); }; - // MUTEX??????????????????????????????????? screen.sleep(&ui_mutex, &wakeup); // blocking // wake up due to touch screen activity or wakeup event is set diff --git a/src/ui/screen.zig b/src/ui/screen.zig index 7359be5..6f73f9d 100644 --- a/src/ui/screen.zig +++ b/src/ui/screen.zig @@ -13,18 +13,21 @@ const logger = std.log.scoped(.screen); /// a touch screen activity or wake event is triggered. /// sleep removes all input devices at enter and reinstates them at exit so that /// a touch event triggers no accidental action. -pub fn sleep(mu: *std.Thread.Mutex, wake: *const Thread.ResetEvent) void { +/// +/// the UI mutex is held while calling LVGL UI functions, and released during +/// idling or waiting for wake event. +/// although sleep is safe for concurrent use, the input drivers init/deinit +/// implementation used on entry and exit might not be. +pub fn sleep(ui: *std.Thread.Mutex, wake: *const Thread.ResetEvent) void { + ui.lock(); drv.deinitInput(); - - mu.lock(); widget.topdrop(.show); - mu.unlock(); - + ui.unlock(); defer { + ui.lock(); + defer ui.unlock(); drv.initInput() catch |err| logger.err("drv.initInput: {any}", .{err}); - mu.lock(); widget.topdrop(.remove); - mu.unlock(); } const watcher = drv.InputWatcher() catch |err| {