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