Shared Library Changes for Release 3.0.1
Shared library libddcutil is backwardly compatible with the ones in ddcutil 2.2.1 and later. The SONAME is unchanged as libddcutil.so.5. The released library file is libddcutil.so.5.6.0.
This is an overview of the changes in releases 3.0.0 and 3.0.1, which are extensive. More detailed information can be found in file CHANGELOG.md in the source tree.
Performance
- The display watch thread now blocks in poll() on the watched fd plus a termination eventfd, instead of sleeping in timed polling loops
- Interruptible sleep execution is reimplemented using a termination event instead of looping over multiple short sleep operations. Eliminates the watch thread's periodic wakeups (up to 10 per second) which degrade idle power residency when libddcutil is embedded in a long-running process such as KDE PowerDevil. Addresses issue #617: ddcutil wakes up every 100ms to check for monitors even when nothing connected
- A burst of udev events, common following a resume, is coalesced to avoid a storm of redundant bus rescans.
- Do not try to open a /dev/i2c device whose DRM connector has status "disconnected"
EACCES Errors
- Further mitigations for transient access permission (EACCES) errors. There is a sliver of time between wehen /dev/i2c devices become visible and the time that udev applies uacces permssions, resuling in open failures on /dev/i2c devices. (KDE bug 522329, reported as 100% single-core CPU and desktop lag on wake)
- Reworked detection and handling of resume from sleep. Resume is detected using a combinattion of the the D-Bus PrepareForSleep signal, and by comparing comparing CLOCK_BOOTTIME and CLOCK_MONOTONIC. Pauses are inserted before opening a /dev/i2c device and in the display watch loop for a short interval after a resume.
- Rate-limit the expensive EACCES diagnostics. Diagnostics are emitted at most once per 10 seconds (set by parm DEFAULT_EACCES_DIAGNOSTIC_INTERVAL_SEC in parms.h), instead of once per bus open.
- Defer display change processing until the EACESS window passes, to avoid briefly treating every monitor as disconnected.
API Changes
- Watch mode xevent is unsupportedd. If no watch mode is specified, or 1--watch-mode dynamic is given, the watch mode resolves to udev if udev is enabled, poll if not. If --watch-mode xevent is explicitly specified it will be respected, but execution will not work properly; it is recognized solely for testing purposes.
- Added API function ddca_elapsed_nanosec(), which returns the nummber of nanoseconds since the library was initialized. This enables client programs to adjusting their timestamps to correlate with those reported by libddcutil.
- dw_stop_watch_displays() now always waits for the watch thread to terminate.
- API cleanup:
- const-qualify string input parameters (and some return values),
- added explicit void to empty parameter lists
Bug Fixes
- Release 3.0.1 fixed a critical bug in 3.0.0 that caused driver AMDGPU crash on Navi based devices. This caused the system to crash on startup of KDE Plasma. (Github issues 628, 629, 630)
- The default recheck thread declared DDC enabled, and emitted DDCA_EVENT_DDC_ENABLED, whenever a recheck completed without error, even if DDC communication was not yet working. In releases through 2.2.6, combined with an incorrect constant in event construction (fixed in 2.2.7), this produced DDCA_EVENT_DDC_ENABLED events reporting ddc working: false (KDE bug 517290). The event is now emitted only when DDC communication is confirmed working; otherwise the recheck is requeued.
- ddca_unregister_display_status_callback(): Status codes for success and not-found were swapped.
- ddca_dbgrpt_display_ref(): The opaque DDCA_Display_Ref was being cast directly to an internal Display_Ref instead of being resolved by lookup.
- ddca_report_displays() now respects API quiescing.
- Segfault if a display was dicsonnected while in use.
- Option --syslog passed in either the ddca_init2() libopts parmameter or in the ddcutilrc configuration file was not recognized.
- Fixed many race conditions uncovered by code analysis.