Skip to content

Dmod_Run: do not hold the module's mutex while its main() runs - #330

Merged
JohnAmadis merged 1 commit into
developfrom
fix/run-without-context-lock
Oct 11, 2026
Merged

JohnAmadis merged 1 commit into
developfrom
fix/run-without-context-lock

Conversation

@JaxCalder

Copy link
Copy Markdown
Contributor

Summary

Dmod_Run() held Context->Mutex from before Dmod_Init() until after Dmod_Deinit(), that is, for the whole time the application runs. Anyone who locks it in the meantime (Dmod_BeginUsage() / _EndUsage(), Dmod_Enable(), ...) waits for the application to end. Because FreeRTOS mutexes inherit priority, the holder runs at the waiter's priority until it releases every mutex it holds.

On dmod-boot, systemd (priority 4) waits on it, so every service ran at priority 4 permanently instead of its own DMOD_PRIORITY. A view drawn by dmview then starved the car HMI's MP3 decoder (priority 2), and playback crackled.

This was found on the board: every service task held one recursive mutex, its context's, at priority 4 over a base of 0 or 1. With the fix, all tasks run at their base priority with no mutexes held, and playback is clean.

The mutex is now released around Dmod_Main() and taken again for the deinit. Context->Running (set under the mutex) still keeps a second Dmod_Run() out, and Dmod_Unload() still refuses a running module.

Test plan

  • STM32F746G-DISCO (dmod-boot): FreeRTOS task walk shows every task at its base priority, held mutexes 0
  • MP3 playback through dmaudio while dmview draws: clean

🤖 Generated with Claude Code

Dmod_Run() kept Context->Mutex locked from before Dmod_Init() until after
Dmod_Deinit(), i.e. for as long as the application runs. Everybody who
locks it meanwhile - Dmod_BeginUsage() / _EndUsage(), Dmod_Enable(), ... -
waited for the application to end, lending it their priority all the time
(FreeRTOS mutexes inherit priority; it is given back only when the holder
releases every mutex it holds): on dmod-boot every service started by
systemd (priority 4) ran at 4 instead of its own DMOD_PRIORITY - a view
being drawn by dmview starved an MP3 decoder of priority 2 (the car HMI
played choppy). Found on the board: every service held one recursive mutex,
its context's, at priority 4 over a base of 0 or 1.

The mutex is released for Dmod_Main() and taken again for the deinit;
Context->Running (set under it) still keeps a second Dmod_Run() out, and
Dmod_Unload() still refuses a running module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JohnAmadis
JohnAmadis merged commit cefe9a3 into develop Oct 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants