1 /* 2 * Copyright (c) 2012-2015 Wind River Systems, Inc. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /* 8 * @file macroses for measuring time in benchmarking tests 9 * 10 * This file contains the macroses for taking and converting time for 11 * benchmarking tests. 12 */ 13 14 #ifndef _TIMESTAMP_H_ 15 #define _TIMESTAMP_H_ 16 #include <zephyr/kernel.h> 17 18 #include <limits.h> 19 #if defined(__GNUC__) 20 #include <zephyr/test_asm_inline_gcc.h> 21 #else 22 #include <zephyr/test_asm_inline_other.h> 23 #endif 24 25 26 #define TICK_SYNCH() k_sleep(K_TICKS(1)) 27 28 #define OS_GET_TIME() k_cycle_get_32() 29 30 /* time necessary to read the time */ 31 extern uint32_t tm_off; 32 TIME_STAMP_DELTA_GET(uint32_t ts)33static inline uint32_t TIME_STAMP_DELTA_GET(uint32_t ts) 34 { 35 uint32_t t; 36 37 /* serialize so OS_GET_TIME() is not reordered */ 38 timestamp_serialize(); 39 40 t = OS_GET_TIME(); 41 uint32_t res = (t >= ts) ? (t - ts) : (ULONG_MAX - ts + t); 42 43 if (ts > 0) { 44 res -= tm_off; 45 } 46 return res; 47 } 48 49 /* 50 * Routine initializes the benchmark timing measurement 51 * The function sets up the global variable tm_off 52 */ bench_test_init(void)53static inline void bench_test_init(void) 54 { 55 uint32_t t = OS_GET_TIME(); 56 57 tm_off = OS_GET_TIME() - t; 58 } 59 60 61 /* timestamp for checks */ 62 static int64_t timestamp_check; 63 64 /* 65 * Routines are invoked before and after the benchmark and check 66 * if benchmarking code took less time than necessary for the 67 * high precision timer register overflow. 68 * Functions modify the timestamp_check global variable. 69 */ bench_test_start(void)70static inline void bench_test_start(void) 71 { 72 timestamp_check = 0; 73 /* before reading time we synchronize to the start of the timer tick */ 74 TICK_SYNCH(); 75 timestamp_check = k_uptime_delta(×tamp_check); 76 } 77 78 79 /* returns 0 if the completed within a second and -1 if not */ bench_test_end(void)80static inline int bench_test_end(void) 81 { 82 timestamp_check = k_uptime_delta(×tamp_check); 83 84 /* Flag an error if the test ran for more than a second. 85 * (Note: Existing benchmarks have CONFIG_SYS_CLOCK_TICKS_PER_SEC=1 set, 86 * in such configs this check can be an indicator of whether 87 * timer tick interrupt overheads too are getting accounted towards 88 * benchmark time) 89 */ 90 if (timestamp_check >= MSEC_PER_SEC) { 91 return -1; 92 } 93 return 0; 94 } 95 96 /* 97 * Returns -1 if number of ticks cause high precision timer counter 98 * overflow and 0 otherwise 99 * Called after bench_test_end to see if we still can use timing 100 * results or is it completely invalid 101 */ high_timer_overflow(void)102static inline int high_timer_overflow(void) 103 { 104 /* Check if the time elapsed in msec is sufficient to trigger an 105 * overflow of the high precision timer 106 */ 107 if (timestamp_check >= (k_cyc_to_ns_floor64(UINT_MAX) / 108 (NSEC_PER_USEC * USEC_PER_MSEC))) { 109 return -1; 110 } 111 return 0; 112 } 113 114 #endif /* _TIMESTAMP_H_ */ 115