tests: latency_measure: Add events

Adds events to the latency_measure benchmark.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
This commit is contained in:
Peter Mitsis 2024-01-04 11:25:03 -05:00 committed by Carles Cufí
commit a8914c56d2
5 changed files with 306 additions and 3 deletions

View file

@ -27,3 +27,6 @@ CONFIG_APPLICATION_DEFINED_SYSCALL=y
# Disable time slicing # Disable time slicing
CONFIG_TIMESLICING=n CONFIG_TIMESLICING=n
# Enable events
CONFIG_EVENTS=y

View file

@ -28,3 +28,6 @@ CONFIG_USERSPACE=y
# Disable time slicing # Disable time slicing
CONFIG_TIMESLICING=n CONFIG_TIMESLICING=n
# Enable events
CONFIG_EVENTS=y

View file

@ -0,0 +1,282 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* @file measure time for various event operations
*
* This file contains the tests that measure the times for manipulating
* event objects from both kernel and user threads:
* 1. Immediately posting and setting events
* 2. Immediately receiving any or all events.
* 3. Blocking to receive either any or all events.
* 4. Waking (and switching to) a thread waiting for any or all events.
*/
#include <zephyr/kernel.h>
#include <zephyr/timing/timing.h>
#include "utils.h"
#include "timing_sc.h"
#define BENCH_EVENT_SET 0x1234
#define ALL_EVENTS 0xFFFFFFFF
static K_EVENT_DEFINE(event_set);
static void event_ops_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 finish;
uint32_t i;
uint64_t cycles;
char description[80];
k_event_clear(&event_set, ALL_EVENTS);
start = timing_timestamp_get();
for (i = 0; i < num_iterations; i++) {
k_event_post(&event_set, BENCH_EVENT_SET);
}
finish = timing_timestamp_get();
snprintf(description, sizeof(description),
"EVENTS post.immediate.%s",
(options & K_USER) ? "user" : "kernel");
cycles = timing_cycles_get(&start, &finish);
PRINT_STATS_AVG(description, (uint32_t)cycles,
num_iterations, false, "");
start = timing_timestamp_get();
for (i = 0; i < num_iterations; i++) {
k_event_set(&event_set, BENCH_EVENT_SET);
}
finish = timing_timestamp_get();
snprintf(description, sizeof(description),
"EVENTS set.immediate.%s",
(options & K_USER) ? "user" : "kernel");
cycles = timing_cycles_get(&start, &finish);
PRINT_STATS_AVG(description, (uint32_t)cycles,
num_iterations, false, "");
start = timing_timestamp_get();
for (i = 0; i < num_iterations; i++) {
k_event_wait(&event_set, BENCH_EVENT_SET, false, K_FOREVER);
}
finish = timing_timestamp_get();
snprintf(description, sizeof(description),
"EVENTS wait.immediate.%s",
(options & K_USER) ? "user" : "kernel");
cycles = timing_cycles_get(&start, &finish);
PRINT_STATS_AVG(description, (uint32_t)cycles,
num_iterations, false, "");
start = timing_timestamp_get();
for (i = 0; i < num_iterations; i++) {
k_event_wait_all(&event_set, BENCH_EVENT_SET, false, K_FOREVER);
}
finish = timing_timestamp_get();
snprintf(description, sizeof(description),
"EVENTS wait_all.immediate.%s",
(options & K_USER) ? "user" : "kernel");
cycles = timing_cycles_get(&start, &finish);
PRINT_STATS_AVG(description, (uint32_t)cycles,
num_iterations, false, "");
}
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 alt_options = (uint32_t)(uintptr_t)p3;
uint32_t i;
uint64_t cycles;
char description[80];
k_thread_start(&alt_thread);
for (i = 0; i < num_iterations; i++) {
/* 2. Set the events to wake alt_thread */
timestamp.sample = timing_timestamp_get();
k_event_set(&event_set, BENCH_EVENT_SET);
}
snprintf(description, sizeof(description),
"EVENTS wait.blocking.(%c -> %c)",
(alt_options & K_USER) ? 'U' : 'K',
(options & K_USER) ? 'U' : 'K');
cycles = timestamp.cycles -
timestamp_overhead_adjustment(options, alt_options);
PRINT_STATS_AVG(description, (uint32_t)cycles,
num_iterations, false, "");
k_sem_give(&pause_sem);
snprintf(description, sizeof(description),
"EVENTS set.wake+ctx.(%c -> %c)",
(options & K_USER) ? 'U' : 'K',
(alt_options & K_USER) ? 'U' : 'K');
cycles = timestamp.cycles -
timestamp_overhead_adjustment(options, alt_options);
PRINT_STATS_AVG(description, (uint32_t)cycles,
num_iterations, false, "");
k_sem_give(&pause_sem);
for (i = 0; i < num_iterations; i++) {
/* 5. Post the events to wake alt_thread */
timestamp.sample = timing_timestamp_get();
k_event_post(&event_set, BENCH_EVENT_SET);
}
snprintf(description, sizeof(description),
"EVENTS wait_all.blocking.(%c -> %c)",
(alt_options & K_USER) ? 'U' : 'K',
(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),
"EVENTS post.wake+ctx.(%c -> %c)",
(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(&alt_thread, K_FOREVER);
}
static void alt_thread_entry(void *p1, void *p2, void *p3)
{
uint32_t num_iterations = (uint32_t)(uintptr_t)p1;
uint32_t i;
timing_t start;
timing_t mid;
timing_t finish;
uint64_t sum1 = 0ULL;
uint64_t sum2 = 0ULL;
for (i = 0; i < num_iterations; i++) {
/* 1. Wait for any of the events */
start = timing_timestamp_get();
k_event_wait(&event_set, BENCH_EVENT_SET, true, K_FOREVER);
/* 3. Record the final timestamp */
finish = timing_timestamp_get();
mid = timestamp.sample;
sum1 += timing_cycles_get(&start, &mid);
sum2 += timing_cycles_get(&mid, &finish);
}
/* Let start_thread print the results */
timestamp.cycles = sum1;
k_sem_take(&pause_sem, K_FOREVER);
timestamp.cycles = sum2;
k_sem_take(&pause_sem, K_FOREVER);
sum1 = 0ULL;
sum2 = 0ULL;
for (i = 0; i < num_iterations; i++) {
/* 4. Wait for all of the events */
start = timing_timestamp_get();
k_event_wait_all(&event_set, BENCH_EVENT_SET, true, K_FOREVER);
/* 6. Record the final timestamp */
finish = timing_timestamp_get();
mid = timestamp.sample;
sum1 += timing_cycles_get(&start, &mid);
sum2 += timing_cycles_get(&mid, &finish);
}
/* Let start_thread print the results */
timestamp.cycles = sum1;
k_sem_take(&pause_sem, K_FOREVER);
timestamp.cycles = sum2;
}
int event_ops(uint32_t num_iterations, uint32_t options)
{
int priority;
priority = k_thread_priority_get(k_current_get());
timing_start();
k_thread_create(&start_thread, start_stack,
K_THREAD_STACK_SIZEOF(start_stack),
event_ops_entry,
(void *)(uintptr_t)num_iterations,
(void *)(uintptr_t)options, NULL,
priority - 1, options, K_FOREVER);
k_thread_access_grant(&start_thread, &event_set);
k_thread_start(&start_thread);
k_thread_join(&start_thread, K_FOREVER);
timing_stop();
return 0;
}
int event_blocking_ops(uint32_t num_iterations, uint32_t start_options,
uint32_t alt_options)
{
int priority;
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,
(void *)(uintptr_t)alt_options,
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)alt_options, NULL,
priority - 2, alt_options, K_FOREVER);
k_thread_access_grant(&start_thread, &alt_thread, &event_set,
&pause_sem);
k_thread_access_grant(&alt_thread, &event_set, &pause_sem);
k_thread_start(&start_thread);
k_thread_join(&start_thread, K_FOREVER);
timing_stop();
return 0;
}

