tests: latency_measure: Add FIFO support
Adds FIFO support to the latency_measure benchmark. This covers both k_fifo_put() and k_fifo_get() with and without context switches as well as variations for userspace support. Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
This commit is contained in:
parent
c2d2cf6d2b
commit
7103b0cdeb
2 changed files with 346 additions and 0 deletions
330
tests/benchmarks/latency_measure/src/fifo.c
Normal file
330
tests/benchmarks/latency_measure/src/fifo.c
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @file measure time for various FIFO operations
|
||||||
|
*
|
||||||
|
* This file contains the tests that measures the times for the following
|
||||||
|
* FIFO operations from both kernel threads and user threads:
|
||||||
|
* 1. Immediately adding a data item to a FIFO
|
||||||
|
* 2. Immediately removing a data item from a FIFO
|
||||||
|
* 3. Immediately adding a data item to a FIFO with allocation
|
||||||
|
* 4. Immediately removing a data item from a FIFO with allocation
|
||||||
|
* 5. Blocking on removing a data item from a FIFO
|
||||||
|
* 6. Waking (and context switching to) a thread blocked on a FIFO via
|
||||||
|
* k_fifo_put().
|
||||||
|
* 7. Waking (and context switching to) a thread blocked on a FIFO via
|
||||||
|
* k_fifo_alloc_put().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/timing/timing.h>
|
||||||
|
#include "utils.h"
|
||||||
|
#include "timing_sc.h"
|
||||||
|
|
||||||
|
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
|
||||||
|
|
||||||
|
static K_FIFO_DEFINE(fifo);
|
||||||
|
|
||||||
|
BENCH_BMEM uintptr_t fifo_data[5];
|
||||||
|
|
||||||
|
static void fifo_put_get_thread_entry(void *p1, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
|
||||||
|
uint32_t options = (uint32_t)(uintptr_t)p2;
|
||||||
|
timing_t start;
|
||||||
|
timing_t mid;
|
||||||
|
timing_t finish;
|
||||||
|
uint64_t put_sum = 0ULL;
|
||||||
|
uint64_t get_sum = 0ULL;
|
||||||
|
uintptr_t *data;
|
||||||
|
|
||||||
|
if ((options & K_USER) == 0) {
|
||||||
|
for (uint32_t i = 0; i < num_iterations; i++) {
|
||||||
|
start = timing_timestamp_get();
|
||||||
|
|
||||||
|
k_fifo_put(&fifo, fifo_data);
|
||||||
|
|
||||||
|
mid = timing_timestamp_get();
|
||||||
|
|
||||||
|
data = k_fifo_get(&fifo, K_NO_WAIT);
|
||||||
|
|
||||||
|
finish = timing_timestamp_get();
|
||||||
|
|
||||||
|
put_sum += timing_cycles_get(&start, &mid);
|
||||||
|
get_sum += timing_cycles_get(&mid, &finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp.cycles = put_sum;
|
||||||
|
k_sem_take(&pause_sem, K_FOREVER);
|
||||||
|
|
||||||
|
timestamp.cycles = get_sum;
|
||||||
|
k_sem_take(&pause_sem, K_FOREVER);
|
||||||
|
|
||||||
|
put_sum = 0ULL;
|
||||||
|
get_sum = 0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < num_iterations; i++) {
|
||||||
|
start = timing_timestamp_get();
|
||||||
|
|
||||||
|
k_fifo_alloc_put(&fifo, fifo_data);
|
||||||
|
|
||||||
|
mid = timing_timestamp_get();
|
||||||
|
|
||||||
|
data = k_fifo_get(&fifo, K_NO_WAIT);
|
||||||
|
|
||||||
|
finish = timing_timestamp_get();
|
||||||
|
|
||||||
|
put_sum += timing_cycles_get(&start, &mid);
|
||||||
|
get_sum += timing_cycles_get(&mid, &finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp.cycles = put_sum;
|
||||||
|
k_sem_take(&pause_sem, K_FOREVER);
|
||||||
|
|
||||||
|
timestamp.cycles = get_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fifo_ops(uint32_t num_iterations, uint32_t options)
|
||||||
|
{
|
||||||
|
int priority;
|
||||||
|
uint64_t cycles;
|
||||||
|
char description[80];
|
||||||
|
|
||||||
|
priority = k_thread_priority_get(k_current_get());
|
||||||
|
|
||||||
|
timing_start();
|
||||||
|
|
||||||
|
k_thread_create(&start_thread, start_stack,
|
||||||
|
K_THREAD_STACK_SIZEOF(start_stack),
|
||||||
|
fifo_put_get_thread_entry,
|
||||||
|
(void *)(uintptr_t)num_iterations,
|
||||||
|
(void *)(uintptr_t)options, NULL,
|
||||||
|
priority - 1, options, K_FOREVER);
|
||||||
|
|
||||||
|
k_thread_access_grant(&start_thread, &pause_sem, &fifo);
|
||||||
|
|
||||||
|
k_thread_start(&start_thread);
|
||||||
|
|
||||||
|
if ((options & K_USER) == 0) {
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO put.immediate.%s",
|
||||||
|
options & K_USER ? "user" : "kernel");
|
||||||
|
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
cycles -= timestamp_overhead_adjustment(options, options);
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
k_sem_give(&pause_sem);
|
||||||
|
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO get.immediate.%s",
|
||||||
|
options & K_USER ? "user" : "kernel");
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
cycles -= timestamp_overhead_adjustment(options, options);
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
k_sem_give(&pause_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO put.alloc.immediate.%s",
|
||||||
|
options & K_USER ? "user" : "kernel");
|
||||||
|
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
k_sem_give(&pause_sem);
|
||||||
|
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO get.free.immediate.%s",
|
||||||
|
options & K_USER ? "user" : "kernel");
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
|
||||||
|
k_thread_join(&start_thread, K_FOREVER);
|
||||||
|
|
||||||
|
timing_stop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alt_thread_entry(void *p1, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
|
||||||
|
uint32_t options = (uint32_t)(uintptr_t)p2;
|
||||||
|
timing_t start;
|
||||||
|
timing_t mid;
|
||||||
|
timing_t finish;
|
||||||
|
uint64_t sum[4] = {0ULL, 0ULL, 0ULL, 0ULL};
|
||||||
|
uintptr_t *data;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if ((options & K_USER) == 0) {
|
||||||
|
|
||||||
|
/* Used with k_fifo_put() */
|
||||||
|
|
||||||
|
for (i = 0; i < num_iterations; i++) {
|
||||||
|
|
||||||
|
/* 1. Block waiting for data on FIFO */
|
||||||
|
|
||||||
|
start = timing_timestamp_get();
|
||||||
|
|
||||||
|
data = k_fifo_get(&fifo, K_FOREVER);
|
||||||
|
|
||||||
|
/* 3. Data obtained. */
|
||||||
|
|
||||||
|
finish = timing_timestamp_get();
|
||||||
|
|
||||||
|
mid = timestamp.sample;
|
||||||
|
|
||||||
|
sum[0] += timing_cycles_get(&start, &mid);
|
||||||
|
sum[1] += timing_cycles_get(&mid, &finish);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used with k_fifo_alloc_put() */
|
||||||
|
|
||||||
|
for (i = 0; i < num_iterations; i++) {
|
||||||
|
|
||||||
|
/* 4. Block waiting for data on FIFO */
|
||||||
|
|
||||||
|
start = timing_timestamp_get();
|
||||||
|
|
||||||
|
data = k_fifo_get(&fifo, K_FOREVER);
|
||||||
|
|
||||||
|
/* 6. Data obtained */
|
||||||
|
|
||||||
|
finish = timing_timestamp_get();
|
||||||
|
|
||||||
|
mid = timestamp.sample;
|
||||||
|
|
||||||
|
sum[2] += timing_cycles_get(&start, &mid);
|
||||||
|
sum[3] += timing_cycles_get(&mid, &finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((options & K_USER) == 0) {
|
||||||
|
timestamp.cycles = sum[0];
|
||||||
|
k_sem_take(&pause_sem, K_FOREVER);
|
||||||
|
timestamp.cycles = sum[1];
|
||||||
|
k_sem_take(&pause_sem, K_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp.cycles = sum[2];
|
||||||
|
k_sem_take(&pause_sem, K_FOREVER);
|
||||||
|
timestamp.cycles = sum[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start_thread_entry(void *p1, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
|
||||||
|
uint32_t options = (uint32_t)(uintptr_t)p2;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
k_thread_start(&alt_thread);
|
||||||
|
|
||||||
|
if ((options & K_USER) == 0) {
|
||||||
|
for (i = 0; i < num_iterations; i++) {
|
||||||
|
|
||||||
|
/* 2. Add data thereby waking alt thread */
|
||||||
|
|
||||||
|
timestamp.sample = timing_timestamp_get();
|
||||||
|
|
||||||
|
k_fifo_put(&fifo, fifo_data);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_iterations; i++) {
|
||||||
|
|
||||||
|
/* 5. Add data thereby waking alt thread */
|
||||||
|
|
||||||
|
timestamp.sample = timing_timestamp_get();
|
||||||
|
|
||||||
|
k_fifo_alloc_put(&fifo, fifo_data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
k_thread_join(&alt_thread, K_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
|
||||||
|
uint32_t alt_options)
|
||||||
|
{
|
||||||
|
int priority;
|
||||||
|
uint64_t cycles;
|
||||||
|
char description[80];
|
||||||
|
|
||||||
|
priority = k_thread_priority_get(k_current_get());
|
||||||
|
|
||||||
|
timing_start();
|
||||||
|
|
||||||
|
k_thread_create(&start_thread, start_stack,
|
||||||
|
K_THREAD_STACK_SIZEOF(start_stack),
|
||||||
|
start_thread_entry,
|
||||||
|
(void *)(uintptr_t)num_iterations,
|
||||||
|
(void *)(uintptr_t)(start_options | alt_options), NULL,
|
||||||
|
priority - 1, start_options, K_FOREVER);
|
||||||
|
|
||||||
|
k_thread_create(&alt_thread, alt_stack,
|
||||||
|
K_THREAD_STACK_SIZEOF(alt_stack),
|
||||||
|
alt_thread_entry,
|
||||||
|
(void *)(uintptr_t)num_iterations,
|
||||||
|
(void *)(uintptr_t)(start_options | alt_options), NULL,
|
||||||
|
priority - 2, alt_options, K_FOREVER);
|
||||||
|
|
||||||
|
k_thread_access_grant(&start_thread, &alt_thread, &pause_sem, &fifo);
|
||||||
|
k_thread_access_grant(&alt_thread, &pause_sem, &fifo);
|
||||||
|
|
||||||
|
k_thread_start(&start_thread);
|
||||||
|
|
||||||
|
if (((start_options | alt_options) & K_USER) == 0) {
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO get.blocking.(%s -> %s)",
|
||||||
|
alt_options & K_USER ? "U" : "K",
|
||||||
|
start_options & K_USER ? "U" : "K");
|
||||||
|
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
k_sem_give(&pause_sem);
|
||||||
|
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO put.wake+ctx.(%s -> %s)",
|
||||||
|
start_options & K_USER ? "U" : "K",
|
||||||
|
alt_options & K_USER ? "U" : "K");
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
k_sem_give(&pause_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO get.free.blocking.(%s -> %s)",
|
||||||
|
alt_options & K_USER ? "U" : "K",
|
||||||
|
start_options & K_USER ? "U" : "K");
|
||||||
|
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
k_sem_give(&pause_sem);
|
||||||
|
|
||||||
|
snprintf(description, sizeof(description),
|
||||||
|
"FIFO put.alloc.wake+ctx.(%s -> %s)",
|
||||||
|
start_options & K_USER ? "U" : "K",
|
||||||
|
alt_options & K_USER ? "U" : "K");
|
||||||
|
cycles = timestamp.cycles;
|
||||||
|
PRINT_STATS_AVG(description, (uint32_t)cycles,
|
||||||
|
num_iterations, false, "");
|
||||||
|
|
||||||
|
k_thread_join(&start_thread, K_FOREVER);
|
||||||
|
|
||||||
|
timing_stop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -46,6 +46,9 @@ extern void sema_context_switch(uint32_t num_iterations,
|
||||||
uint32_t start_options, uint32_t alt_options);
|
uint32_t start_options, uint32_t alt_options);
|
||||||
extern int thread_ops(uint32_t num_iterations, uint32_t start_options,
|
extern int thread_ops(uint32_t num_iterations, uint32_t start_options,
|
||||||
uint32_t alt_options);
|
uint32_t alt_options);
|
||||||
|
extern int fifo_ops(uint32_t num_iterations, uint32_t options);
|
||||||
|
extern int fifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
|
||||||
|
uint32_t alt_options);
|
||||||
extern int lifo_ops(uint32_t num_iterations, uint32_t options);
|
extern int lifo_ops(uint32_t num_iterations, uint32_t options);
|
||||||
extern int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
|
extern int lifo_blocking_ops(uint32_t num_iterations, uint32_t start_options,
|
||||||
uint32_t alt_options);
|
uint32_t alt_options);
|
||||||
|
@ -92,6 +95,19 @@ static void test_thread(void *arg1, void *arg2, void *arg3)
|
||||||
thread_ops(NUM_ITERATIONS, K_USER, 0);
|
thread_ops(NUM_ITERATIONS, K_USER, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fifo_ops(NUM_ITERATIONS, 0);
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
fifo_ops(NUM_ITERATIONS, K_USER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fifo_blocking_ops(NUM_ITERATIONS, 0, 0);
|
||||||
|
#ifdef CONFIG_USERSPACE
|
||||||
|
fifo_blocking_ops(NUM_ITERATIONS, 0, K_USER);
|
||||||
|
fifo_blocking_ops(NUM_ITERATIONS, K_USER, 0);
|
||||||
|
fifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
lifo_ops(NUM_ITERATIONS, 0);
|
lifo_ops(NUM_ITERATIONS, 0);
|
||||||
#ifdef CONFIG_USERSPACE
|
#ifdef CONFIG_USERSPACE
|
||||||
lifo_ops(NUM_ITERATIONS, K_USER);
|
lifo_ops(NUM_ITERATIONS, K_USER);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue