Skip to content

Commit 4f57b42

Browse files
Chris Friedtcfriedt
authored andcommitted
tests: kernel: mutex: move race timeout test to mutex_api
Previously, this change was added to `mutex_error_case`. That worked fine in `main`, but once the change was backported to `v2.7-branch`, the test would fail because it *did not* cause a failure. The reason for that, was that the `mutex_error_case` suite has `CONFIG_ZTEST_FATAL_HOOK=y`. With the newer ztest API, it allowed a separate suite to be used, allowing the test to pass (although it did not really fit in with the rest of the testsuite). The solution is to simply merge it with the `mutex_api` suite which uses non-inverted success logic. This change will also have to be cherry-picked for the backport in #49031. Fixes #48056. tests: kernel: mutex: move race timeout test to mutex_api Previously, this change was added to `mutex_error_case`. That worked fine in `main`, but once the change was backported to `v2.7-branch`, the test would fail because it *did not* cause a failure. The reason for that, was that the `mutex_error_case` suite has `CONFIG_ZTEST_FATAL_HOOK=y`. With the newer ztest API, it allowed a separate suite to be used, allowing the test to pass (although it did not really fit in with the rest of the testsuite). The solution is to simply merge it with the `mutex_api` suite which uses non-inverted success logic. This change will also have to be cherry-picked for the backport in #49031. Fixes #48056. Signed-off-by: Chris Friedt <[email protected]>
1 parent 024e949 commit 4f57b42

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright (c) 2022 Meta
3+
4+
config TEST_MUTEX_API_THREAD_CREATE_TICKS
5+
int "Wait time (in ticks) after thread creation"
6+
default 42
7+
8+
source "Kconfig"

tests/kernel/mutex/mutex_api/src/test_mutex_apis.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,68 @@ ZTEST_USER(mutex_api_1cpu, test_mutex_priority_inheritance)
387387
k_msleep(TIMEOUT+1000);
388388
}
389389

390+
static void tThread_mutex_lock_should_fail(void *p1, void *p2, void *p3)
391+
{
392+
k_timeout_t timeout;
393+
struct k_mutex *mutex = (struct k_mutex *)p1;
394+
395+
timeout.ticks = 0;
396+
timeout.ticks |= (uint64_t)(uintptr_t)p2 << 32;
397+
timeout.ticks |= (uint64_t)(uintptr_t)p3 << 0;
398+
399+
zassert_equal(-EAGAIN, k_mutex_lock(mutex, timeout), NULL);
400+
}
401+
402+
/**
403+
* @brief Test fix for subtle race during priority inversion
404+
*
405+
* - A low priority thread (Tlow) locks mutex A.
406+
* - A high priority thread (Thigh) blocks on mutex A, boosting the priority
407+
* of Tlow.
408+
* - Thigh times out waiting for mutex A.
409+
* - Before Thigh has a chance to execute, Tlow unlocks mutex A (which now
410+
* has no owner) and drops its own priority.
411+
* - Thigh now gets a chance to execute and finds that it timed out, and
412+
* then enters the block of code to lower the priority of the thread that
413+
* owns mutex A (now nobody).
414+
* - Thigh tries to the dereference the owner of mutex A (which is nobody,
415+
* and thus it is NULL). This leads to an exception.
416+
*
417+
* @ingroup kernel_mutex_tests
418+
*
419+
* @see k_mutex_lock()
420+
*/
421+
ZTEST(mutex_api_1cpu, test_mutex_timeout_race_during_priority_inversion)
422+
{
423+
k_timeout_t timeout;
424+
uintptr_t timeout_upper;
425+
uintptr_t timeout_lower;
426+
int helper_prio = k_thread_priority_get(k_current_get()) + 1;
427+
428+
k_mutex_init(&mutex);
429+
430+
/* align to tick boundary */
431+
k_sleep(K_TICKS(1));
432+
433+
/* allow non-kobject data to be shared (via registers) */
434+
timeout = K_TIMEOUT_ABS_TICKS(k_uptime_ticks()
435+
+ CONFIG_TEST_MUTEX_API_THREAD_CREATE_TICKS);
436+
timeout_upper = timeout.ticks >> 32;
437+
timeout_lower = timeout.ticks & BIT64_MASK(32);
438+
439+
k_mutex_lock(&mutex, K_FOREVER);
440+
k_thread_create(&tdata, tstack, K_THREAD_STACK_SIZEOF(tstack),
441+
tThread_mutex_lock_should_fail, &mutex, (void *)timeout_upper,
442+
(void *)timeout_lower, helper_prio,
443+
K_USER | K_INHERIT_PERMS, K_NO_WAIT);
444+
445+
k_thread_priority_set(k_current_get(), K_HIGHEST_THREAD_PRIO);
446+
447+
k_sleep(timeout);
448+
449+
k_mutex_unlock(&mutex);
450+
}
451+
390452
static void *mutex_api_tests_setup(void)
391453
{
392454
#ifdef CONFIG_USERSPACE

0 commit comments

Comments
 (0)