From 6ca327d8ce1d9c98204ab7c6d62123cfd5e12dcf Mon Sep 17 00:00:00 2001 From: Shell Date: Tue, 4 Jun 2024 00:06:41 +0800 Subject: [PATCH] [smart] add CPU/thread usage tracing config (#8947) * [smart] add CPU usage tracing config This patch introduces following features: - Added CPU usage tracing functionality, enabled by default, for applications like 'top' - update time as smart independent Signed-off-by: Shell * fixup: add ump idle thread --------- Signed-off-by: Shell --- components/lwp/Kconfig | 6 +++--- components/lwp/lwp.c | 34 ---------------------------------- include/rtdef.h | 42 ++++++++++++++++++++++++++++-------------- src/Kconfig | 8 ++++++++ src/clock.c | 34 ++++++++++++++++++++++++++++++++++ src/idle.c | 6 ++++-- 6 files changed, 77 insertions(+), 53 deletions(-) diff --git a/components/lwp/Kconfig b/components/lwp/Kconfig index 16b23c4dd7..b42dfa585d 100644 --- a/components/lwp/Kconfig +++ b/components/lwp/Kconfig @@ -12,9 +12,9 @@ if RT_USING_LWP if LWP_DEBUG config LWP_DEBUG_INIT - select RT_USING_HOOKLIST - bool "Enable debug mode of init process" - default n + select RT_USING_HOOKLIST + bool "Enable debug mode of init process" + default n endif config RT_LWP_MAX_NR diff --git a/components/lwp/lwp.c b/components/lwp/lwp.c index de2c3b5133..e8092226ca 100644 --- a/components/lwp/lwp.c +++ b/components/lwp/lwp.c @@ -686,37 +686,3 @@ rt_err_t lwp_backtrace_frame(rt_thread_t uthread, struct rt_hw_backtrace_frame * } return rc; } - -void rt_update_process_times(void) -{ - struct rt_thread *thread; -#ifdef RT_USING_SMP - struct rt_cpu* pcpu; - - pcpu = rt_cpu_self(); -#endif - - thread = rt_thread_self(); - - if (!IS_USER_MODE(thread)) - { - thread->user_time += 1; -#ifdef RT_USING_SMP - pcpu->cpu_stat.user += 1; -#endif - } - else - { - thread->system_time += 1; -#ifdef RT_USING_SMP - if (thread == pcpu->idle_thread) - { - pcpu->cpu_stat.idle += 1; - } - else - { - pcpu->cpu_stat.system += 1; - } -#endif - } -} diff --git a/include/rtdef.h b/include/rtdef.h index 3e48a137f6..26a1647ee6 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -701,6 +701,18 @@ enum #define RT_THREAD_CTRL_INFO 0x03 /**< Get thread information. */ #define RT_THREAD_CTRL_BIND_CPU 0x04 /**< Set thread bind cpu. */ +/** + * CPU usage statistics data + */ +struct rt_cpu_usage_stats +{ + rt_ubase_t user; + rt_ubase_t system; + rt_ubase_t irq; + rt_ubase_t idle; +}; +typedef struct rt_cpu_usage_stats *rt_cpu_usage_stats_t; + #ifdef RT_USING_SMP #define RT_CPU_DETACHED RT_CPUS_NR /**< The thread not running on cpu. */ @@ -714,15 +726,6 @@ enum #define RT_STOP_IPI 1 #endif /* RT_STOP_IPI */ -struct rt_cpu_usage_stats -{ - rt_uint64_t user; - rt_uint64_t system; - rt_uint64_t irq; - rt_uint64_t idle; -}; -typedef struct rt_cpu_usage_stats *rt_cpu_usage_stats_t; - #define _SCHEDULER_CONTEXT(fileds) fileds /** @@ -762,14 +765,21 @@ struct rt_cpu #ifdef RT_USING_SMART struct rt_spinlock spinlock; +#endif /* RT_USING_SMART */ +#ifdef RT_USING_CPU_USAGE_TRACER struct rt_cpu_usage_stats cpu_stat; -#endif +#endif /* RT_USING_CPU_USAGE_TRACER */ }; #else /* !RT_USING_SMP */ struct rt_cpu { struct rt_thread *current_thread; + struct rt_thread *idle_thread; + +#ifdef RT_USING_CPU_USAGE_TRACER + struct rt_cpu_usage_stats cpu_stat; +#endif /* RT_USING_CPU_USAGE_TRACER */ }; #endif /* RT_USING_SMP */ @@ -947,9 +957,6 @@ struct rt_thread void *susp_recycler; /**< suspended recycler on this thread */ void *robust_list; /**< pi lock, very carefully, it's a userspace list!*/ - rt_uint64_t user_time; - rt_uint64_t system_time; - #ifndef ARCH_MM_MMU lwp_sighandler_t signal_handler[32]; #else @@ -963,6 +970,11 @@ struct rt_thread #endif /* ARCH_MM_MMU */ #endif /* RT_USING_SMART */ +#ifdef RT_USING_CPU_USAGE_TRACER + rt_ubase_t user_time; /**< Ticks on user */ + rt_ubase_t system_time; /**< Ticks on system */ +#endif /* RT_USING_CPU_USAGE_TRACER */ + #ifdef RT_USING_MEM_PROTECTION void *mem_regions; #ifdef RT_USING_HW_STACK_GUARD @@ -976,7 +988,9 @@ struct rt_thread typedef struct rt_thread *rt_thread_t; #ifdef RT_USING_SMART -#define IS_USER_MODE(t) ((t)->user_ctx.ctx == RT_NULL) +#define LWP_IS_USER_MODE(t) ((t)->user_ctx.ctx == RT_NULL) +#else +#define LWP_IS_USER_MODE(t) (0) #endif /* RT_USING_SMART */ /**@}*/ diff --git a/src/Kconfig b/src/Kconfig index 1d4c0489d7..0443366051 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -183,6 +183,14 @@ if RT_USING_TIMER_SOFT default 512 endif +config RT_USING_CPU_USAGE_TRACER + select RT_USING_HOOK + bool "Enable cpu usage tracing" + help + Enable cpu usage tracer for application like top. + default y if RT_USING_SMART + default n + menu "kservice optimization" config RT_USING_TINY_FFS bool "Enable kservice to use tiny finding first bit set method" diff --git a/src/clock.c b/src/clock.c index c2fe321c33..6a2366a0ac 100644 --- a/src/clock.c +++ b/src/clock.c @@ -79,6 +79,36 @@ void rt_tick_set(rt_tick_t tick) rt_atomic_store(&(rt_tick), tick); } +#ifdef RT_USING_CPU_USAGE_TRACER +static void _update_process_times(void) +{ + struct rt_thread *thread = rt_thread_self(); + struct rt_cpu *pcpu = rt_cpu_self(); + + if (!LWP_IS_USER_MODE(thread)) + { + thread->user_time += 1; + pcpu->cpu_stat.user += 1; + } + else + { + thread->system_time += 1; + if (thread == pcpu->idle_thread) + { + pcpu->cpu_stat.idle += 1; + } + else + { + pcpu->cpu_stat.system += 1; + } + } +} + +#else + +#define _update_process_times() +#endif /* RT_USING_CPU_USAGE_TRACER */ + /** * @brief This function will notify kernel there is one tick passed. * Normally, this function is invoked by clock ISR. @@ -88,6 +118,10 @@ void rt_tick_increase(void) RT_ASSERT(rt_interrupt_get_nest() > 0); RT_OBJECT_HOOK_CALL(rt_tick_hook, ()); + + /* tracing cpu usage */ + _update_process_times(); + /* increase the global tick */ #ifdef RT_USING_SMP /* get percpu and increase the tick */ diff --git a/src/idle.c b/src/idle.c index 26b559b70e..0447de79b3 100644 --- a/src/idle.c +++ b/src/idle.c @@ -346,9 +346,11 @@ void rt_thread_idle_init(void) 32); #ifdef RT_USING_SMP rt_thread_control(&idle_thread[i], RT_THREAD_CTRL_BIND_CPU, (void*)i); - - rt_cpu_index(i)->idle_thread = &idle_thread[i]; #endif /* RT_USING_SMP */ + + /* update */ + rt_cpu_index(i)->idle_thread = &idle_thread[i]; + /* startup */ rt_thread_startup(&idle_thread[i]); }