From 09e8db3d688d5f3979fe9920f4e5f0ea909e100c Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Wed, 31 Mar 2021 13:56:05 -0700 Subject: [PATCH] kernel: enable using timing subsys to collect paging histograms This adds bits to the paging timing histogram collection routines so they can use timing functions to collect execution time data. Signed-off-by: Daniel Leung --- arch/Kconfig | 6 ++++++ kernel/mmu.c | 42 +++++++++++++++++++++++++++++++++++++- kernel/paging/statistics.c | 18 ++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index 47c7f2ec2da..d63c6cdfb6b 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -684,6 +684,12 @@ config DEMAND_PAGING_STATS Should say N in production system as this is not without cost. +config DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + bool "Use Timing Functions to Gather Demand Paging Statistics" + select TIMING_FUNCTIONS_NEED_AT_BOOT + help + Use timing functions to gather various demand paging statistics. + config DEMAND_PAGING_THREAD_STATS bool "Gather per Thread Demand Paging Statistics" depends on DEMAND_PAGING_STATS diff --git a/kernel/mmu.c b/kernel/mmu.c index bd8badf83d2..baab6b455d0 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -582,15 +583,27 @@ static inline void do_backing_store_page_in(uintptr_t location) { #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM uint32_t time_diff; + +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + timing_t time_start, time_end; + + time_start = timing_counter_get(); +#else uint32_t time_start; time_start = k_cycle_get_32(); +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ z_backing_store_page_in(location); #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + time_end = timing_counter_get(); + time_diff = (uint32_t)timing_cycles_get(&time_start, &time_end); +#else time_diff = k_cycle_get_32() - time_start; +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ z_paging_histogram_inc(&z_paging_histogram_backing_store_page_in, time_diff); @@ -601,15 +614,27 @@ static inline void do_backing_store_page_out(uintptr_t location) { #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM uint32_t time_diff; + +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + timing_t time_start, time_end; + + time_start = timing_counter_get(); +#else uint32_t time_start; time_start = k_cycle_get_32(); +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ z_backing_store_page_out(location); #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + time_end = timing_counter_get(); + time_diff = (uint32_t)timing_cycles_get(&time_start, &time_end); +#else time_diff = k_cycle_get_32() - time_start; +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ z_paging_histogram_inc(&z_paging_histogram_backing_store_page_out, time_diff); @@ -901,14 +926,29 @@ static inline struct z_page_frame *do_eviction_select(bool *dirty) struct z_page_frame *pf; #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM - uint32_t time_start = k_cycle_get_32(); uint32_t time_diff; + +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + timing_t time_start, time_end; + + time_start = timing_counter_get(); +#else + uint32_t time_start; + + time_start = k_cycle_get_32(); +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ pf = z_eviction_select(dirty); #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + time_end = timing_counter_get(); + time_diff = (uint32_t)timing_cycles_get(&time_start, &time_end); +#else time_diff = k_cycle_get_32() - time_start; +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ + z_paging_histogram_inc(&z_paging_histogram_eviction, time_diff); #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ diff --git a/kernel/paging/statistics.c b/kernel/paging/statistics.c index c340f06b307..907c0f8245c 100644 --- a/kernel/paging/statistics.c +++ b/kernel/paging/statistics.c @@ -17,6 +17,23 @@ struct k_mem_paging_histogram_t z_paging_histogram_eviction; struct k_mem_paging_histogram_t z_paging_histogram_backing_store_page_in; struct k_mem_paging_histogram_t z_paging_histogram_backing_store_page_out; +#ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS + +/* + * The frequency of timing functions is highly dependent on + * architecture, SoC or board. It is also not available at build time. + * Therefore, the bounds for the timing histograms needs to be defined + * externally to this file, and must be tailored to the platform + * being used. + */ + +extern unsigned long +z_eviction_histogram_bounds[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS]; + +extern unsigned long +z_backing_store_histogram_bounds[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS]; + +#else #define NS_TO_CYC(ns) (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000U * ns) /* @@ -53,6 +70,7 @@ z_backing_store_histogram_bounds[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS] NS_TO_CYC(10000), ULONG_MAX }; +#endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ unsigned long z_num_pagefaults_get(void)