kernel: use timing functions to gather thread runtime stats

This uses the timing functions to gather execution cycles of
threads. This provides greater details if arch/SoC/board
uses timer with higher resolution.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
Daniel Leung 2020-10-14 12:17:12 -07:00 committed by Anas Nashif
parent 11e6b43090
commit fd7a68dbe9
4 changed files with 48 additions and 2 deletions

View file

@ -19,6 +19,10 @@
#include <stdbool.h>
#include <toolchain.h>
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
#include <timing/timing.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -283,14 +287,22 @@ struct z_poller {
#ifdef CONFIG_THREAD_RUNTIME_STATS
struct k_thread_runtime_stats {
/* Thread execution cycles */
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
timing_t execution_cycles;
#else
uint64_t execution_cycles;
#endif
};
typedef struct k_thread_runtime_stats k_thread_runtime_stats_t;
struct _thread_runtime_stats {
/* Timestamp when last switched in */
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
timing_t last_switched_in;
#else
uint32_t last_switched_in;
#endif
k_thread_runtime_stats_t stats;
};

View file

@ -355,7 +355,7 @@ config THREAD_MAX_NAME_LEN
config INSTRUMENT_THREAD_SWITCHING
bool
config THREAD_RUNTIME_STATS
menuconfig THREAD_RUNTIME_STATS
bool "Thread runtime statistics"
select INSTRUMENT_THREAD_SWITCHING
help
@ -364,6 +364,19 @@ config THREAD_RUNTIME_STATS
For example:
- Thread total execution cycles
if THREAD_RUNTIME_STATS
config THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
bool "Use timing functions to gather statistics"
select TIMING_FUNCTIONS
help
Use timing functions to gather thread runtime statistics.
Note that timing functions may use a different timer than
the default timer for OS timekeeping.
endif # THREAD_RUNTIME_STATS
endmenu
menu "Work Queue Options"

View file

@ -480,6 +480,11 @@ FUNC_NORETURN void z_cstart(void)
__stack_chk_guard <<= 8;
#endif /* CONFIG_STACK_CANARIES */
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
timing_init();
timing_start();
#endif
#ifdef CONFIG_MULTITHREADING
switch_to_main_thread(prepare_multithreading());
#else

View file

@ -1036,14 +1036,24 @@ void z_thread_mark_switched_in(void)
struct k_thread *thread;
thread = k_current_get();
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
thread->rt_stats.last_switched_in = timing_counter_get();
#else
thread->rt_stats.last_switched_in = k_cycle_get_32();
#endif /* CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS */
#endif /* CONFIG_THREAD_RUNTIME_STATS */
}
void z_thread_mark_switched_out(void)
{
#ifdef CONFIG_THREAD_RUNTIME_STATS
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
timing_t now;
#else
uint32_t now;
#endif /* CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS */
uint64_t diff;
struct k_thread *thread;
@ -1059,10 +1069,16 @@ void z_thread_mark_switched_out(void)
return;
}
#ifdef CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
now = timing_counter_get();
diff = timing_cycles_get(&thread->rt_stats.last_switched_in, &now);
#else
now = k_cycle_get_32();
diff = (uint64_t)now - thread->rt_stats.last_switched_in;
thread->rt_stats.stats.execution_cycles += diff;
thread->rt_stats.last_switched_in = 0;
#endif /* CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS */
thread->rt_stats.stats.execution_cycles += diff;
threads_runtime_stats.execution_cycles += diff;
#endif /* CONFIG_THREAD_RUNTIME_STATS */