| /* timestamp.h - macroses for measuring time in benchmarking tests */ |
| |
| /* |
| * Copyright (c) 2012-2015 Wind River Systems, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* |
| * 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 |
| |
| #if defined(CONFIG_NANOKERNEL) |
| /* number of ticks before timer overflows */ |
| #define BENCH_MAX_TICKS (sys_clock_ticks_per_sec - 1) |
| |
| typedef int64_t TICK_TYPE; |
| |
| static inline void TICK_SYNCH(void) |
| { |
| TICK_TYPE reftime; |
| |
| (void) sys_tick_delta(&reftime); |
| while (sys_tick_delta(&reftime) == 0) { |
| } |
| } |
| |
| #elif (defined(CONFIG_MICROKERNEL) && defined(KERNEL)) |
| typedef int64_t TICK_TYPE; |
| |
| #define TICK_SYNCH() task_sleep(1) |
| |
| #else |
| #error either CONFIG_NANOKERNEL or CONFIG_MICROKERNEL must be defined |
| #endif /* CONFIG_NANOKERNEL */ |
| |
| #define TICK_GET(x) ((TICK_TYPE) sys_tick_delta(x)) |
| #define OS_GET_TIME() sys_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; |
| } |
| |
| #if defined(CONFIG_MICROKERNEL) && defined(KERNEL) |
| |
| /* number of ticks before timer overflows */ |
| #define BENCH_MAX_TICKS (sys_clock_ticks_per_sec - 1) |
| |
| #endif /* CONFIG_MICROKERNEL */ |
| |
| #if (defined(CONFIG_NANOKERNEL) || defined(CONFIG_MICROKERNEL)) && defined(KERNEL) |
| /* tickstamp used for timer counter overflow check */ |
| static TICK_TYPE 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 = TICK_GET(&tCheck); |
| } |
| |
| |
| /* returns 0 if the number of ticks is valid and -1 if not */ |
| static inline int bench_test_end(void) |
| { |
| tCheck = TICK_GET(&tCheck); |
| if (tCheck > BENCH_MAX_TICKS) { |
| 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) |
| { |
| if (tCheck >= (UINT_MAX / sys_clock_hw_cycles_per_tick)) { |
| return -1; |
| } |
| return 0; |
| } |
| #endif /* CONFIG_NANOKERNEL || CONFIG_MICROKERNEL */ |
| |
| #endif /* _TIMESTAMP_H_ */ |