View file

@ -29,7 +29,7 @@ K_APPMEM_PARTITION_DEFINE(bench_mem_partition);
#endif #endif
K_THREAD_STACK_DEFINE(start_stack, START_STACK_SIZE); K_THREAD_STACK_DEFINE(start_stack, START_STACK_SIZE);
K_THREAD_STACK_DEFINE(alt_stack, START_STACK_SIZE); K_THREAD_STACK_DEFINE(alt_stack, ALT_STACK_SIZE);
K_SEM_DEFINE(pause_sem, 0, 1); K_SEM_DEFINE(pause_sem, 0, 1);
@ -52,6 +52,9 @@ extern int fifo_blocking_ops(uint32_t num_iterations, uint32_t start_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);
extern int event_ops(uint32_t num_iterations, uint32_t options);
extern int event_blocking_ops(uint32_t num_iterations, uint32_t start_options,
uint32_t alt_options);
extern void heap_malloc_free(void); extern void heap_malloc_free(void);
static void test_thread(void *arg1, void *arg2, void *arg3) static void test_thread(void *arg1, void *arg2, void *arg3)
@ -120,6 +123,18 @@ static void test_thread(void *arg1, void *arg2, void *arg3)
lifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER); lifo_blocking_ops(NUM_ITERATIONS, K_USER, K_USER);
#endif #endif
event_ops(NUM_ITERATIONS, 0);
#ifdef CONFIG_USERSPACE
event_ops(NUM_ITERATIONS, K_USER);
#endif
event_blocking_ops(NUM_ITERATIONS, 0, 0);
#ifdef CONFIG_USERSPACE
event_blocking_ops(NUM_ITERATIONS, 0, K_USER);
event_blocking_ops(NUM_ITERATIONS, K_USER, 0);
event_blocking_ops(NUM_ITERATIONS, K_USER, K_USER);
#endif
sema_test_signal(NUM_ITERATIONS, 0); sema_test_signal(NUM_ITERATIONS, 0);
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
sema_test_signal(NUM_ITERATIONS, K_USER); sema_test_signal(NUM_ITERATIONS, K_USER);

View file

@ -17,8 +17,8 @@
#include <zephyr/timestamp.h> #include <zephyr/timestamp.h>
#include <zephyr/app_memory/app_memdomain.h> #include <zephyr/app_memory/app_memdomain.h>
#define START_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) #define START_STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
#define ALT_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE) #define ALT_STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE)
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
#define BENCH_BMEM K_APP_BMEM(bench_mem_partition) #define BENCH_BMEM K_APP_BMEM(bench_mem_partition)