Skip to content

refactor(zkernel): back k_mutex with FreeRTOS recursive mutex#55

Open
swoisz wants to merge 1 commit into
mainfrom
refactor/zkernel-mutex-recursive
Open

refactor(zkernel): back k_mutex with FreeRTOS recursive mutex#55
swoisz wants to merge 1 commit into
mainfrom
refactor/zkernel-mutex-recursive

Conversation

@swoisz

@swoisz swoisz commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Why

k_mutex was implemented as a non-recursive FreeRTOS mutex plus manual owner/count re-entrancy tracking, on the belief that FreeRTOS recursive mutexes lack priority inheritance. That premise is false.

Both mutex types route a blocking take through xQueueSemaphoreTake, which priority-inherits for any mutex-type queue — gated only on uxQueueType == queueQUEUE_IS_MUTEX, set for recursive and non-recursive alike by prvInitialiseMutex. Verified against ESP-IDF's FreeRTOS-Kernel (configUSE_RECURSIVE_MUTEXES=1):

  • xQueueTakeMutexRecursive (queue.c) falls through to xQueueSemaphoreTake when it blocks
  • xQueueSemaphoreTake calls xTaskPriorityInherit(...)

So the recursive mutex already gives us re-entrancy + PI in one primitive. The manual layer bought only the debug instrumentation, which isn't yet justified — safer to ride the battle-tested FreeRTOS primitive.

What

  • Collapse k_mutex to a thin wrapper over xSemaphoreCreateRecursiveMutexStatic / TakeRecursive / GiveRecursive. Public API, error codes (-EBUSY/-EAGAIN/-EPERM/-EWOULDBLOCK), and ISR handling unchanged.
  • Drop the manual owner/count state and the debug/ordered extension (k_mutex_init_ordered, K_MUTEX_DEFINE_ORDERED, CONFIG_ZKERNEL_MUTEX_DEBUG, CONFIG_ZKERNEL_MUTEX_HOLD_WARNING_MS) — no in-repo callers.
  • Correct the stale rationale in k_mutex.c, kernel.h, README.md, and devlog/review/k_mutex.md; document the ISR (-EWOULDBLOCK) and -EPERM-breadth divergences inline.

k_mutex.c: 109 → 55 lines.

⚠️ Breaking change

Removes k_mutex_init_ordered, K_MUTEX_DEFINE_ORDERED, CONFIG_ZKERNEL_MUTEX_DEBUG, CONFIG_ZKERNEL_MUTEX_HOLD_WARNING_MS — Boreas extensions (not Zephyr API) that shipped in v0.1.0. Wants a minor bump (0.2.0), not a patch. The two submodule consumers don't use these.

Verification

  • clang-format --dry-run -Werror clean on changed files
  • linux host build clean (-Werror)
  • 224 Tests 0 Failures, including all 8 mutex tests and the 3 PI tests (priority_boost, priority_restore, pi_prevents_inversion)

Reviews run

  • /boreas-review: 1 blocker (stale header banner), fixed in-branch. Zephyr conformance improved.
  • /code-review xhigh: zero correctness findings.

🤖 Generated with Claude Code

FreeRTOS recursive mutexes already provide both re-entrancy and priority
inheritance: a blocking xSemaphoreTakeRecursive routes through
xQueueSemaphoreTake, which priority-inherits for any mutex-type queue
(gated only on uxQueueType == queueQUEUE_IS_MUTEX, set for recursive and
non-recursive alike). The prior non-recursive-mutex + manual owner/count
implementation was built on the false premise that recursive mutexes
lack PI.

Collapse k_mutex to a thin wrapper over the recursive primitive and drop
the manual re-entrancy state. Public API (init/lock/unlock), error
codes, and ISR handling are unchanged.

Also removes the CONFIG_ZKERNEL_MUTEX_DEBUG lock-ordering / hold-time
instrumentation and the ordered-mutex API, which existed only to feed
off that manual state and were not yet justified -- safer to ride the
battle-tested FreeRTOS primitive.

Verified: linux host build clean, 224 tests pass including all 8 mutex
tests and the 3 priority-inheritance tests.

BREAKING CHANGE: removes k_mutex_init_ordered, K_MUTEX_DEFINE_ORDERED,
CONFIG_ZKERNEL_MUTEX_DEBUG, and CONFIG_ZKERNEL_MUTEX_HOLD_WARNING_MS
(Boreas extensions, not Zephyr API; shipped in v0.1.0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant