116 lines
2.5 KiB
C
116 lines
2.5 KiB
C
/* timestamp.h - macroses for measuring time in benchmarking tests */
|
|
|
|
/*
|
|
* Copyright (c) 2012-2015 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*
|
|
* DESCRIPTION
|
|
* This file contains the macroses for taking and converting time for
|
|
* benchmarking tests.
|
|
*/
|
|
|
|
#ifndef _TIMESTAMP_H_
|
|
#define _TIMESTAMP_H_
|
|
#include <zephyr.h>
|
|
|
|
#include <limits.h>
|
|
#if defined(__GNUC__)
|
|
#include <test_asm_inline_gcc.h>
|
|
#else
|
|
#include <test_asm_inline_other.h>
|
|
#endif
|
|
|
|
|
|
#define TICK_SYNCH() k_sleep(1)
|
|
|
|
#define OS_GET_TIME() k_cycle_get_32()
|
|
|
|
/* time necessary to read the time */
|
|
extern uint32_t tm_off;
|
|
|
|
static inline uint32_t TIME_STAMP_DELTA_GET(uint32_t ts)
|
|
{
|
|
uint32_t t;
|
|
|
|
/* serialize so OS_GET_TIME() is not reordered */
|
|
timestamp_serialize();
|
|
|
|
t = OS_GET_TIME();
|
|
uint32_t res = (t >= ts) ? (t - ts) : (ULONG_MAX - ts + t);
|
|
|
|
if (ts > 0) {
|
|
res -= tm_off;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
* Routine initializes the benchmark timing measurement
|
|
* The function sets up the global variable tm_off
|
|
*/
|
|
static inline void bench_test_init(void)
|
|
{
|
|
uint32_t t = OS_GET_TIME();
|
|
|
|
tm_off = OS_GET_TIME() - t;
|
|
}
|
|
|
|
|
|
/* timestamp for checks */
|
|
static int64_t tCheck;
|
|
|
|
/*
|
|
* Routines are invoked before and after the benchmark and check
|
|
* if penchmarking code took less time than necessary for the
|
|
* high precision timer register overflow.
|
|
* Functions modify the tCheck global variable.
|
|
*/
|
|
static inline void bench_test_start(void)
|
|
{
|
|
tCheck = 0;
|
|
/* before reading time we synchronize to the start of the timer tick */
|
|
TICK_SYNCH();
|
|
tCheck = k_uptime_delta(&tCheck);
|
|
}
|
|
|
|
|
|
/* returns 0 if the completed within a second and -1 if not */
|
|
static inline int bench_test_end(void)
|
|
{
|
|
tCheck = k_uptime_delta(&tCheck);
|
|
|
|
/* Flag an error if the test ran for more than a second.
|
|
* (Note: Existing benchmarks have CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 set,
|
|
* in such configs this check can be an indicator of whether
|
|
* timer tick interrupt overheads too are getting accounted towards
|
|
* benchmark time)
|
|
*/
|
|
if (tCheck >= MSEC_PER_SEC) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Returns -1 if number of ticks cause high precision timer counter
|
|
* overflow and 0 otherwise
|
|
* Called after bench_test_end to see if we still can use timing
|
|
* results or is it completely invalid
|
|
*/
|
|
static inline int high_timer_overflow(void)
|
|
{
|
|
/* Check if the time elapsed in msec is sufficient to trigger an
|
|
* overflow of the high precision timer
|
|
*/
|
|
if (tCheck >= (SYS_CLOCK_HW_CYCLES_TO_NS64(UINT_MAX) /
|
|
(NSEC_PER_USEC * USEC_PER_MSEC))) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif /* _TIMESTAMP_H_ */
|