tests: latency_measure: Using timing functions
Use new timing API instead if local macros and functions. Add new becnhmarks for threads and semaphore and change the output to be parseable. Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
4b41cb14a8
commit
e90a4bb6b3
18 changed files with 426 additions and 571 deletions
41
tests/benchmarks/latency_measure/README.rst
Normal file
41
tests/benchmarks/latency_measure/README.rst
Normal file
|
@ -0,0 +1,41 @@
|
|||
Latency Measurements
|
||||
####################
|
||||
|
||||
This benchmark measures the latency of selected kernel capabilities, including:
|
||||
|
||||
|
||||
* Measure time to switch from ISR back to interrupted thread
|
||||
* Measure time from ISR to executing a different thread (rescheduled)
|
||||
* Measure average time to signal a semaphore then test that semaphore
|
||||
* Measure average time to signal a semaphore then test that semaphore with a context switch
|
||||
* Measure average time to lock a mutex then unlock that mutex
|
||||
* Measure average context switch time between threads using (k_yield)
|
||||
* Measure average context switch time between threads (coop)
|
||||
* Time it takes to suspend a thread
|
||||
* Time it takes to resume a suspended thread
|
||||
* Time it takes to create a new thread (without starting it)
|
||||
* Time it takes to start a newly created thread
|
||||
|
||||
|
||||
Sample output of the benchmark::
|
||||
|
||||
*** Booting Zephyr OS build zephyr-v2.3.0-2257-g0f420483db07 ***
|
||||
START - Time Measurement
|
||||
Timing results: Clock frequency: 120 MHz
|
||||
Average thread context switch using yield : 420 cycles , 3502 ns
|
||||
Average context switch time between threads (coop) : 429 cycles , 3583 ns
|
||||
Switch from ISR back to interrupted thread : 670 cycles , 5583 ns
|
||||
Time from ISR to executing a different thread : 570 cycles , 4750 ns
|
||||
Time to create a thread (without start) : 360 cycles , 3000 ns
|
||||
Time to start a thread : 545 cycles , 4541 ns
|
||||
Time to suspend a thread : 605 cycles , 5041 ns
|
||||
Time to resume a thread : 660 cycles , 5500 ns
|
||||
Time to abort a thread (not running) : 495 cycles , 4125 ns
|
||||
Average semaphore signal time : 195 cycles , 1626 ns
|
||||
Average semaphore test time : 62 cycles , 518 ns
|
||||
Semaphore take time (context switch) : 695 cycles , 5791 ns
|
||||
Semaphore give time (context switch) : 845 cycles , 7041 ns
|
||||
Average time to lock a mutex : 79 cycles , 659 ns
|
||||
Average time to unlock a mutex : 370 cycles , 3085 ns
|
||||
===================================================================
|
||||
PROJECT EXECUTION SUCCESSFUL
|
|
@ -1,41 +0,0 @@
|
|||
Title: Latency Measurement
|
||||
|
||||
Description:
|
||||
|
||||
This benchmark measures the latency of selected capabilities
|
||||
|
||||
IMPORTANT: The sample output below was generated using a simulation
|
||||
environment, and may not reflect the results that will be generated using other
|
||||
environments (simulated or otherwise).
|
||||
|
||||
|
||||
Sample Output:
|
||||
|
||||
***** BOOTING ZEPHYR OS v1.7.99 - BUILD: Mar 24 2017 22:46:05 *****
|
||||
|-----------------------------------------------------------------------------|
|
||||
| Latency Benchmark |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| tcs = timer clock cycles: 1 tcs is 10 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| 1 - Measure time to switch from ISR back to interrupted thread |
|
||||
| switching time is 12591 tcs = 125910 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| 2 - Measure time from ISR to executing a different thread (rescheduled) |
|
||||
| switch time is 8344 tcs = 83440 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| 3 - Measure average time to signal a sema then test that sema |
|
||||
| Average semaphore signal time 63 tcs = 638 nsec |
|
||||
| Average semaphore test time 49 tcs = 498 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| 4- Measure average time to lock a mutex then unlock that mutex |
|
||||
| Average time to lock the mutex 107 tcs = 1078 nsec |
|
||||
| Average time to unlock the mutex 92 tcs = 929 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| 5 - Measure average context switch time between threads using (k_yield) |
|
||||
| Average thread context switch using yield 110 tcs = 1107 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
| 6 - Measure average context switch time between threads (coop) |
|
||||
| Average context switch time is 88 tcs = 882 nsec |
|
||||
|-----------------------------------------------------------------------------|
|
||||
===================================================================
|
||||
PROJECT EXECUTION SUCCESSFUL
|
|
@ -1,6 +1,4 @@
|
|||
CONFIG_TEST=y
|
||||
# needed for printf output sent to console
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
|
||||
# eliminate timer interrupts during the benchmark
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1
|
||||
|
@ -21,3 +19,4 @@ CONFIG_SYS_POWER_MANAGEMENT=n
|
|||
|
||||
# Can only run under 1 CPU
|
||||
CONFIG_MP_NUM_CPUS=1
|
||||
CONFIG_TIMING_FUNCTIONS=y
|
||||
|
|
|
@ -16,16 +16,14 @@
|
|||
* forth by yielding the cpu. When counter reaches the maximal value, threads
|
||||
* stop and the average time of context switch is displayed.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <timing/timing.h>
|
||||
#include "utils.h"
|
||||
#include "timing_info.h"
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
/* number of context switches */
|
||||
#define NCTXSWITCH 10000
|
||||
#define NCTXSWITCH 10000
|
||||
#ifndef STACKSIZE
|
||||
#define STACKSIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
#define STACKSIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
#endif
|
||||
|
||||
/* stack used by the threads */
|
||||
|
@ -34,8 +32,8 @@ static K_THREAD_STACK_DEFINE(thread_two_stack, STACKSIZE);
|
|||
static struct k_thread thread_one_data;
|
||||
static struct k_thread thread_two_data;
|
||||
|
||||
static uint32_t timestamp_start;
|
||||
static uint32_t timestamp_end;
|
||||
static timing_t timestamp_start;
|
||||
static timing_t timestamp_end;
|
||||
|
||||
/* context switches counter */
|
||||
static volatile uint32_t ctx_switch_counter;
|
||||
|
@ -58,8 +56,7 @@ static void thread_one(void)
|
|||
{
|
||||
k_sem_take(&sync_sema, K_FOREVER);
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_start = timing_counter_get();
|
||||
|
||||
while (ctx_switch_counter < NCTXSWITCH) {
|
||||
k_yield();
|
||||
|
@ -67,8 +64,7 @@ static void thread_one(void)
|
|||
ctx_switch_balancer--;
|
||||
}
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_end = timing_counter_get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,37 +94,32 @@ static void thread_two(void)
|
|||
*/
|
||||
int coop_ctx_switch(void)
|
||||
{
|
||||
PRINT_FORMAT(" 6 - Measure average context switch time between threads (coop)");
|
||||
ctx_switch_counter = 0U;
|
||||
ctx_switch_balancer = 0;
|
||||
|
||||
benchmark_timer_start();
|
||||
timing_start();
|
||||
bench_test_start();
|
||||
|
||||
k_thread_create(&thread_one_data, thread_one_stack, STACKSIZE,
|
||||
(k_thread_entry_t) thread_one, NULL, NULL, NULL,
|
||||
6, 0, K_NO_WAIT);
|
||||
(k_thread_entry_t)thread_one, NULL, NULL, NULL,
|
||||
K_PRIO_COOP(6), 0, K_NO_WAIT);
|
||||
k_thread_create(&thread_two_data, thread_two_stack, STACKSIZE,
|
||||
(k_thread_entry_t) thread_two, NULL, NULL, NULL,
|
||||
6, 0, K_NO_WAIT);
|
||||
(k_thread_entry_t)thread_two, NULL, NULL, NULL,
|
||||
K_PRIO_COOP(6), 0, K_NO_WAIT);
|
||||
|
||||
if (ctx_switch_balancer > 3 || ctx_switch_balancer < -3) {
|
||||
PRINT_FORMAT(" Balance is %d. FAILED", ctx_switch_balancer);
|
||||
printk(" Balance is %d. FAILED", ctx_switch_balancer);
|
||||
} else if (bench_test_end() != 0) {
|
||||
error_count++;
|
||||
PRINT_OVERFLOW_ERROR();
|
||||
} else {
|
||||
uint32_t diff;
|
||||
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
|
||||
PRINT_FORMAT(" Average context switch time is %u tcs = %u"
|
||||
" nsec",
|
||||
diff / ctx_switch_counter,
|
||||
CYCLES_TO_NS_AVG(diff, ctx_switch_counter));
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
PRINT_STATS_AVG("Average context switch time between threads (coop)", diff, ctx_switch_counter);
|
||||
}
|
||||
|
||||
benchmark_timer_stop();
|
||||
timing_stop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -14,16 +14,15 @@
|
|||
* handler back to the interrupted thread.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include "utils.h"
|
||||
#include "timing_info.h"
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <irq_offload.h>
|
||||
|
||||
static volatile int flag_var;
|
||||
|
||||
static uint32_t timestamp_start;
|
||||
static uint32_t timestamp_end;
|
||||
static timing_t timestamp_start;
|
||||
static timing_t timestamp_end;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -36,11 +35,9 @@ static uint32_t timestamp_end;
|
|||
static void latency_test_isr(const void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
flag_var = 1;
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_start = timing_counter_get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,10 +54,9 @@ static void make_int(void)
|
|||
flag_var = 0;
|
||||
irq_offload(latency_test_isr, NULL);
|
||||
if (flag_var != 1) {
|
||||
PRINT_FORMAT(" Flag variable has not changed. FAILED\n");
|
||||
printk(" Flag variable has not changed. FAILED\n");
|
||||
} else {
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_end = timing_counter_get();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,16 +70,13 @@ int int_to_thread(void)
|
|||
{
|
||||
uint32_t diff;
|
||||
|
||||
PRINT_FORMAT(" 1 - Measure time to switch from ISR back to"
|
||||
" interrupted thread");
|
||||
benchmark_timer_start();
|
||||
timing_start();
|
||||
TICK_SYNCH();
|
||||
make_int();
|
||||
if (flag_var == 1) {
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
PRINT_FORMAT(" switching time is %u tcs = %u nsec",
|
||||
diff, CYCLES_TO_NS(diff));
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
PRINT_STATS("Switch from ISR back to interrupted thread", diff);
|
||||
}
|
||||
benchmark_timer_stop();
|
||||
timing_stop();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,18 +19,14 @@
|
|||
#include <irq_offload.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "timing_info.h"
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
static uint32_t timestamp_start;
|
||||
static uint32_t timestamp_end;
|
||||
static timing_t timestamp_start;
|
||||
static timing_t timestamp_end;
|
||||
static struct k_work work;
|
||||
|
||||
K_SEM_DEFINE(INTSEMA, 0, 1);
|
||||
K_SEM_DEFINE(WORKSEMA, 0, 1);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Test ISR used to measure best case interrupt latency
|
||||
|
@ -44,18 +40,14 @@ static void latency_test_isr(const void *unused)
|
|||
ARG_UNUSED(unused);
|
||||
|
||||
k_work_submit(&work);
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_start = timing_counter_get();
|
||||
}
|
||||
|
||||
static void worker(struct k_work *item)
|
||||
{
|
||||
(void)item;
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
timestamp_end = timing_counter_get();
|
||||
k_sem_give(&WORKSEMA);
|
||||
}
|
||||
|
||||
|
@ -76,10 +68,8 @@ void int_thread(void)
|
|||
k_thread_suspend(k_current_get());
|
||||
}
|
||||
|
||||
|
||||
K_THREAD_DEFINE(int_thread_id, 512,
|
||||
(k_thread_entry_t) int_thread, NULL, NULL, NULL,
|
||||
11, 0, 0);
|
||||
K_THREAD_DEFINE(int_thread_id, 512, (k_thread_entry_t)int_thread, NULL, NULL,
|
||||
NULL, 11, 0, 0);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -91,19 +81,17 @@ int int_to_thread_evt(void)
|
|||
{
|
||||
uint32_t diff;
|
||||
|
||||
PRINT_FORMAT(" 2 - Measure time from ISR to executing a different thread"
|
||||
" (rescheduled)");
|
||||
k_work_init(&work, worker);
|
||||
|
||||
benchmark_timer_start();
|
||||
timing_start();
|
||||
TICK_SYNCH();
|
||||
k_sem_give(&INTSEMA);
|
||||
k_sem_take(&WORKSEMA, K_FOREVER);
|
||||
benchmark_timer_stop();
|
||||
timing_stop();
|
||||
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
|
||||
PRINT_STATS("Time from ISR to executing a different thread", diff)
|
||||
|
||||
PRINT_FORMAT(" switch time is %u tcs = %u nsec",
|
||||
diff, CYCLES_TO_NS(diff));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,53 +12,55 @@
|
|||
#include <timestamp.h>
|
||||
#include "utils.h"
|
||||
#include <tc_util.h>
|
||||
#include "timing_info.h"
|
||||
|
||||
#define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
|
||||
uint32_t tm_off; /* time necessary to read the time */
|
||||
int error_count; /* track number of errors */
|
||||
|
||||
uint32_t tm_off; /* time necessary to read the time */
|
||||
int error_count; /* track number of errors */
|
||||
|
||||
extern void thread_switch_yield(void);
|
||||
extern void int_to_thread(void);
|
||||
extern void int_to_thread_evt(void);
|
||||
extern void sema_lock_unlock(void);
|
||||
extern void sema_test_signal(void);
|
||||
extern void mutex_lock_unlock(void);
|
||||
extern int coop_ctx_switch(void);
|
||||
extern int sema_test(void);
|
||||
extern int sema_context_switch(void);
|
||||
extern int suspend_resume(void);
|
||||
|
||||
void test_thread(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
PRINT_BANNER();
|
||||
PRINT_TIME_BANNER();
|
||||
uint32_t freq;
|
||||
|
||||
bench_test_init();
|
||||
benchmark_timer_init();
|
||||
|
||||
int_to_thread();
|
||||
print_dash_line();
|
||||
freq = timing_freq_get_mhz();
|
||||
|
||||
int_to_thread_evt();
|
||||
print_dash_line();
|
||||
TC_START("Time Measurement");
|
||||
TC_PRINT("Timing results: Clock frequency: %u MHz\n", freq);
|
||||
|
||||
sema_lock_unlock();
|
||||
print_dash_line();
|
||||
|
||||
mutex_lock_unlock();
|
||||
print_dash_line();
|
||||
timing_init();
|
||||
|
||||
thread_switch_yield();
|
||||
print_dash_line();
|
||||
|
||||
coop_ctx_switch();
|
||||
print_dash_line();
|
||||
|
||||
int_to_thread();
|
||||
|
||||
int_to_thread_evt();
|
||||
|
||||
suspend_resume();
|
||||
|
||||
sema_test_signal();
|
||||
|
||||
sema_context_switch();
|
||||
|
||||
mutex_lock_unlock();
|
||||
|
||||
TC_END_REPORT(error_count);
|
||||
}
|
||||
|
||||
K_THREAD_DEFINE(tt_id, STACK_SIZE,
|
||||
test_thread, NULL, NULL, NULL,
|
||||
10, 0, 0);
|
||||
|
||||
K_THREAD_DEFINE(test_thread_id, STACK_SIZE, test_thread, NULL, NULL, NULL, K_PRIO_PREEMPT(10), 0, 0);
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
|
59
tests/benchmarks/latency_measure/src/mutex_lock_unlock.c
Normal file
59
tests/benchmarks/latency_measure/src/mutex_lock_unlock.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2015 Wind River Systems, Inc.
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <timing/timing.h>
|
||||
#include "utils.h"
|
||||
|
||||
/* the number of mutex lock/unlock cycles */
|
||||
#define N_TEST_MUTEX 1000
|
||||
|
||||
K_MUTEX_DEFINE(test_mutex);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Test for the multiple mutex lock/unlock time
|
||||
*
|
||||
* The routine performs multiple mutex locks and then multiple mutex
|
||||
* unlocks to measure the necessary time.
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int mutex_lock_unlock(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t diff;
|
||||
timing_t timestamp_start;
|
||||
timing_t timestamp_end;
|
||||
|
||||
timing_start();
|
||||
|
||||
timestamp_start = timing_counter_get();
|
||||
|
||||
for (i = 0; i < N_TEST_MUTEX; i++) {
|
||||
k_mutex_lock(&test_mutex, K_FOREVER);
|
||||
}
|
||||
|
||||
timestamp_end = timing_counter_get();
|
||||
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
PRINT_STATS_AVG("Average time to lock a mutex", diff, N_TEST_MUTEX);
|
||||
|
||||
timestamp_start = timing_counter_get();
|
||||
|
||||
for (i = 0; i < N_TEST_MUTEX; i++) {
|
||||
k_mutex_unlock(&test_mutex);
|
||||
}
|
||||
|
||||
timestamp_end = timing_counter_get();
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
|
||||
PRINT_STATS_AVG("Average time to unlock a mutex", diff, N_TEST_MUTEX);
|
||||
timing_stop();
|
||||
return 0;
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2015 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file measure time for sema lock and release
|
||||
*
|
||||
* This file contains the test that measures semaphore and mutex lock and
|
||||
* release time in the kernel. There is no contention on the sema nor the
|
||||
* mutex being tested.
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "timing_info.h"
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
/* the number of semaphore give/take cycles */
|
||||
#define N_TEST_SEMA 1000
|
||||
|
||||
/* the number of mutex lock/unlock cycles */
|
||||
#define N_TEST_MUTEX 1000
|
||||
|
||||
static uint32_t timestamp_start;
|
||||
static uint32_t timestamp_end;
|
||||
|
||||
K_SEM_DEFINE(lock_unlock_sema, 0, N_TEST_SEMA);
|
||||
K_MUTEX_DEFINE(TEST_MUTEX);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief The function tests semaphore lock/unlock time
|
||||
*
|
||||
* The routine performs unlock the quite amount of semaphores and then
|
||||
* acquires them in order to measure the necessary time.
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int sema_lock_unlock(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t diff;
|
||||
|
||||
PRINT_FORMAT(" 3 - Measure average time to signal a sema then test"
|
||||
" that sema");
|
||||
bench_test_start();
|
||||
benchmark_timer_start();
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
for (i = 0; i < N_TEST_SEMA; i++) {
|
||||
k_sem_give(&lock_unlock_sema);
|
||||
}
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
benchmark_timer_stop();
|
||||
|
||||
if (bench_test_end() == 0) {
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
PRINT_FORMAT(" Average semaphore signal time %u tcs = %u"
|
||||
" nsec",
|
||||
diff / N_TEST_SEMA,
|
||||
CYCLES_TO_NS_AVG(diff, N_TEST_SEMA));
|
||||
} else {
|
||||
error_count++;
|
||||
PRINT_OVERFLOW_ERROR();
|
||||
}
|
||||
|
||||
bench_test_start();
|
||||
benchmark_timer_start();
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
for (i = 0; i < N_TEST_SEMA; i++) {
|
||||
k_sem_take(&lock_unlock_sema, K_FOREVER);
|
||||
}
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
benchmark_timer_stop();
|
||||
|
||||
if (bench_test_end() == 0) {
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
PRINT_FORMAT(" Average semaphore test time %u tcs = %u "
|
||||
"nsec",
|
||||
diff / N_TEST_SEMA,
|
||||
CYCLES_TO_NS_AVG(diff, N_TEST_SEMA));
|
||||
} else {
|
||||
error_count++;
|
||||
PRINT_OVERFLOW_ERROR();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Test for the multiple mutex lock/unlock time
|
||||
*
|
||||
* The routine performs multiple mutex locks and then multiple mutex
|
||||
* unlocks to measure the necessary time.
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int mutex_lock_unlock(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t diff;
|
||||
|
||||
benchmark_timer_start();
|
||||
PRINT_FORMAT(" 4- Measure average time to lock a mutex then"
|
||||
" unlock that mutex");
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
for (i = 0; i < N_TEST_MUTEX; i++) {
|
||||
k_mutex_lock(&TEST_MUTEX, K_FOREVER);
|
||||
}
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
PRINT_FORMAT(" Average time to lock the mutex %u tcs = %u nsec",
|
||||
diff / N_TEST_MUTEX,
|
||||
CYCLES_TO_NS_AVG(diff, N_TEST_MUTEX));
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
for (i = 0; i < N_TEST_MUTEX; i++) {
|
||||
k_mutex_unlock(&TEST_MUTEX);
|
||||
}
|
||||
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
|
||||
diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
PRINT_FORMAT(" Average time to unlock the mutex %u tcs = %u nsec",
|
||||
diff / N_TEST_MUTEX,
|
||||
CYCLES_TO_NS_AVG(diff, N_TEST_MUTEX));
|
||||
benchmark_timer_stop();
|
||||
return 0;
|
||||
}
|
126
tests/benchmarks/latency_measure/src/sema_test_signal_release.c
Normal file
126
tests/benchmarks/latency_measure/src/sema_test_signal_release.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2015 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file measure time for sema lock and release
|
||||
*
|
||||
* This file contains the test that measures semaphore and mutex lock and
|
||||
* release time in the kernel. There is no contention on the sema nor the
|
||||
* mutex being tested.
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <timing/timing.h>
|
||||
#include "utils.h"
|
||||
|
||||
/* the number of semaphore give/take cycles */
|
||||
#define N_TEST_SEMA 1000
|
||||
|
||||
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
/* stack used by the threads */
|
||||
static K_THREAD_STACK_DEFINE(thread_one_stack, STACK_SIZE);
|
||||
|
||||
static struct k_thread thread_one_data;
|
||||
|
||||
K_SEM_DEFINE(lock_unlock_sema, 0, N_TEST_SEMA);
|
||||
|
||||
K_SEM_DEFINE(sem_bench, 0, 1);
|
||||
|
||||
timing_t timestamp_start_sema_t_c;
|
||||
timing_t timestamp_end_sema_t_c;
|
||||
timing_t timestamp_start_sema_g_c;
|
||||
timing_t timestamp_end_sema_g_c;
|
||||
|
||||
void thread_sema_test1(void *p1, void *p2, void *p3)
|
||||
{
|
||||
timestamp_start_sema_t_c = timing_counter_get();
|
||||
k_sem_take(&sem_bench, K_FOREVER);
|
||||
timestamp_end_sema_g_c = timing_counter_get();
|
||||
}
|
||||
|
||||
int sema_context_switch(void)
|
||||
{
|
||||
uint32_t diff;
|
||||
timing_start();
|
||||
|
||||
k_thread_create(&thread_one_data, thread_one_stack,
|
||||
STACK_SIZE, thread_sema_test1,
|
||||
NULL, NULL, NULL,
|
||||
K_PRIO_PREEMPT(3), 0, K_FOREVER);
|
||||
k_thread_name_set(&thread_one_data, "sema_test1");
|
||||
k_thread_start(&thread_one_data);
|
||||
|
||||
timestamp_end_sema_t_c = timing_counter_get();
|
||||
diff = timing_cycles_get(×tamp_start_sema_t_c, ×tamp_end_sema_t_c);
|
||||
PRINT_STATS("Semaphore take time (context switch)", diff);
|
||||
|
||||
|
||||
timestamp_start_sema_g_c = timing_counter_get();
|
||||
k_sem_give(&sem_bench);
|
||||
diff = timing_cycles_get(×tamp_start_sema_g_c, ×tamp_end_sema_g_c);
|
||||
PRINT_STATS("Semaphore give time (context switch)", diff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief The function tests semaphore test/signal time
|
||||
*
|
||||
* The routine performs unlock the quite amount of semaphores and then
|
||||
* acquires them in order to measure the necessary time.
|
||||
*
|
||||
* @return 0 on success
|
||||
*/
|
||||
int sema_test_signal(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t diff;
|
||||
timing_t timestamp_start;
|
||||
timing_t timestamp_end;
|
||||
|
||||
bench_test_start();
|
||||
timing_start();
|
||||
|
||||
timestamp_start = timing_counter_get();
|
||||
|
||||
for (i = 0; i < N_TEST_SEMA; i++) {
|
||||
k_sem_give(&lock_unlock_sema);
|
||||
}
|
||||
|
||||
timestamp_end = timing_counter_get();
|
||||
timing_stop();
|
||||
|
||||
if (bench_test_end() == 0) {
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
PRINT_STATS_AVG("Average semaphore signal time", diff, N_TEST_SEMA);
|
||||
} else {
|
||||
error_count++;
|
||||
PRINT_OVERFLOW_ERROR();
|
||||
}
|
||||
|
||||
bench_test_start();
|
||||
timing_start();
|
||||
|
||||
timestamp_start = timing_counter_get();
|
||||
|
||||
for (i = 0; i < N_TEST_SEMA; i++) {
|
||||
k_sem_take(&lock_unlock_sema, K_FOREVER);
|
||||
}
|
||||
|
||||
timestamp_end = timing_counter_get();
|
||||
timing_stop();
|
||||
|
||||
if (bench_test_end() == 0) {
|
||||
diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
PRINT_STATS_AVG("Average semaphore test time", diff, N_TEST_SEMA);
|
||||
} else {
|
||||
error_count++;
|
||||
PRINT_OVERFLOW_ERROR();
|
||||
}
|
||||
timing_stop();
|
||||
return 0;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/* GCC specific test inline assembler functions and macros */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015, Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _TEST_ASM_INLINE_GCC_H
|
||||
#define _TEST_ASM_INLINE_GCC_H
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
#error test_asm_inline_gcc.h goes only with GCC
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_X86)
|
||||
static inline void timestamp_serialize(void)
|
||||
{
|
||||
__asm__ __volatile__ (/* serialize */
|
||||
"xorl %%eax,%%eax;\n\t"
|
||||
"cpuid;\n\t"
|
||||
:
|
||||
:
|
||||
: "%eax", "%ebx", "%ecx", "%edx");
|
||||
}
|
||||
#elif defined(CONFIG_CPU_CORTEX_M)
|
||||
static inline void timestamp_serialize(void)
|
||||
{
|
||||
/* isb is available in all Cortex-M */
|
||||
__asm__ __volatile__ (
|
||||
"isb;\n\t"
|
||||
:
|
||||
:
|
||||
: "memory");
|
||||
}
|
||||
#elif defined(CONFIG_CPU_ARCV2)
|
||||
#define timestamp_serialize()
|
||||
#else
|
||||
#error implementation of timestamp_serialize() not provided for your CPU target
|
||||
#endif
|
||||
|
||||
#endif /* _TEST_ASM_INLINE_GCC_H */
|
87
tests/benchmarks/latency_measure/src/thread.c
Normal file
87
tests/benchmarks/latency_measure/src/thread.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr.h>
|
||||
#include <timing/timing.h>
|
||||
#include "utils.h"
|
||||
|
||||
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
/* stack used by the threads */
|
||||
static K_THREAD_STACK_DEFINE(t1_stack, STACK_SIZE);
|
||||
|
||||
static struct k_thread t1;
|
||||
|
||||
timing_t timestamp_start_create_c;
|
||||
timing_t timestamp_end_create_c;
|
||||
timing_t timestamp_start_start_c;
|
||||
timing_t timestamp_end_start_c;
|
||||
timing_t timestamp_start_suspend_c;
|
||||
timing_t timestamp_end_suspend_c;
|
||||
timing_t timestamp_start_resume_c;
|
||||
timing_t timestamp_end_resume_c;
|
||||
|
||||
timing_t timestamp_start_abort_1;
|
||||
timing_t timestamp_end_abort_1;
|
||||
|
||||
void thread_suspend_resume(void *p1, void *p2, void *p3)
|
||||
{
|
||||
timestamp_start_suspend_c = timing_counter_get();
|
||||
k_thread_suspend(_current);
|
||||
|
||||
/* comes to this line once its resumed*/
|
||||
timestamp_start_resume_c = timing_counter_get();
|
||||
|
||||
}
|
||||
|
||||
int suspend_resume(void)
|
||||
{
|
||||
uint32_t diff;
|
||||
|
||||
timing_start();
|
||||
|
||||
timestamp_start_create_c = timing_counter_get();
|
||||
|
||||
k_tid_t t1_tid = k_thread_create(&t1, t1_stack, STACK_SIZE,
|
||||
thread_suspend_resume, NULL, NULL,
|
||||
NULL, K_PRIO_PREEMPT(6), 0, K_FOREVER);
|
||||
|
||||
timestamp_end_create_c = timing_counter_get();
|
||||
k_thread_name_set(t1_tid, "t1");
|
||||
|
||||
timestamp_start_start_c = timing_counter_get();
|
||||
k_thread_start(t1_tid);
|
||||
|
||||
timestamp_end_suspend_c = timing_counter_get();
|
||||
k_thread_resume(t1_tid);
|
||||
timestamp_end_resume_c = timing_counter_get();
|
||||
|
||||
|
||||
diff = timing_cycles_get(×tamp_start_create_c,
|
||||
×tamp_end_create_c);
|
||||
PRINT_STATS("Time to create a thread (without start)", diff);
|
||||
|
||||
diff = timing_cycles_get(×tamp_start_start_c,
|
||||
×tamp_start_suspend_c);
|
||||
PRINT_STATS("Time to start a thread", diff);
|
||||
|
||||
diff = timing_cycles_get(×tamp_start_suspend_c,
|
||||
×tamp_end_suspend_c);
|
||||
PRINT_STATS("Time to suspend a thread", diff);
|
||||
|
||||
diff = timing_cycles_get(×tamp_start_resume_c,
|
||||
×tamp_end_resume_c);
|
||||
PRINT_STATS("Time to resume a thread", diff);
|
||||
|
||||
timestamp_start_abort_1 = timing_counter_get();
|
||||
k_thread_abort(t1_tid);
|
||||
timestamp_end_abort_1 = timing_counter_get();
|
||||
|
||||
diff = timing_cycles_get(×tamp_start_abort_1,
|
||||
×tamp_end_abort_1);
|
||||
PRINT_STATS("Time to abort a thread (not running)", diff);
|
||||
|
||||
timing_stop();
|
||||
return 0;
|
||||
}
|
|
@ -12,24 +12,23 @@
|
|||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <timing/timing.h>
|
||||
#include <stdlib.h>
|
||||
#include "timestamp.h"
|
||||
#include "utils.h" /* PRINT () and other macros */
|
||||
#include "timing_info.h"
|
||||
#include "utils.h" /* PRINT () and other macros */
|
||||
|
||||
/* context switch enough time so our measurement is precise */
|
||||
#define NB_OF_YIELD 1000
|
||||
#define NB_OF_YIELD 1000
|
||||
|
||||
static uint32_t helper_thread_iterations;
|
||||
|
||||
#define Y_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
#define Y_PRIORITY 10
|
||||
#define Y_STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACKSIZE)
|
||||
#define Y_PRIORITY K_PRIO_PREEMPT(10)
|
||||
|
||||
K_THREAD_STACK_DEFINE(y_stack_area, Y_STACK_SIZE);
|
||||
static struct k_thread y_thread;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper thread for measuring thread switch latency using yield
|
||||
*
|
||||
* @return N/A
|
||||
|
@ -43,7 +42,6 @@ void yielding_thread(void *arg1, void *arg2, void *arg3)
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Entry point for thread context switch using yield test
|
||||
*
|
||||
* @return N/A
|
||||
|
@ -52,24 +50,21 @@ void thread_switch_yield(void)
|
|||
{
|
||||
uint32_t iterations = 0U;
|
||||
int32_t delta;
|
||||
uint32_t timestamp_start;
|
||||
uint32_t timestamp_end;
|
||||
timing_t timestamp_start;
|
||||
timing_t timestamp_end;
|
||||
uint32_t ts_diff;
|
||||
|
||||
PRINT_FORMAT(" 5 - Measure average context switch time between threads"
|
||||
" using (k_yield)");
|
||||
|
||||
benchmark_timer_start();
|
||||
timing_start();
|
||||
bench_test_start();
|
||||
|
||||
/* launch helper thread of the same priority than this routine */
|
||||
k_thread_create(&y_thread, y_stack_area, Y_STACK_SIZE,
|
||||
yielding_thread, NULL, NULL, NULL,
|
||||
Y_PRIORITY, 0, K_NO_WAIT);
|
||||
/* launch helper thread of the same priority as the thread
|
||||
* of routine
|
||||
*/
|
||||
k_thread_create(&y_thread, y_stack_area, Y_STACK_SIZE, yielding_thread,
|
||||
NULL, NULL, NULL, Y_PRIORITY, 0, K_NO_WAIT);
|
||||
|
||||
/* get initial timestamp */
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_start = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_start = timing_counter_get();
|
||||
|
||||
/* loop until either helper or this routine reaches number of yields */
|
||||
while (iterations < NB_OF_YIELD &&
|
||||
|
@ -79,8 +74,7 @@ void thread_switch_yield(void)
|
|||
}
|
||||
|
||||
/* get the number of cycles it took to do the test */
|
||||
TIMING_INFO_PRE_READ();
|
||||
timestamp_end = TIMING_INFO_OS_GET_TIME();
|
||||
timestamp_end = timing_counter_get();
|
||||
|
||||
/* Ensure both helper and this routine were context switching back &
|
||||
* forth.
|
||||
|
@ -98,19 +92,15 @@ void thread_switch_yield(void)
|
|||
* called yield without the other having chance to execute
|
||||
*/
|
||||
error_count++;
|
||||
PRINT_FORMAT(" Error, iteration:%u, helper iteration:%u",
|
||||
printk(" Error, iteration:%u, helper iteration:%u",
|
||||
iterations, helper_thread_iterations);
|
||||
} else {
|
||||
/* thread_yield is called (iterations + helper_thread_iterations)
|
||||
* times in total.
|
||||
*/
|
||||
ts_diff = TIMING_INFO_GET_DELTA(timestamp_start, timestamp_end);
|
||||
PRINT_FORMAT(" Average thread context switch using "
|
||||
"yield %u tcs = %u nsec",
|
||||
ts_diff / (iterations + helper_thread_iterations),
|
||||
CYCLES_TO_NS_AVG(ts_diff,
|
||||
(iterations + helper_thread_iterations)));
|
||||
ts_diff = timing_cycles_get(×tamp_start, ×tamp_end);
|
||||
PRINT_STATS_AVG("Average thread context switch using yield", ts_diff, (iterations + helper_thread_iterations));
|
||||
}
|
||||
|
||||
benchmark_timer_stop();
|
||||
timing_stop();
|
||||
}
|
||||
|
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _TIMING_INFO_H_
|
||||
#define _TIMING_INFO_H_
|
||||
|
||||
#include <timestamp.h>
|
||||
|
||||
#ifdef CONFIG_NRF_RTC_TIMER
|
||||
#include <soc.h>
|
||||
|
||||
/* To get current count of timer, first 1 need to be written into
|
||||
* Capture Register and Current Count will be copied into corresponding
|
||||
* current count register.
|
||||
*/
|
||||
#define TIMING_INFO_PRE_READ() (NRF_TIMER2->TASKS_CAPTURE[0] = 1)
|
||||
#define TIMING_INFO_OS_GET_TIME() (NRF_TIMER2->CC[0])
|
||||
|
||||
#elif CONFIG_SOC_SERIES_MEC1501X
|
||||
#include <soc.h>
|
||||
|
||||
#define TIMING_INFO_PRE_READ()
|
||||
#define TIMING_INFO_OS_GET_TIME() (B32TMR1_REGS->CNT)
|
||||
|
||||
#else
|
||||
#define TIMING_INFO_PRE_READ()
|
||||
#define TIMING_INFO_OS_GET_TIME() (k_cycle_get_32())
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* NRF RTC TIMER runs ar very slow rate (32KHz), So in order to measure
|
||||
* Kernel starts a dedicated timer to measure kernel stats.
|
||||
*/
|
||||
#ifdef CONFIG_NRF_RTC_TIMER
|
||||
#define NANOSECS_PER_SEC (1000000000)
|
||||
#define CYCLES_PER_SEC (16000000/(1 << NRF_TIMER2->PRESCALER))
|
||||
|
||||
#define CYCLES_TO_NS(x) ((x) * (NANOSECS_PER_SEC/CYCLES_PER_SEC))
|
||||
#define CYCLES_TO_NS_AVG(x, NCYCLES) \
|
||||
(CYCLES_TO_NS(x) / NCYCLES)
|
||||
|
||||
/* Configure Timer parameters */
|
||||
static inline void benchmark_timer_init(void)
|
||||
{
|
||||
NRF_TIMER2->TASKS_CLEAR = 1; /* Clear Timer */
|
||||
NRF_TIMER2->MODE = 0; /* Timer Mode */
|
||||
NRF_TIMER2->PRESCALER = 0; /* 16M Hz */
|
||||
NRF_TIMER2->BITMODE = 3; /* 32 - bit */
|
||||
}
|
||||
|
||||
/* Stop the timer */
|
||||
static inline void benchmark_timer_stop(void)
|
||||
{
|
||||
NRF_TIMER2->TASKS_STOP = 1; /* Stop Timer */
|
||||
}
|
||||
|
||||
/*Start the timer */
|
||||
static inline void benchmark_timer_start(void)
|
||||
{
|
||||
NRF_TIMER2->TASKS_START = 1; /* Start Timer */
|
||||
}
|
||||
|
||||
#elif CONFIG_SOC_SERIES_MEC1501X
|
||||
|
||||
#define NANOSECS_PER_SEC (1000000000)
|
||||
#define CYCLES_PER_SEC (48000000)
|
||||
#define CYCLES_TO_NS(x) ((x) * (NANOSECS_PER_SEC/CYCLES_PER_SEC))
|
||||
#define CYCLES_TO_NS_AVG(x, NCYCLES) \
|
||||
(CYCLES_TO_NS(x) / NCYCLES)
|
||||
|
||||
/* Configure Timer parameters */
|
||||
static inline void benchmark_timer_init(void)
|
||||
{
|
||||
/* Setup counter */
|
||||
B32TMR1_REGS->CTRL =
|
||||
MCHP_BTMR_CTRL_ENABLE |
|
||||
MCHP_BTMR_CTRL_AUTO_RESTART |
|
||||
MCHP_BTMR_CTRL_COUNT_UP;
|
||||
|
||||
B32TMR1_REGS->PRLD = 0; /* Preload */
|
||||
B32TMR1_REGS->CNT = 0; /* Counter value */
|
||||
|
||||
B32TMR1_REGS->IEN = 0; /* Disable interrupt */
|
||||
B32TMR1_REGS->STS = 1; /* Clear interrupt */
|
||||
}
|
||||
|
||||
/* Stop the timer */
|
||||
static inline void benchmark_timer_stop(void)
|
||||
{
|
||||
B32TMR1_REGS->CTRL &= ~MCHP_BTMR_CTRL_START;
|
||||
}
|
||||
|
||||
/* Start the timer */
|
||||
static inline void benchmark_timer_start(void)
|
||||
{
|
||||
B32TMR1_REGS->CTRL |= MCHP_BTMR_CTRL_START;
|
||||
}
|
||||
|
||||
#else /* All other architectures */
|
||||
/* Done because weak attribute doesn't work on static inline. */
|
||||
static inline void benchmark_timer_init(void) { }
|
||||
static inline void benchmark_timer_stop(void) { }
|
||||
static inline void benchmark_timer_start(void) { }
|
||||
|
||||
#define CYCLES_TO_NS(x) ((uint32_t)k_cyc_to_ns_floor64(x))
|
||||
#define CYCLES_TO_NS_AVG(x, NCYCLES) \
|
||||
((uint32_t)(k_cyc_to_ns_floor64(x) / NCYCLES))
|
||||
|
||||
#endif /* CONFIG_NRF_RTC_TIMER */
|
||||
|
||||
static inline uint32_t TIMING_INFO_GET_DELTA(uint32_t start, uint32_t end)
|
||||
{
|
||||
return (end >= start) ? (end - start) : (ULONG_MAX - start + end);
|
||||
}
|
||||
|
||||
#endif /* _TIMING_INFO_H_ */
|
|
@ -1,20 +0,0 @@
|
|||
/* utils.c - utility functions used by latency measurement */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* DESCRIPTION
|
||||
* this file contains commonly used functions
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
#include "timestamp.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* scratchpad for the string used to print on console */
|
||||
char tmp_string[TMP_STRING_SIZE];
|
|
@ -1,85 +1,47 @@
|
|||
/* utils.h - utility functions used by latency measurement */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _LATENCY_MEASURE_UNIT_H
|
||||
#define _LATENCY_MEASURE_UNIT_H
|
||||
/*
|
||||
* DESCRIPTION
|
||||
* This file contains function declarations, macroses and inline functions
|
||||
* @brief This file contains function declarations, macroses and inline functions
|
||||
* used in latency measurement.
|
||||
*/
|
||||
|
||||
#include "timing_info.h"
|
||||
#include <timing/timing.h>
|
||||
#include <sys/printk.h>
|
||||
#include <stdio.h>
|
||||
#include "timestamp.h"
|
||||
|
||||
#define INT_IMM8_OFFSET 1
|
||||
#define IRQ_PRIORITY 3
|
||||
|
||||
#ifdef CONFIG_PRINTK
|
||||
#include <sys/printk.h>
|
||||
#include <stdio.h>
|
||||
#include "timestamp.h"
|
||||
extern char tmp_string[];
|
||||
extern int error_count;
|
||||
|
||||
#define TMP_STRING_SIZE 100
|
||||
|
||||
#define PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__)
|
||||
#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)
|
||||
|
||||
#define PRINT_FORMAT(fmt, ...) \
|
||||
do { \
|
||||
snprintf(tmp_string, TMP_STRING_SIZE, fmt, ##__VA_ARGS__); \
|
||||
PRINTF("|%-77s|\n", tmp_string); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Print dash line
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void print_dash_line(void)
|
||||
{
|
||||
PRINTF("|-------------------------------------------------------"
|
||||
"----------------------|\n");
|
||||
}
|
||||
|
||||
#define PRINT_END_BANNER() \
|
||||
do { \
|
||||
PRINTF("| E N D " \
|
||||
" |\n"); \
|
||||
print_dash_line(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define PRINT_BANNER() \
|
||||
do { \
|
||||
print_dash_line(); \
|
||||
PRINTF("| Latency Benchmark " \
|
||||
" |\n"); \
|
||||
print_dash_line(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define PRINT_TIME_BANNER() \
|
||||
do { \
|
||||
PRINT_FORMAT(" tcs = timer clock cycles: 1 tcs is %u nsec", \
|
||||
CYCLES_TO_NS(1)); \
|
||||
print_dash_line(); \
|
||||
} while (0)
|
||||
|
||||
#define PRINT_OVERFLOW_ERROR() \
|
||||
PRINT_FORMAT(" Error: tick occurred")
|
||||
printk(" Error: tick occurred\n")
|
||||
|
||||
#ifdef CSV_FORMAT_OUTPUT
|
||||
#define FORMAT "%-60s,%8u,%8u\n"
|
||||
#else
|
||||
#error PRINTK configuration option needs to be enabled
|
||||
#define FORMAT "%-60s:%8u cycles , %8u ns\n"
|
||||
#endif
|
||||
|
||||
void raiseIntFunc(void);
|
||||
extern void raiseInt(uint8_t id);
|
||||
#define PRINT_F(...) \
|
||||
{ \
|
||||
char sline[256]; \
|
||||
snprintk(sline, 254, FORMAT, ##__VA_ARGS__); \
|
||||
printk("%s", sline); \
|
||||
}
|
||||
|
||||
/* pointer to the ISR */
|
||||
typedef void (*ptestIsr) (void *unused);
|
||||
#define PRINT_STATS(x, y) \
|
||||
PRINT_F(x, y, (uint32_t)timing_cycles_to_ns(y))
|
||||
|
||||
#define PRINT_STATS_AVG(x, y, counter) \
|
||||
PRINT_F(x, y / counter, (uint32_t)timing_cycles_to_ns_avg(y, counter));
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
tests:
|
||||
benchmark.kernel.latency:
|
||||
arch_allow: x86 arm posix
|
||||
platform_exclude: qemu_x86_64
|
||||
# FIXME: no DWT and no RTC_TIMER for qemu_cortex_m0
|
||||
platform_exclude: qemu_x86_64 qemu_cortex_m0
|
||||
filter: CONFIG_PRINTK and not CONFIG_SOC_FAMILY_STM32
|
||||
tags: benchmark
|
||||
|
||||
|
@ -10,6 +11,8 @@ tests:
|
|||
# 20 Ticks per secondes allows a frequency up to 335544300Hz (335MHz)
|
||||
benchmark.kernel.latency.stm32:
|
||||
filter: CONFIG_PRINTK and CONFIG_SOC_FAMILY_STM32
|
||||
# FIXME: no DWT and no RTC_TIMER
|
||||
platform_exclude: qemu_cortex_m0
|
||||
tags: benchmark
|
||||
extra_configs:
|
||||
- CONFIG_SYS_CLOCK_TICKS_PER_SEC=20
|
||||
|
|
|
@ -88,19 +88,6 @@ int check_result(int i, uint32_t t)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Check for a key press
|
||||
*
|
||||
* @return 1 when a keyboard key is pressed, or 0 if no keyboard support
|
||||
*/
|
||||
int kbhit(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Prepares the test output
|
||||
|
@ -193,7 +180,7 @@ void main(void)
|
|||
}
|
||||
TC_PRINT_RUNID;
|
||||
|
||||
} while (continuously && !kbhit());
|
||||
} while (continuously);
|
||||
|
||||
output_close();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue