tests: add threads scheduling test case with unified kernel
this commit cover thread scheduling relevant apis k_current_get() k_sched_lock() k_sched_unlock() k_yield() k_sleep() k_wakeup() k_busy_wait() k_sched_time_slice_set() Change-Id: Ie449db3dda910bc1bafc0b5a04633f284e7f1dc3 Signed-off-by: jing wang <jing.j.wang@intel.com> Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
4b288999b2
commit
b10ab24c02
8 changed files with 421 additions and 0 deletions
4
tests/kernel/threads_scheduling/schedule_api/Makefile
Normal file
4
tests/kernel/threads_scheduling/schedule_api/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
BOARD ?= qemu_x86
|
||||||
|
CONF_FILE = prj.conf
|
||||||
|
|
||||||
|
include ${ZEPHYR_BASE}/Makefile.inc
|
1
tests/kernel/threads_scheduling/schedule_api/prj.conf
Normal file
1
tests/kernel/threads_scheduling/schedule_api/prj.conf
Normal file
|
@ -0,0 +1 @@
|
||||||
|
CONFIG_ZTEST=y
|
|
@ -0,0 +1,3 @@
|
||||||
|
include $(ZEPHYR_BASE)/tests/Makefile.test
|
||||||
|
|
||||||
|
obj-y = main.o test_sched_priority.o test_sched_timeslice_and_lock.o
|
43
tests/kernel/threads_scheduling/schedule_api/src/main.c
Normal file
43
tests/kernel/threads_scheduling/schedule_api/src/main.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup t_kernel_threads
|
||||||
|
* @{
|
||||||
|
* @defgroup t_threads_scheduling test_threads_scheduling
|
||||||
|
* @brief TestPurpose: verify threads scheduling based on priority, time
|
||||||
|
* slice and lock/unlock
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_sched.h"
|
||||||
|
|
||||||
|
/*test case main entry*/
|
||||||
|
void test_main(void *p1, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
ztest_test_suite(test_threads_scheduling,
|
||||||
|
ztest_unit_test(test_priority_cooperative),
|
||||||
|
ztest_unit_test(test_priority_preemptible),
|
||||||
|
ztest_unit_test(test_yield_cooperative),
|
||||||
|
ztest_unit_test(test_sleep_cooperative),
|
||||||
|
ztest_unit_test(test_sleep_wakeup_preemptible),
|
||||||
|
ztest_unit_test(test_time_slicing_preemptible),
|
||||||
|
ztest_unit_test(test_time_slicing_disable_preemptible),
|
||||||
|
ztest_unit_test(test_lock_preemptible),
|
||||||
|
ztest_unit_test(test_unlock_preemptible)
|
||||||
|
);
|
||||||
|
ztest_run_test_suite(test_threads_scheduling);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TEST_SCHED_H__
|
||||||
|
#define __TEST_SCHED_H__
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <ztest.h>
|
||||||
|
|
||||||
|
#define STACK_SIZE 256
|
||||||
|
|
||||||
|
struct thread_data {
|
||||||
|
k_tid_t tid;
|
||||||
|
int priority;
|
||||||
|
int executed;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_priority_cooperative(void);
|
||||||
|
void test_priority_preemptible(void);
|
||||||
|
void test_yield_cooperative(void);
|
||||||
|
void test_sleep_cooperative(void);
|
||||||
|
void test_sleep_wakeup_preemptible(void);
|
||||||
|
void test_time_slicing_preemptible(void);
|
||||||
|
void test_time_slicing_disable_preemptible(void);
|
||||||
|
void test_lock_preemptible(void);
|
||||||
|
void test_unlock_preemptible(void);
|
||||||
|
|
||||||
|
#endif /* __TEST_SCHED_H__ */
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup t_threads_scheduling
|
||||||
|
* @{
|
||||||
|
* @defgroup t_threads_priority test_threads_priority
|
||||||
|
* @brief TestPurpose: verify threads scheduling priority
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_sched.h"
|
||||||
|
|
||||||
|
static char __noinit __stack tstack[STACK_SIZE];
|
||||||
|
static int last_prio;
|
||||||
|
|
||||||
|
static void thread_entry(void *p1, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
last_prio = k_thread_priority_get(k_current_get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*test cases*/
|
||||||
|
void test_priority_cooperative(void)
|
||||||
|
{
|
||||||
|
int old_prio = k_thread_priority_get(k_current_get());
|
||||||
|
|
||||||
|
/* set current thread to a negative priority */
|
||||||
|
last_prio = -1;
|
||||||
|
k_thread_priority_set(k_current_get(), last_prio);
|
||||||
|
|
||||||
|
/* spawn thread with higher priority */
|
||||||
|
int spawn_prio = last_prio - 1;
|
||||||
|
|
||||||
|
k_tid_t tid = k_thread_spawn(tstack, STACK_SIZE,
|
||||||
|
thread_entry, NULL, NULL, NULL,
|
||||||
|
spawn_prio, 0, 0);
|
||||||
|
/* checkpoint: current thread shouldn't preempted by higher thread */
|
||||||
|
assert_true(last_prio == k_thread_priority_get(k_current_get()), NULL);
|
||||||
|
k_sleep(100);
|
||||||
|
/* checkpoint: spawned thread get executed */
|
||||||
|
assert_true(last_prio == spawn_prio, NULL);
|
||||||
|
k_thread_abort(tid);
|
||||||
|
|
||||||
|
/* restore environment */
|
||||||
|
k_thread_priority_set(k_current_get(), old_prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_priority_preemptible(void)
|
||||||
|
{
|
||||||
|
int old_prio = k_thread_priority_get(k_current_get());
|
||||||
|
|
||||||
|
/* set current thread to a non-negative priority */
|
||||||
|
last_prio = 2;
|
||||||
|
k_thread_priority_set(k_current_get(), last_prio);
|
||||||
|
|
||||||
|
int spawn_prio = last_prio - 1;
|
||||||
|
|
||||||
|
k_tid_t tid = k_thread_spawn(tstack, STACK_SIZE,
|
||||||
|
thread_entry, NULL, NULL, NULL,
|
||||||
|
spawn_prio, 0, 0);
|
||||||
|
/* checkpoint: thread is preempted by higher thread */
|
||||||
|
assert_true(last_prio == spawn_prio, NULL);
|
||||||
|
|
||||||
|
k_sleep(100);
|
||||||
|
k_thread_abort(tid);
|
||||||
|
|
||||||
|
spawn_prio = last_prio + 1;
|
||||||
|
tid = k_thread_spawn(tstack, STACK_SIZE,
|
||||||
|
thread_entry, NULL, NULL, NULL,
|
||||||
|
spawn_prio, 0, 0);
|
||||||
|
/* checkpoint: thread is not preempted by lower thread */
|
||||||
|
assert_false(last_prio == spawn_prio, NULL);
|
||||||
|
k_thread_abort(tid);
|
||||||
|
|
||||||
|
/* restore environment */
|
||||||
|
k_thread_priority_set(k_current_get(), old_prio);
|
||||||
|
}
|
|
@ -0,0 +1,235 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Intel Corporation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup t_threads_scheduling
|
||||||
|
* @{
|
||||||
|
* @defgroup t_sched_timeslice_and_lock test_sched_timeslice_and_lock
|
||||||
|
* @brief TestPurpose: verify sched time slice and lock/unlock
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_sched.h"
|
||||||
|
#define THREADS_NUM 3
|
||||||
|
static char __noinit __stack tstack[THREADS_NUM][STACK_SIZE];
|
||||||
|
|
||||||
|
static struct thread_data tdata[THREADS_NUM];
|
||||||
|
static int old_prio, init_prio;
|
||||||
|
|
||||||
|
static void thread_entry(void *p1, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
int sleep_ms = (int)p2;
|
||||||
|
|
||||||
|
if (sleep_ms > 0) {
|
||||||
|
k_sleep(sleep_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tnum = (int)p1;
|
||||||
|
|
||||||
|
tdata[tnum].executed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_threads(void)
|
||||||
|
{
|
||||||
|
old_prio = k_thread_priority_get(k_current_get());
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
/* spawn thread with higher priority */
|
||||||
|
tdata[i].priority = init_prio - 1;
|
||||||
|
} else if (i == 1) {
|
||||||
|
/* spawn thread with same priority */
|
||||||
|
tdata[i].priority = init_prio;
|
||||||
|
} else {
|
||||||
|
/* spawn thread with lower priority */
|
||||||
|
tdata[i].priority = init_prio + 1;
|
||||||
|
}
|
||||||
|
tdata[i].executed = 0;
|
||||||
|
}
|
||||||
|
k_thread_priority_set(k_current_get(), init_prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spawn_threads(int sleep_sec)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
tdata[i].tid = k_thread_spawn(tstack[i], STACK_SIZE,
|
||||||
|
thread_entry, (void *)i, (void *)sleep_sec, NULL,
|
||||||
|
tdata[i].priority, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void teardown_threads(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
k_thread_abort(tdata[i].tid);
|
||||||
|
}
|
||||||
|
k_thread_priority_set(k_current_get(), old_prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*test cases*/
|
||||||
|
void test_yield_cooperative(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* set current thread to a cooperative priority */
|
||||||
|
init_prio = -1;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
spawn_threads(0);
|
||||||
|
/* checkpoint: only higher priority thread get executed when yield */
|
||||||
|
k_yield();
|
||||||
|
assert_true(tdata[0].executed == 1, NULL);
|
||||||
|
assert_true(tdata[1].executed == 1, NULL);
|
||||||
|
for (int i = 2; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_sleep_cooperative(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a cooperative priority */
|
||||||
|
init_prio = -1;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
spawn_threads(0);
|
||||||
|
/* checkpoint: all ready threads get executed when k_sleep */
|
||||||
|
k_sleep(100);
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_busy_wait_cooperative(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a preemptible priority */
|
||||||
|
init_prio = -1;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
spawn_threads(0);
|
||||||
|
k_busy_wait(100000); /* 100 ms */
|
||||||
|
/* checkpoint: No other threads get executed */
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_sleep_wakeup_preemptible(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a preemptible priority */
|
||||||
|
init_prio = 0;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
spawn_threads(10 * 1000); /* 10 second */
|
||||||
|
/* checkpoint: lower threads not executed, high threads are in sleep */
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
k_wakeup(tdata[0].tid);
|
||||||
|
assert_true(tdata[0].executed == 1, NULL);
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_time_slicing_preemptible(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a preemptible priority */
|
||||||
|
init_prio = 0;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
k_sched_time_slice_set(200, 0); /* 200 ms */
|
||||||
|
spawn_threads(0);
|
||||||
|
/* checkpoint: higher priority threads get executed immediately */
|
||||||
|
assert_true(tdata[0].executed == 1, NULL);
|
||||||
|
k_busy_wait(500000); /* 500 ms */
|
||||||
|
/* checkpoint: equal priority threads get executed every time slice */
|
||||||
|
assert_true(tdata[1].executed == 1, NULL);
|
||||||
|
for (int i = 2; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore environment */
|
||||||
|
k_sched_time_slice_set(0, 0); /* disable time slice */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_time_slicing_disable_preemptible(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a preemptible priority */
|
||||||
|
init_prio = 0;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
spawn_threads(0);
|
||||||
|
/* checkpoint: higher priority threads get executed immediately */
|
||||||
|
assert_true(tdata[0].executed == 1, NULL);
|
||||||
|
k_busy_wait(500000); /* 500 ms */
|
||||||
|
/* checkpoint: equal priority threads get executed every time slice */
|
||||||
|
assert_true(tdata[1].executed == 0, NULL);
|
||||||
|
for (int i = 2; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_lock_preemptible(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a preemptible priority */
|
||||||
|
init_prio = 0;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
k_sched_lock();
|
||||||
|
spawn_threads(0);
|
||||||
|
/* do critical thing */
|
||||||
|
k_busy_wait(100000);
|
||||||
|
/* checkpoint: all other threads not been executed */
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
/* make current thread unready */
|
||||||
|
k_sleep(100);
|
||||||
|
/* checkpoint: all other threads get executed */
|
||||||
|
for (int i = 0; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 1, NULL);
|
||||||
|
}
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_unlock_preemptible(void)
|
||||||
|
{
|
||||||
|
/* set current thread to a preemptible priority */
|
||||||
|
init_prio = 0;
|
||||||
|
setup_threads();
|
||||||
|
|
||||||
|
k_sched_lock();
|
||||||
|
spawn_threads(0);
|
||||||
|
/* do critical thing */
|
||||||
|
k_busy_wait(100000);
|
||||||
|
|
||||||
|
k_sched_unlock();
|
||||||
|
/* checkpoint: higher threads get executed */
|
||||||
|
assert_true(tdata[0].executed == 1, NULL);
|
||||||
|
for (int i = 1; i < THREADS_NUM; i++) {
|
||||||
|
assert_true(tdata[i].executed == 0, NULL);
|
||||||
|
}
|
||||||
|
/* restore environment */
|
||||||
|
teardown_threads();
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
[test]
|
||||||
|
tags = kernel
|
||||||
|
# tickless is not supported on nios2
|
||||||
|
arch_exclude = nios2
|
Loading…
Add table
Add a link
Reference in a new issue