As of today <zephyr/zephyr.h> is 100% equivalent to <zephyr/kernel.h>. This patch proposes to then include <zephyr/kernel.h> instead of <zephyr/zephyr.h> since it is more clear that you are including the Kernel APIs and (probably) nothing else. <zephyr/zephyr.h> sounds like a catch-all header that may be confusing. Most applications need to include a bunch of other things to compile, e.g. driver headers or subsystem headers like BT, logging, etc. The idea of a catch-all header in Zephyr is probably not feasible anyway. Reason is that Zephyr is not a library, like it could be for example `libpython`. Zephyr provides many utilities nowadays: a kernel, drivers, subsystems, etc and things will likely grow. A catch-all header would be massive, difficult to keep up-to-date. It is also likely that an application will only build a small subset. Note that subsystem-level headers may use a catch-all approach to make things easier, though. NOTE: This patch is **NOT** removing the header, just removing its usage in-tree. I'd advocate for its deprecation (add a #warning on it), but I understand many people will have concerns. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
146 lines
3.5 KiB
C
146 lines
3.5 KiB
C
/*
|
|
* Copyright (c) 2021 intel, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef CONFIG_USERSPACE
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/ztest.h>
|
|
#include <zephyr/sys/mutex.h>
|
|
|
|
#define HIGH_T1 0
|
|
#define HIGH_T2 1
|
|
#define LOW_PRO 2
|
|
|
|
#define STACKSIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
|
|
|
|
static K_THREAD_STACK_DEFINE(thread_low_stack, STACKSIZE);
|
|
static struct k_thread thread_low_data;
|
|
static K_THREAD_STACK_DEFINE(thread_high_stack1, STACKSIZE);
|
|
static struct k_thread thread_high_data1;
|
|
static K_THREAD_STACK_DEFINE(thread_high_stack2, STACKSIZE);
|
|
static struct k_thread thread_high_data2;
|
|
SYS_MUTEX_DEFINE(mutex);
|
|
static uint32_t flag[3];
|
|
|
|
/* The order of threads getting mutex is judged by index
|
|
* self addition.
|
|
*/
|
|
static uint32_t order;
|
|
|
|
static void low_prio_wait_for_mutex(void *p1, void *p2, void *p3)
|
|
{
|
|
struct sys_mutex *pmutex = p1;
|
|
|
|
sys_mutex_lock(pmutex, K_FOREVER);
|
|
|
|
flag[2] = order;
|
|
|
|
order++;
|
|
/* Keep mutex for a while */
|
|
k_sleep(K_MSEC(10));
|
|
|
|
sys_mutex_unlock(pmutex);
|
|
}
|
|
|
|
static void high_prio_t1_wait_for_mutex(void *p1, void *p2, void *p3)
|
|
{
|
|
struct sys_mutex *pmutex = p1;
|
|
|
|
sys_mutex_lock(pmutex, K_FOREVER);
|
|
|
|
flag[0] = order;
|
|
|
|
order++;
|
|
/* Keep mutex for a while */
|
|
k_sleep(K_MSEC(10));
|
|
|
|
sys_mutex_unlock(pmutex);
|
|
}
|
|
|
|
static void high_prio_t2_wait_for_mutex(void *p1, void *p2, void *p3)
|
|
{
|
|
struct sys_mutex *pmutex = p1;
|
|
|
|
sys_mutex_lock(pmutex, K_FOREVER);
|
|
|
|
flag[1] = order;
|
|
|
|
order++;
|
|
/* Keep mutex for a while */
|
|
k_sleep(K_MSEC(10));
|
|
|
|
sys_mutex_unlock(pmutex);
|
|
}
|
|
|
|
/**
|
|
* @brief Test multi-threads to take mutex.
|
|
*
|
|
* @details Define three threads, and set a higher priority for two of them,
|
|
* and set a lower priority for the last one. Then Add a delay between
|
|
* creating the two high priority threads.
|
|
* Test point:
|
|
* 1. Any number of threads may wait on a mutex locked by others
|
|
* simultaneously.
|
|
* 2. When the mutex is released, it is took by the highest priority
|
|
* thread that has waited longest.
|
|
*
|
|
* @ingroup kernel_mutex_tests
|
|
*/
|
|
ZTEST(mutex_complex, test_mutex_multithread_competition)
|
|
{
|
|
int old_prio = k_thread_priority_get(k_current_get());
|
|
int prio = 10;
|
|
flag[0] = flag[1] = flag[2] = 0;
|
|
order = 0;
|
|
|
|
sys_mutex_lock(&mutex, K_NO_WAIT);
|
|
|
|
k_thread_priority_set(k_current_get(), prio);
|
|
|
|
k_thread_create(&thread_high_data1, thread_high_stack1, STACKSIZE,
|
|
high_prio_t1_wait_for_mutex,
|
|
&mutex, NULL, NULL,
|
|
prio + 2, 0, K_NO_WAIT);
|
|
|
|
/* Thread thread_high_data1 wait more time than thread_high_data2 */
|
|
k_sleep(K_MSEC(10));
|
|
|
|
k_thread_create(&thread_low_data, thread_low_stack, STACKSIZE,
|
|
low_prio_wait_for_mutex,
|
|
&mutex, NULL, NULL,
|
|
prio + 4, 0, K_NO_WAIT);
|
|
|
|
k_thread_create(&thread_high_data2, thread_high_stack2, STACKSIZE,
|
|
high_prio_t2_wait_for_mutex,
|
|
&mutex, NULL, NULL,
|
|
prio + 2, 0, K_NO_WAIT);
|
|
|
|
/* Release mutex by current thread */
|
|
sys_mutex_unlock(&mutex);
|
|
|
|
/* Wait for thread exiting */
|
|
k_thread_join(&thread_low_data, K_FOREVER);
|
|
k_thread_join(&thread_high_data1, K_FOREVER);
|
|
k_thread_join(&thread_high_data2, K_FOREVER);
|
|
|
|
/* The mutex should be keep by high prio t1 thread */
|
|
zassert_true(flag[0] == HIGH_T1,
|
|
"The highest priority thread failed to take the mutex.");
|
|
|
|
/* The mutex should be keep by high prio t2 thread */
|
|
zassert_true(flag[1] == HIGH_T2,
|
|
"The higher priority thread failed to take the mutex.");
|
|
|
|
/* The mutex should be keep by low prio thread */
|
|
zassert_true(flag[2] == LOW_PRO,
|
|
"The low priority thread failed to take the mutex.");
|
|
|
|
/* Revert priority of the main thread */
|
|
k_thread_priority_set(k_current_get(), old_prio);
|
|
}
|
|
|
|
#endif /** not CONFIG_USERSPACE */
|