Skip to content

Added opt-in priority inheritance through chains of mutexes - #808

Open
howjmay wants to merge 1 commit into
eclipse-threadx:masterfrom
howjmay:fix/mutex-inherit-chain
Open

howjmay wants to merge 1 commit into
eclipse-threadx:masterfrom
howjmay:fix/mutex-inherit-chain

Conversation

@howjmay

@howjmay howjmay commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

tx_mutex_get raised the owner of a TX_INHERIT mutex and stopped. If that owner was itself blocked on a second inheriting mutex, the second owner never inherited the priority: with H blocked on m1, owned by L1, blocked on m2, owned by L2, L2 stayed at L1's old priority and H waited behind every thread between the two.

When TX_MUTEX_INHERIT_CHAIN_MAX is defined, tx_mutex_get passes the inherited priority on through a new internal function, _tx_mutex_priority_chain. While the thread it last raised is waiting on an inheriting mutex, it updates that mutex's highest waiting priority and raises the mutex owner with _tx_mutex_priority_change, which handles ready and suspended owners alike, for at most TX_MUTEX_INHERIT_CHAIN_MAX mutexes. It stops at the first owner already at the priority or higher, which also ends it on a lock cycle. The walk is iterative and only raises priorities. It is opt-in, so existing builds keep their worst-case tx_mutex_get time. Documented in tx_user_sample.h. Applied to common and common_smp.

threadx_mutex_inherit_chain_test covers a chain of four suspended owners, which also checks the length limit, a chain ending at a ready owner, and a lock cycle, and checks the unchained behaviour when the option is not defined. Added to both suites, with TX_MUTEX_INHERIT_CHAIN_MAX=2 in default_build_coverage so the walk is built and covered. Without the fix it fails with ERROR #12 in both; with it, the mutex tests pass in both suites' default_build_coverage configuration and the new test passes in disable_notify_callbacks_build, where the option is not defined. The changed sources build cleanly under -Wall -Wextra -Werror with TX_NOT_INTERRUPTABLE, TX_MISRA_ENABLE and TX_DISABLE_PREEMPTION_THRESHOLD, with and without the option.

PR checklist

  • Updated function header with a short description and version number
  • Added test case for bug fix or new feature
  • Validated on real hardware

tx_mutex_get raised the owner of a TX_INHERIT mutex and stopped. If that owner was
itself blocked on a second inheriting mutex, the second owner never inherited the
priority: with H blocked on m1, owned by L1, blocked on m2, owned by L2, L2 stayed at
L1's old priority and H waited behind every thread between the two.

When TX_MUTEX_INHERIT_CHAIN_MAX is defined, tx_mutex_get passes the inherited priority
on through a new internal function, _tx_mutex_priority_chain. While the thread it last
raised is waiting on an inheriting mutex, it updates that mutex's highest waiting
priority and raises the mutex owner with _tx_mutex_priority_change, which handles ready
and suspended owners alike, for at most TX_MUTEX_INHERIT_CHAIN_MAX mutexes. It stops at
the first owner already at the priority or higher, which also ends it on a lock cycle.
The walk is iterative and only raises priorities. It is opt-in, so existing builds keep
their worst-case tx_mutex_get time. Documented in tx_user_sample.h. Applied to common
and common_smp.

threadx_mutex_inherit_chain_test covers a chain of four suspended owners, which also
checks the length limit, a chain ending at a ready owner, and a lock cycle, and checks
the unchained behaviour when the option is not defined. Added to both suites, with
TX_MUTEX_INHERIT_CHAIN_MAX=2 in default_build_coverage so the walk is built and covered.
Without the fix it fails with ERROR eclipse-threadx#12 in both; with it, the mutex tests pass in both
suites' default_build_coverage configuration and the new test passes in
disable_notify_callbacks_build, where the option is not defined. The changed sources
build cleanly under -Wall -Wextra -Werror with TX_NOT_INTERRUPTABLE, TX_MISRA_ENABLE and
TX_DISABLE_PREEMPTION_THRESHOLD, with and without the option.
@fdesbiens
fdesbiens self-requested a review October 16, 2026 13:30
@fdesbiens fdesbiens self-assigned this Oct 16, 2026

@fdesbiens fdesbiens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @howjmay. Thank you for this contribution. The bounded chain walk and its cycle test are useful. I left a comment on how the inherited priority is restored. Please retarget the PR to dev and share coverage for the new production code.

Comment thread common/src/tx_mutex_get.c
#ifdef TX_MUTEX_INHERIT_CHAIN_MAX

/* Pass the priority on to the owner of any mutex the owner is waiting on. */
_tx_mutex_priority_chain(mutex_owner, thread_ptr -> tx_thread_priority);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This passes a priority boost to downstream owners, but I cannot find a matching update when the triggering waiter leaves or lowers its priority. In an H → L1 → L2 chain, L2 can retain H’s priority after H stops waiting, even if #807 restores L1. Could you update the affected chain on those paths and add regression coverage?

This branch has not been deployed

No deployments
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