Skip to content

!threads: implement robust and priority ceiling locks#815

Draft
adamgreloch wants to merge 2 commits into
masterfrom
adamgreloch/RTOS-1399
Draft

!threads: implement robust and priority ceiling locks#815
adamgreloch wants to merge 2 commits into
masterfrom
adamgreloch/RTOS-1399

Conversation

@adamgreloch

@adamgreloch adamgreloch commented Jul 22, 2026

Copy link
Copy Markdown
Member

TASK: RTOS-1399

Description

Motivation and Context

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Chore (refactoring, style fixes, git/CI config, submodule management, no code logic changes)

How Has This Been Tested?

  • Already covered by automatic testing.
  • New test added: (add PR link here).
  • Tested by hand on: (list targets here).

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Special treatment

  • This PR needs additional PRs to work (list the PRs, preferably in merge-order).
  • I will merge this PR by myself when appropriate.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for robust mutexes and the priority ceiling protocol, adding new syscalls and internal functions such as mutexConsistent and mutexPrioCeiling. Feedback highlights several critical issues: priority is not immediately elevated to the ceiling upon lock acquisition, proc_lockConsistent lacks robust-lock validation and allows non-owners to clear inconsistency, proc_mutexCreate does not validate the protocol field, proc_lockPrioCeiling fails to check for invalid negative ceiling values, and disabling assertions with #if 0 leaves dead code in the codebase.

Comment thread proc/threads.c
Comment thread proc/threads.c Outdated
Comment thread proc/mutex.c
Comment thread proc/threads.c Outdated
Comment on lines +1880 to +1882
else if (prioceiling > MAX_PRIO) {
err = -EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

proc_lockPrioCeiling does not check if prioceiling < -1. It should return -EINVAL for any negative value other than -1 (which is used to retrieve the ceiling).

else if (prioceiling < -1 || prioceiling > MAX_PRIO) {
		err = -EINVAL;
	}

Comment thread proc/threads.c Outdated
static int _proc_lockClear(lock_t *lock)
{
#ifndef NDEBUG
#if 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Changing #ifndef NDEBUG to #if 0 disables assertions completely and leaves dead code in the codebase. If the ownership assertion is invalid for PH_LOCK_NORMAL locks (which can be unlocked by other threads), the assertion should be conditionally checked based on the lock type instead of being completely disabled.

#ifndef NDEBUG

Comment thread proc/mutex.c
return -EINVAL;
}

if (attr->protocol == PH_LOCK_PROTO_PRIOCEILING && attr->prioceiling > MAX_PRIO) {
Comment thread proc/mutex.c
return -EINVAL;
}

if (attr->protocol == PH_LOCK_PROTO_PRIOCEILING && attr->prioceiling > MAX_PRIO) {
Comment thread proc/threads.c
_Static_assert(sizeof(threads_common.ready) / sizeof(threads_common.ready[0]) <= (u8)-1, "queue size must fit into priority type");

#define MAX_PRIO ((u8)(sizeof(threads_common.ready) / sizeof(threads_common.ready[0])) - 1U)
_Static_assert(MAX_PRIO <= (u8)-1, "MAX_PRIO must fit into priority type");
Comment thread proc/threads.c
thread_t *thread = lock->queue;

if (thread != NULL) {
if (lock->attr.protocol == PH_LOCK_PROTO_PRIOCEILING) {
Comment thread proc/threads.c
return lock->attr.prioceiling;
}

if (lock->attr.protocol == PH_LOCK_PROTO_INHERIT && thread != NULL) {
Comment thread proc/threads.c

lock->owner = current;
lock->depth = 1;
if (lock->inconsistent != 0 && lock->attr.robust != 0) {
Comment thread proc/threads.c Outdated
hal_spinlockSet(&lock->spinlock, &sc);

if (lock->owner == NULL || lock->owner == proc_current()) {
if (lock->inconsistent != 0) {
Comment thread proc/threads.c

hal_spinlockSet(&lock->spinlock, &sc);

if (lock->attr.protocol != PH_LOCK_PROTO_PRIOCEILING) {
Comment thread proc/threads.c
err = -EINVAL;
}
else {
err = lock->attr.prioceiling;
Comment thread proc/threads.c
err = lock->attr.prioceiling;
if (prioceiling >= 0) {
if (lock->owner == NULL || lock->owner == proc_current()) {
lock->attr.prioceiling = prioceiling;
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Unit Test Results

11 307 tests  ±0   10 600 ✅ +1   53m 51s ⏱️ + 1m 24s
   690 suites ±0      707 💤 ±0 
     1 files   ±0        0 ❌  - 1 

Results for commit 324eb5b. ± Comparison against base commit fb914a8.

♻️ This comment has been updated with latest results.

Some assertions are too radical for the DEBUG=1.

The panic on "unlock on unlocked lock" assertions is particularly too
harsh, as the kernel can easily recover from such state and return
-EPERM. POSIX tests will test that path and since the CI test runner
runs under DEBUG=1, the test would fail.

TASK: RTOS-1399
@adamgreloch
adamgreloch force-pushed the adamgreloch/RTOS-1399 branch from 99aa11d to 324eb5b Compare July 22, 2026 11:58
Comment thread proc/mutex.c
return -EINVAL;
}

if ((attr->protocol != PH_LOCK_PROTO_INHERIT) && (attr->protocol != PH_LOCK_PROTO_NOINHERIT) && (attr->protocol != PH_LOCK_PROTO_PRIOCEILING)) {
Comment thread proc/mutex.c
return -EINVAL;
}

if ((attr->protocol != PH_LOCK_PROTO_INHERIT) && (attr->protocol != PH_LOCK_PROTO_NOINHERIT) && (attr->protocol != PH_LOCK_PROTO_PRIOCEILING)) {
Comment thread proc/mutex.c
return -EINVAL;
}

if ((attr->protocol != PH_LOCK_PROTO_INHERIT) && (attr->protocol != PH_LOCK_PROTO_NOINHERIT) && (attr->protocol != PH_LOCK_PROTO_PRIOCEILING)) {
Comment thread proc/threads.c
hal_spinlockSet(&lock->spinlock, &sc);

if (lock->owner == proc_current()) {
if (lock->attr.robust != 0 && lock->inconsistent != 0) {
Comment thread proc/threads.c

hal_spinlockSet(&lock->spinlock, &sc);

if (lock->attr.protocol != PH_LOCK_PROTO_PRIOCEILING) {
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