Browse Source
Adds a test to test the objects integrated into the object core statistics framework. Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>pull/63341/head
4 changed files with 729 additions and 0 deletions
@ -0,0 +1,8 @@ |
|||||||
|
# SPDX-License-Identifier: Apache-2.0 |
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0) |
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) |
||||||
|
project(obj_core) |
||||||
|
|
||||||
|
FILE(GLOB app_sources src/*.c) |
||||||
|
target_sources(app PRIVATE ${app_sources}) |
@ -0,0 +1,8 @@ |
|||||||
|
CONFIG_ZTEST=y |
||||||
|
CONFIG_ZTEST_NEW_API=y |
||||||
|
CONFIG_OBJ_CORE=y |
||||||
|
CONFIG_OBJ_CORE_STATS=y |
||||||
|
CONFIG_SCHED_THREAD_USAGE=y |
||||||
|
CONFIG_SCHED_THREAD_USAGE_ANALYSIS=y |
||||||
|
CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION=y |
||||||
|
CONFIG_SYS_MEM_BLOCKS=y |
@ -0,0 +1,704 @@ |
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Intel Corporation |
||||||
|
* |
||||||
|
* SPDX-License-Identifier: Apache-2.0 |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <zephyr/ztest.h> |
||||||
|
#include <zephyr/sys/mem_blocks.h> |
||||||
|
|
||||||
|
SYS_MEM_BLOCKS_DEFINE(mem_block, 32, 4, 16); /* Four 32 byte blocks */ |
||||||
|
|
||||||
|
K_MEM_SLAB_DEFINE(mem_slab, 32, 4, 16); /* Four 32 byte blocks */ |
||||||
|
|
||||||
|
#if !defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_SPARC) && !defined(CONFIG_MIPS) |
||||||
|
static void test_thread_entry(void *, void *, void *); |
||||||
|
K_THREAD_DEFINE(test_thread, 1024, test_thread_entry, NULL, NULL, NULL, |
||||||
|
K_HIGHEST_THREAD_PRIO, 0, 0); |
||||||
|
|
||||||
|
K_SEM_DEFINE(wake_main_thread, 0, 1); |
||||||
|
K_SEM_DEFINE(wake_test_thread, 0, 1); |
||||||
|
#endif /* !CONFIG_ARCH_POSIX && !CONFIG_SPARC && !CONFIG_MIPS */ |
||||||
|
|
||||||
|
#if CONFIG_MP_MAX_NUM_CPUS > 1 |
||||||
|
K_THREAD_STACK_ARRAY_DEFINE(busy_thread_stack, CONFIG_MP_MAX_NUM_CPUS - 1, 512); |
||||||
|
|
||||||
|
struct k_thread busy_thread[CONFIG_MP_MAX_NUM_CPUS - 1]; |
||||||
|
|
||||||
|
void busy_thread_entry(void *p1, void *p2, void *p3) |
||||||
|
{ |
||||||
|
while (1) { |
||||||
|
/* Busy loop to prevent CPU from entering idle */ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
/***************** SYSTEM (CPUs and KERNEL) ******************/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* As the k_obj_core_stats_xxx() APIs are essentially wrappers to the |
||||||
|
* thread runtime stats APIs, limit this test to the same architectures as |
||||||
|
* that thread runtime stats test. |
||||||
|
*/ |
||||||
|
|
||||||
|
#if !defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_SPARC) && !defined(CONFIG_MIPS) |
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_system) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
struct k_cycle_stats kernel_raw[CONFIG_MP_MAX_NUM_CPUS]; |
||||||
|
struct k_cycle_stats cpu_raw; |
||||||
|
struct k_thread_runtime_stats kernel_query; |
||||||
|
struct k_thread_runtime_stats cpu_query; |
||||||
|
struct k_thread_runtime_stats sum_query; |
||||||
|
unsigned int i; |
||||||
|
|
||||||
|
#if CONFIG_MP_MAX_NUM_CPUS > 1 |
||||||
|
|
||||||
|
/* Create 1 busy thread for each core except the current */ |
||||||
|
|
||||||
|
int prio; |
||||||
|
|
||||||
|
prio = k_thread_priority_get(k_current_get()); |
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS - 1; i++) { |
||||||
|
k_thread_create(&busy_thread[i], busy_thread_stack[i], |
||||||
|
K_THREAD_STACK_SIZEOF(busy_thread_stack[i]), |
||||||
|
busy_thread_entry, NULL, NULL, NULL, |
||||||
|
prio + 10, 0, K_NO_WAIT); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
status = k_obj_core_stats_raw(K_OBJ_CORE(&_kernel), kernel_raw, |
||||||
|
sizeof(kernel_raw)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Not much can be predicted for the raw stats aside from the |
||||||
|
* the contents of the CPU sampling to be at least as large as |
||||||
|
* kernel sampling. The same goes for the query stats. |
||||||
|
*/ |
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { |
||||||
|
status = k_obj_core_stats_raw(K_OBJ_CORE(&_kernel.cpus[i]), |
||||||
|
&cpu_raw, sizeof(cpu_raw)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d on CPU %u\n", |
||||||
|
status, i); |
||||||
|
|
||||||
|
zassert_true(cpu_raw.total >= kernel_raw[i].total); |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS |
||||||
|
zassert_true(cpu_raw.current >= kernel_raw[i].current); |
||||||
|
zassert_true(cpu_raw.longest >= kernel_raw[i].longest); |
||||||
|
zassert_true(cpu_raw.num_windows >= kernel_raw[i].num_windows); |
||||||
|
#endif |
||||||
|
zassert_true(cpu_raw.track_usage == kernel_raw[i].track_usage); |
||||||
|
} |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(&_kernel), &kernel_query, |
||||||
|
sizeof(kernel_query)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
sum_query = (struct k_thread_runtime_stats){}; |
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { |
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(&_kernel.cpus[i]), |
||||||
|
&cpu_query, sizeof(cpu_query)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d on CPU %u\n", |
||||||
|
status, i); |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE |
||||||
|
sum_query.execution_cycles += cpu_query.execution_cycles; |
||||||
|
sum_query.total_cycles += cpu_query.total_cycles; |
||||||
|
#endif |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS |
||||||
|
sum_query.current_cycles += cpu_query.current_cycles; |
||||||
|
sum_query.peak_cycles += cpu_query.peak_cycles; |
||||||
|
sum_query.average_cycles += cpu_query.average_cycles; |
||||||
|
#endif |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ALL |
||||||
|
sum_query.idle_cycles += cpu_query.idle_cycles; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE |
||||||
|
zassert_true(sum_query.execution_cycles >= kernel_query.execution_cycles); |
||||||
|
zassert_true(sum_query.total_cycles >= kernel_query.total_cycles); |
||||||
|
#endif |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS |
||||||
|
zassert_true(sum_query.current_cycles >= kernel_query.current_cycles); |
||||||
|
zassert_true(sum_query.peak_cycles >= kernel_query.peak_cycles); |
||||||
|
zassert_true(sum_query.average_cycles >= kernel_query.average_cycles); |
||||||
|
#endif |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ALL |
||||||
|
zassert_true(sum_query.idle_cycles >= kernel_query.idle_cycles); |
||||||
|
#endif |
||||||
|
} |
||||||
|
#endif /* !CONFIG_ARCH_POSIX && !CONFIG_SPARC && !CONFIG_MIPS */ |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_cpu_reset) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { |
||||||
|
status = k_obj_core_stats_reset(K_OBJ_CORE(&_kernel.cpus[i])); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Expected %d, got %d on CPU%d\n", |
||||||
|
-ENOTSUP, status, i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_cpu_disable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { |
||||||
|
status = k_obj_core_stats_disable(K_OBJ_CORE(&_kernel.cpus[i])); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Expected %d, got %d on CPU%d\n", |
||||||
|
-ENOTSUP, status, i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_cpu_enable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
for (unsigned int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) { |
||||||
|
status = k_obj_core_stats_enable(K_OBJ_CORE(&_kernel.cpus[i])); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Expected %d, got %d on CPU%d\n", |
||||||
|
-ENOTSUP, status, i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_kernel_reset) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_reset(K_OBJ_CORE(&_kernel)); |
||||||
|
zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", |
||||||
|
-ENOTSUP, status); |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_kernel_disable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_disable(K_OBJ_CORE(&_kernel)); |
||||||
|
zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", |
||||||
|
-ENOTSUP, status); |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_system, test_obj_core_stats_kernel_enable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_enable(K_OBJ_CORE(&_kernel)); |
||||||
|
zassert_equal(status, -ENOTSUP, "Expected %d, got %d\n", |
||||||
|
-ENOTSUP, status); |
||||||
|
} |
||||||
|
|
||||||
|
/***************** THREADS ******************/ |
||||||
|
|
||||||
|
#if !defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_SPARC) && !defined(CONFIG_MIPS) |
||||||
|
/*
|
||||||
|
* As the k_obj_core_stats_xxx() APIs are essentially wrappers to the |
||||||
|
* thread runtime stats APIs, limit this test to the same architectures as |
||||||
|
* that thread runtime stats test. |
||||||
|
*/ |
||||||
|
void test_thread_entry(void *p1, void *p2, void *p3) |
||||||
|
{ |
||||||
|
while (1) { |
||||||
|
k_busy_wait(10000); |
||||||
|
|
||||||
|
k_sem_give(&wake_main_thread); |
||||||
|
k_sem_take(&wake_test_thread, K_FOREVER); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_thread, test_obj_core_stats_thread_test) |
||||||
|
{ |
||||||
|
struct k_cycle_stats raw1; |
||||||
|
struct k_cycle_stats raw2; |
||||||
|
struct k_thread_runtime_stats query1; |
||||||
|
struct k_thread_runtime_stats query2; |
||||||
|
struct k_thread_runtime_stats query3; |
||||||
|
int status; |
||||||
|
|
||||||
|
k_sem_take(&wake_main_thread, K_FOREVER); |
||||||
|
k_busy_wait(10000); |
||||||
|
|
||||||
|
/* test_thread should now be blocked on wake_test_thread */ |
||||||
|
|
||||||
|
status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), &raw1, |
||||||
|
sizeof(raw1)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d", status); |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), &query1, |
||||||
|
sizeof(query1)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d", status); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Busy wait for 10 msec. As test_thread should still be blocked, |
||||||
|
* its stats data should not change. |
||||||
|
*/ |
||||||
|
|
||||||
|
k_busy_wait(10000); |
||||||
|
|
||||||
|
status = k_obj_core_stats_raw(K_OBJ_CORE(test_thread), &raw2, |
||||||
|
sizeof(raw2)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d", status); |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), &query2, |
||||||
|
sizeof(query2)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d", status); |
||||||
|
|
||||||
|
zassert_mem_equal(&raw1, &raw2, sizeof(raw1), |
||||||
|
"Thread raw stats changed while blocked\n"); |
||||||
|
zassert_mem_equal(&query1, &query2, sizeof(query1), |
||||||
|
"Thread query stats changed while blocked\n"); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Let test_thread execute for a short bit and then re-sample the |
||||||
|
* stats. As the k_obj_core_stats_query() backend is identical to |
||||||
|
* that of k_thread_runtime_stats_get(), their queries should be |
||||||
|
* identical (and different from the previous sample). |
||||||
|
*/ |
||||||
|
|
||||||
|
k_sem_give(&wake_test_thread); |
||||||
|
k_sem_take(&wake_main_thread, K_FOREVER); |
||||||
|
k_busy_wait(10000); |
||||||
|
|
||||||
|
/* test_thread should now be blocked. */ |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), &query2, |
||||||
|
sizeof(query3)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
status = k_thread_runtime_stats_get(test_thread, &query3); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
zassert_mem_equal(&query2, &query3, sizeof(query2), |
||||||
|
"Queries not equal!\n"); |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE |
||||||
|
zassert_true(query2.execution_cycles > query1.execution_cycles, |
||||||
|
"Execution cycles did not increase\n"); |
||||||
|
zassert_true(query2.total_cycles > query1.total_cycles, |
||||||
|
"Total cycles did not increase\n"); |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS |
||||||
|
|
||||||
|
/*
|
||||||
|
* [current_cycles], [peak_cycles] and [average_cycles] can not be |
||||||
|
* predicted by this test. |
||||||
|
*/ |
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ALL |
||||||
|
zassert_equal(query2.idle_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query2.idle_cycles); |
||||||
|
#endif |
||||||
|
|
||||||
|
/* Reset the stats */ |
||||||
|
|
||||||
|
status = k_obj_core_stats_reset(K_OBJ_CORE(test_thread)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(test_thread), |
||||||
|
&query3, sizeof(query3)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE |
||||||
|
zassert_equal(query3.execution_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query3.execution_cycles); |
||||||
|
zassert_equal(query3.total_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query3.total_cycles); |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS |
||||||
|
zassert_equal(query3.current_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query3.current_cycles); |
||||||
|
zassert_equal(query3.peak_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query3.peak_cycles); |
||||||
|
zassert_equal(query3.average_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query3.average_cycles); |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ALL |
||||||
|
zassert_equal(query3.idle_cycles, 0, |
||||||
|
"Expected 0, got %llu\n", query3.idle_cycles); |
||||||
|
#endif |
||||||
|
|
||||||
|
/* Disable the stats (re-using query2 and query3) */ |
||||||
|
|
||||||
|
status = k_obj_core_stats_disable(K_OBJ_CORE(test_thread)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %llu\n", status); |
||||||
|
|
||||||
|
k_sem_give(&wake_test_thread); |
||||||
|
k_sem_take(&wake_main_thread, K_FOREVER); |
||||||
|
k_busy_wait(10000); |
||||||
|
|
||||||
|
k_obj_core_stats_query(K_OBJ_CORE(test_thread), |
||||||
|
&query2, sizeof(query2)); |
||||||
|
|
||||||
|
zassert_mem_equal(&query2, &query3, sizeof(query2), |
||||||
|
"Stats changed while disabled!\n"); |
||||||
|
|
||||||
|
/* Enable the stats */ |
||||||
|
|
||||||
|
status = k_obj_core_stats_enable(K_OBJ_CORE(test_thread)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %llu\n", status); |
||||||
|
|
||||||
|
k_sem_give(&wake_test_thread); |
||||||
|
k_sem_take(&wake_main_thread, K_FOREVER); |
||||||
|
k_busy_wait(10000); |
||||||
|
|
||||||
|
k_obj_core_stats_query(K_OBJ_CORE(test_thread), |
||||||
|
&query3, sizeof(query3)); |
||||||
|
|
||||||
|
/* We can not predict the stats, but they should be non-zero. */ |
||||||
|
|
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE |
||||||
|
zassert_true(query3.execution_cycles > 0); |
||||||
|
zassert_true(query3.total_cycles > 0); |
||||||
|
#endif |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE |
||||||
|
zassert_true(query3.current_cycles > 0); |
||||||
|
zassert_true(query3.peak_cycles > 0); |
||||||
|
zassert_true(query3.average_cycles > 0); |
||||||
|
#endif |
||||||
|
#ifdef CONFIG_SCHED_THREAD_USAGE_ALL |
||||||
|
zassert_true(query3.idle_cycles == 0); |
||||||
|
#endif |
||||||
|
|
||||||
|
k_thread_abort(test_thread); |
||||||
|
} |
||||||
|
#endif /* !CONFIG_ARCH_POSIX && !CONFIG_SPARC && !CONFIG_MIPS */ |
||||||
|
|
||||||
|
/***************** SYSTEM MEMORY BLOCKS *********************/ |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_mem_block, test_sys_mem_block_enable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_enable(K_OBJ_CORE(&mem_block)); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Not supposed to be supported. Got %d, not %d\n", |
||||||
|
status, -ENOTSUP); |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_mem_block, test_sys_mem_block_disable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_disable(K_OBJ_CORE(&mem_block)); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Not supposed to be supported. Got %d, not %d\n", |
||||||
|
status, -ENOTSUP); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_mem_block_raw(const char *str, |
||||||
|
struct sys_mem_blocks_info *expected) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
struct sys_mem_blocks_info raw; |
||||||
|
|
||||||
|
status = k_obj_core_stats_raw(K_OBJ_CORE(&mem_block), &raw, |
||||||
|
sizeof(raw)); |
||||||
|
zassert_equal(status, 0, |
||||||
|
"%s: Failed to get raw stats (%d)\n", str, status); |
||||||
|
|
||||||
|
zassert_equal(raw.num_blocks, expected->num_blocks, |
||||||
|
"%s: Expected %u blocks, got %u\n", |
||||||
|
str, expected->num_blocks, raw.num_blocks); |
||||||
|
zassert_equal(raw.blk_sz_shift, expected->blk_sz_shift, |
||||||
|
"%s: Expected blk_sz_shift=%u, got %u\n", |
||||||
|
str, expected->blk_sz_shift, raw.blk_sz_shift); |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
zassert_equal(raw.used_blocks, expected->used_blocks, |
||||||
|
"%s: Expected %u used, got %d\n", |
||||||
|
str, expected->used_blocks, raw.used_blocks); |
||||||
|
zassert_equal(raw.max_used_blocks, expected->max_used_blocks, |
||||||
|
"%s: Expected max %u used, got %d\n", |
||||||
|
str, expected->max_used_blocks, raw.max_used_blocks); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
static void test_mem_block_query(const char *str, |
||||||
|
struct sys_memory_stats *expected) |
||||||
|
{ |
||||||
|
struct sys_memory_stats query; |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(&mem_block), &query, |
||||||
|
sizeof(query)); |
||||||
|
zassert_equal(status, 0, |
||||||
|
"%s: Failed to get query stats (%d)\n", str, status); |
||||||
|
|
||||||
|
zassert_equal(query.free_bytes, expected->free_bytes, |
||||||
|
"%s: Expected %u free bytes, got %u\n", |
||||||
|
str, expected->free_bytes, query.free_bytes); |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
zassert_equal(query.allocated_bytes, expected->allocated_bytes, |
||||||
|
"%s: Expected %u allocated bytes, got %u\n", |
||||||
|
str, expected->allocated_bytes, query.allocated_bytes); |
||||||
|
zassert_equal(query.max_allocated_bytes, expected->max_allocated_bytes, |
||||||
|
"%s: Expected %u max_allocated bytes, got %d\n", |
||||||
|
str, expected->max_allocated_bytes, |
||||||
|
query.max_allocated_bytes); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_mem_block, test_obj_core_stats_mem_block) |
||||||
|
{ |
||||||
|
struct sys_mem_blocks_info raw = { |
||||||
|
.num_blocks = 4, .blk_sz_shift = 5, |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
.used_blocks = 0, .max_used_blocks = 0 |
||||||
|
#endif |
||||||
|
}; |
||||||
|
struct sys_memory_stats query = { |
||||||
|
.free_bytes = 128, |
||||||
|
.allocated_bytes = 0, |
||||||
|
.max_allocated_bytes = 0 |
||||||
|
}; |
||||||
|
void *mem1; |
||||||
|
void *mem2; |
||||||
|
int status; |
||||||
|
|
||||||
|
/*
|
||||||
|
* As the ordering of the "raw", "query" and "reset" tests matter, |
||||||
|
* they have been grouped together here. As they are for the most |
||||||
|
* wrappers for the runtime stats routines, minimal testing is |
||||||
|
* being done. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* Initial checks */ |
||||||
|
|
||||||
|
test_mem_block_raw("Initial", &raw); |
||||||
|
test_mem_block_query("Initial", &query); |
||||||
|
|
||||||
|
/* Allocate 1st block */ |
||||||
|
|
||||||
|
status = sys_mem_blocks_alloc(&mem_block, 1, &mem1); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
query.free_bytes -= 32; |
||||||
|
query.allocated_bytes += 32; |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
raw.used_blocks++; |
||||||
|
raw.max_used_blocks++; |
||||||
|
query.max_allocated_bytes += 32; |
||||||
|
#endif |
||||||
|
test_mem_block_raw("1st Alloc", &raw); |
||||||
|
test_mem_block_query("1st Alloc", &query); |
||||||
|
|
||||||
|
/* Allocate 2nd block */ |
||||||
|
|
||||||
|
status = sys_mem_blocks_alloc(&mem_block, 1, &mem2); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
query.free_bytes -= 32; |
||||||
|
query.allocated_bytes += 32; |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
raw.used_blocks++; |
||||||
|
raw.max_used_blocks++; |
||||||
|
query.max_allocated_bytes += 32; |
||||||
|
#endif |
||||||
|
test_mem_block_raw("2nd Alloc", &raw); |
||||||
|
test_mem_block_query("2nd Alloc", &query); |
||||||
|
|
||||||
|
/* Free 1st block */ |
||||||
|
|
||||||
|
sys_mem_blocks_free(&mem_block, 1, &mem1); |
||||||
|
|
||||||
|
query.free_bytes += 32; |
||||||
|
query.allocated_bytes -= 32; |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
raw.used_blocks--; |
||||||
|
#endif |
||||||
|
test_mem_block_raw("Free 1st", &raw); |
||||||
|
test_mem_block_query("Free 1st", &query); |
||||||
|
|
||||||
|
/* Reset the mem block stats */ |
||||||
|
|
||||||
|
status = k_obj_core_stats_reset(K_OBJ_CORE(&mem_block)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS |
||||||
|
raw.max_used_blocks = raw.used_blocks; |
||||||
|
query.max_allocated_bytes = query.allocated_bytes; |
||||||
|
#endif |
||||||
|
test_mem_block_raw("Reset", &raw); |
||||||
|
test_mem_block_query("Reset", &query); |
||||||
|
|
||||||
|
/* Cleanup - Free 2nd block */ |
||||||
|
sys_mem_blocks_free(&mem_block, 1, &mem2); |
||||||
|
} |
||||||
|
|
||||||
|
/***************** MEMORY SLABS *********************/ |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_mem_slab, test_mem_slab_enable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_disable(K_OBJ_CORE(&mem_slab)); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Not supposed to be supported. Got %d, not %d\n", |
||||||
|
status, -ENOTSUP); |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_mem_slab, test_mem_slab_disable) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_disable(K_OBJ_CORE(&mem_slab)); |
||||||
|
zassert_equal(status, -ENOTSUP, |
||||||
|
"Not supposed to be supported. Got %d, not %d\n", |
||||||
|
status, -ENOTSUP); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_mem_slab_raw(const char *str, struct k_mem_slab_info *expected) |
||||||
|
{ |
||||||
|
int status; |
||||||
|
struct k_mem_slab_info raw; |
||||||
|
|
||||||
|
status = k_obj_core_stats_raw(K_OBJ_CORE(&mem_slab), &raw, |
||||||
|
sizeof(raw)); |
||||||
|
zassert_equal(status, 0, |
||||||
|
"%s: Failed to get raw stats (%d)\n", str, status); |
||||||
|
|
||||||
|
zassert_equal(raw.num_blocks, expected->num_blocks, |
||||||
|
"%s: Expected %u blocks, got %u\n", |
||||||
|
str, expected->num_blocks, raw.num_blocks); |
||||||
|
zassert_equal(raw.block_size, expected->block_size, |
||||||
|
"%s: Expected block size=%u blocks, got %u\n", |
||||||
|
str, expected->block_size, raw.block_size); |
||||||
|
zassert_equal(raw.num_used, expected->num_used, |
||||||
|
"%s: Expected %u used, got %d\n", |
||||||
|
str, expected->num_used, raw.num_used); |
||||||
|
#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION |
||||||
|
zassert_equal(raw.max_used, expected->max_used, |
||||||
|
"%s: Expected max %u used, got %d\n", |
||||||
|
str, expected->max_used, raw.max_used); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
static void test_mem_slab_query(const char *str, |
||||||
|
struct sys_memory_stats *expected) |
||||||
|
{ |
||||||
|
struct sys_memory_stats query; |
||||||
|
int status; |
||||||
|
|
||||||
|
status = k_obj_core_stats_query(K_OBJ_CORE(&mem_slab), &query, |
||||||
|
sizeof(query)); |
||||||
|
zassert_equal(status, 0, |
||||||
|
"%s: Failed to get query stats (%d)\n", str, status); |
||||||
|
|
||||||
|
zassert_equal(query.free_bytes, expected->free_bytes, |
||||||
|
"%s: Expected %u free bytes, got %u\n", |
||||||
|
str, expected->free_bytes, query.free_bytes); |
||||||
|
zassert_equal(query.allocated_bytes, expected->allocated_bytes, |
||||||
|
"%s: Expected %u allocated bytes, got %u\n", |
||||||
|
str, expected->allocated_bytes, query.allocated_bytes); |
||||||
|
zassert_equal(query.max_allocated_bytes, expected->max_allocated_bytes, |
||||||
|
"%s: Expected %u max_allocated bytes, got %d\n", |
||||||
|
str, expected->max_allocated_bytes, |
||||||
|
query.max_allocated_bytes); |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST(obj_core_stats_mem_slab, test_obj_core_stats_mem_slab) |
||||||
|
{ |
||||||
|
struct k_mem_slab_info raw = { |
||||||
|
.num_blocks = 4, .block_size = 32, .num_used = 0, |
||||||
|
#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION |
||||||
|
.max_used = 0 |
||||||
|
#endif |
||||||
|
}; |
||||||
|
struct sys_memory_stats query = { |
||||||
|
.free_bytes = 128, |
||||||
|
.allocated_bytes = 0, |
||||||
|
.max_allocated_bytes = 0 |
||||||
|
}; |
||||||
|
void *mem1; |
||||||
|
void *mem2; |
||||||
|
int status; |
||||||
|
|
||||||
|
/*
|
||||||
|
* As the ordering of the "raw", "query" and "reset" tests matter, |
||||||
|
* they have been grouped together here. As they are for the most |
||||||
|
* wrappers for the runtime stats routines, minimal testing is |
||||||
|
* being done. |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
/* Initial checks */ |
||||||
|
|
||||||
|
test_mem_slab_raw("Initial", &raw); |
||||||
|
test_mem_slab_query("Initial", &query); |
||||||
|
|
||||||
|
/* Allocate 1st block */ |
||||||
|
|
||||||
|
status = k_mem_slab_alloc(&mem_slab, &mem1, K_FOREVER); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
raw.num_used++; |
||||||
|
query.free_bytes -= 32; |
||||||
|
query.allocated_bytes += 32; |
||||||
|
#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION |
||||||
|
raw.max_used++; |
||||||
|
query.max_allocated_bytes += 32; |
||||||
|
#endif |
||||||
|
test_mem_slab_raw("1st Alloc", &raw); |
||||||
|
test_mem_slab_query("1st Alloc", &query); |
||||||
|
|
||||||
|
/* Allocate 2nd block */ |
||||||
|
|
||||||
|
status = k_mem_slab_alloc(&mem_slab, &mem2, K_FOREVER); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
|
||||||
|
raw.num_used++; |
||||||
|
query.free_bytes -= 32; |
||||||
|
query.allocated_bytes += 32; |
||||||
|
#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION |
||||||
|
raw.max_used++; |
||||||
|
query.max_allocated_bytes += 32; |
||||||
|
#endif |
||||||
|
test_mem_slab_raw("2nd Alloc", &raw); |
||||||
|
test_mem_slab_query("2nd Alloc", &query); |
||||||
|
|
||||||
|
/* Free 1st block */ |
||||||
|
k_mem_slab_free(&mem_slab, mem1); |
||||||
|
|
||||||
|
raw.num_used--; |
||||||
|
query.free_bytes += 32; |
||||||
|
query.allocated_bytes -= 32; |
||||||
|
test_mem_slab_raw("Free 1st", &raw); |
||||||
|
test_mem_slab_query("Free 1st", &query); |
||||||
|
|
||||||
|
/* Reset the mem slab stats */ |
||||||
|
status = k_obj_core_stats_reset(K_OBJ_CORE(&mem_slab)); |
||||||
|
zassert_equal(status, 0, "Expected 0, got %d\n", status); |
||||||
|
#ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION |
||||||
|
raw.max_used = raw.num_used; |
||||||
|
query.max_allocated_bytes = query.allocated_bytes; |
||||||
|
#endif |
||||||
|
test_mem_slab_raw("Reset", &raw); |
||||||
|
test_mem_slab_query("Reset", &query); |
||||||
|
|
||||||
|
/* Cleanup - Free 2nd block */ |
||||||
|
k_mem_slab_free(&mem_slab, mem2); |
||||||
|
} |
||||||
|
|
||||||
|
ZTEST_SUITE(obj_core_stats_system, NULL, NULL, |
||||||
|
ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); |
||||||
|
|
||||||
|
ZTEST_SUITE(obj_core_stats_thread, NULL, NULL, |
||||||
|
ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); |
||||||
|
|
||||||
|
ZTEST_SUITE(obj_core_stats_mem_block, NULL, NULL, |
||||||
|
ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); |
||||||
|
|
||||||
|
ZTEST_SUITE(obj_core_stats_mem_slab, NULL, NULL, |
||||||
|
ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL); |
Loading…
Reference in new issue