Skip to content

Commit 019a6ec

Browse files
Christopher Friedtfabiobaltieri
authored andcommitted
tests: kernel: mutex: test for lock timeout race
Say threadA holds a mutex and threadB tries to lock it with a timeout, a race would occur if threadA unlock that mutex after threadB got unpended by sys_clock and before it gets scheduled and calls k_spin_lock. This patch supplies the test that can be used to reproduce the problem and the fix that was provided in #48056 Fixes #48056 Signed-off-by: Christopher Friedt <[email protected]>
1 parent 884d747 commit 019a6ec

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2022 SeediqQ from Issue 48056
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/ztest.h>
8+
9+
#define TIMEOUT_MS 100
10+
#define STACKSZ 8192
11+
12+
static struct k_mutex mutex;
13+
static struct k_thread thread;
14+
15+
K_THREAD_STACK_DEFINE(stack, STACKSZ);
16+
17+
static void test_thread(void *p1, void *p2, void *p3)
18+
{
19+
ARG_UNUSED(p1);
20+
ARG_UNUSED(p2);
21+
ARG_UNUSED(p3);
22+
23+
zassert_equal(-EAGAIN, k_mutex_lock(&mutex, K_MSEC(TIMEOUT_MS)));
24+
}
25+
26+
/**
27+
* @brief Test fix for subtle race during priority inversion
28+
*
29+
* - A low priority thread (Tlow) locks mutex A.
30+
* - A high priority thread (Thigh) blocks on mutex A, boosting the priority
31+
* of Tlow.
32+
* - Thigh times out waiting for mutex A.
33+
* - Before Thigh has a chance to execute, Tlow unlocks mutex A (which now
34+
* has no owner) and drops its own priority.
35+
* - Thigh now gets a chance to execute and finds that it timed out, and
36+
* then enters the block of code to lower the priority of the thread that
37+
* owns mutex A (now nobody).
38+
* - Thigh tries to the dereference the owner of mutex A (which is nobody,
39+
* and thus it is NULL). This leads to an exception.
40+
*
41+
* @ingroup kernel_mutex_tests
42+
*
43+
* @see k_mutex_lock()
44+
*/
45+
ZTEST(mutex_timeout_race_during_priority_inversion, test_mutex_timeout_error)
46+
{
47+
k_mutex_init(&mutex);
48+
49+
/* align to tick boundary */
50+
k_sleep(K_TICKS(1));
51+
k_thread_create(&thread, stack, K_THREAD_STACK_SIZEOF(stack), test_thread, NULL, NULL, NULL,
52+
8, 0, K_NO_WAIT);
53+
54+
k_mutex_lock(&mutex, K_FOREVER);
55+
56+
k_sleep(K_MSEC(TIMEOUT_MS));
57+
58+
k_mutex_unlock(&mutex);
59+
}
60+
61+
ZTEST_SUITE(mutex_timeout_race_during_priority_inversion, NULL, NULL, NULL, NULL, NULL);

0 commit comments

Comments
 (0)