diff --git a/components/finsh/cmd.c b/components/finsh/cmd.c index 9251ce4cb0..14086b83d6 100644 --- a/components/finsh/cmd.c +++ b/components/finsh/cmd.c @@ -165,6 +165,7 @@ long list_thread(void) rt_list_t *next = (rt_list_t *)RT_NULL; const char *item_title = "thread"; const size_t tcb_strlen = sizeof(void *) * 2 + 2; + const size_t usage_strlen = sizeof(void *) + 1; int maxlen; list_find_init(&find_arg, RT_Object_Class_Thread, obj_list, sizeof(obj_list) / sizeof(obj_list[0])); @@ -173,18 +174,22 @@ long list_thread(void) maxlen = RT_NAME_MAX; #ifdef RT_USING_SMP - rt_kprintf("%-*.*s cpu bind pri status sp stack size max used left tick error tcb addr\n", maxlen, maxlen, item_title); + rt_kprintf("%-*.*s cpu bind pri status sp stack size max used left tick error tcb addr usage\n", maxlen, maxlen, item_title); object_split(maxlen); rt_kprintf(" --- ---- --- ------- ---------- ---------- ------ ---------- -------"); rt_kprintf(" "); object_split(tcb_strlen); + rt_kprintf(" "); + object_split(usage_strlen); rt_kprintf("\n"); #else - rt_kprintf("%-*.*s pri status sp stack size max used left tick error tcb addr\n", maxlen, maxlen, item_title); + rt_kprintf("%-*.*s pri status sp stack size max used left tick error tcb addr usage\n", maxlen, maxlen, item_title); object_split(maxlen); rt_kprintf(" --- ------- ---------- ---------- ------ ---------- -------"); rt_kprintf(" "); object_split(tcb_strlen); + rt_kprintf(" "); + object_split(usage_strlen); rt_kprintf("\n"); #endif /*RT_USING_SMP*/ @@ -243,17 +248,22 @@ long list_thread(void) ptr = (rt_uint8_t *)thread->stack_addr + thread->stack_size - 1; while (*ptr == '#')ptr --; - rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s %p\n", + rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s %p", ((rt_ubase_t)thread->sp - (rt_ubase_t)thread->stack_addr), thread->stack_size, ((rt_ubase_t)ptr - (rt_ubase_t)thread->stack_addr) * 100 / thread->stack_size, thread->remaining_tick, rt_strerror(thread->error), thread); +#ifdef RT_USING_CPU_USAGE_TRACER + rt_kprintf(" %3d%%\n", rt_thread_get_usage(thread)); +#else + rt_kprintf(" N/A\n"); +#endif #else ptr = (rt_uint8_t *)thread->stack_addr; while (*ptr == '#') ptr ++; - rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s %p\n", + rt_kprintf(" 0x%08x 0x%08x %02d%% 0x%08x %s %p", thread->stack_size + ((rt_ubase_t)thread->stack_addr - (rt_ubase_t)thread->sp), thread->stack_size, (thread->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) thread->stack_addr)) * 100 @@ -261,6 +271,11 @@ long list_thread(void) RT_SCHED_PRIV(thread).remaining_tick, rt_strerror(thread->error), thread); +#ifdef RT_USING_CPU_USAGE_TRACER + rt_kprintf(" %3d%%\n", rt_thread_get_usage(thread)); +#else + rt_kprintf(" N/A\n"); +#endif #endif } } diff --git a/include/rtthread.h b/include/rtthread.h index d9b582ab1e..286189ca35 100644 --- a/include/rtthread.h +++ b/include/rtthread.h @@ -181,6 +181,9 @@ rt_err_t rt_thread_wakeup(rt_thread_t thread); void rt_thread_wakeup_set(struct rt_thread *thread, rt_wakeup_func_t func, void* user_data); #endif /* RT_USING_SMART */ rt_err_t rt_thread_get_name(rt_thread_t thread, char *name, rt_uint8_t name_size); +#ifdef RT_USING_CPU_USAGE_TRACER +rt_uint8_t rt_thread_get_usage(rt_thread_t thread); +#endif /* RT_USING_CPU_USAGE_TRACER */ #ifdef RT_USING_SIGNALS void rt_thread_alloc_sig(rt_thread_t tid); void rt_thread_free_sig(rt_thread_t tid); diff --git a/src/Kconfig b/src/Kconfig index 099f95e9cf..4ac6cdd8aa 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -192,10 +192,12 @@ 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 + help + Enable thread CPU usage statistics and monitoring. + This feature tracks CPU usage for each thread and provides + percentage information through the list thread command. + It will automatically integrate with the scheduler to track thread execution time. menu "kservice options" config RT_USING_TINY_FFS diff --git a/src/kservice.c b/src/kservice.c index 880e8f377d..259eac9a70 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -535,6 +535,53 @@ rt_err_t rt_backtrace_thread(rt_thread_t thread) return rc; } +#ifdef RT_USING_CPU_USAGE_TRACER +/** + * @brief Get thread usage percentage relative to total system CPU time + * + * This function calculates the CPU usage percentage of a specific thread + * relative to the total CPU time consumed by all threads in the system. + * + * @param thread Pointer to the thread object. Must not be NULL. + * + * @return The CPU usage percentage as an integer value (0-100). + * Returns 0 if total system time is 0 or if CPU usage tracing is not enabled. + * + * @note This function requires RT_USING_CPU_USAGE_TRACER to be enabled. + * @note The percentage is calculated as: (thread_time * 100) / total_system_time + * @note Due to integer arithmetic, the result is truncated and may not sum + * to exactly 100% across all threads due to rounding. + * @note If thread is NULL, an assertion will be triggered in debug builds. + */ +rt_uint8_t rt_thread_get_usage(rt_thread_t thread) +{ + rt_ubase_t thread_time; + rt_ubase_t total_time = 0U; + int i; + rt_cpu_t pcpu; + + RT_ASSERT(thread != RT_NULL); + + thread_time = thread->user_time + thread->system_time; + + /* Calculate total system time by summing all CPUs' time */ + for (i = 0; i < RT_CPUS_NR; i++) + { + pcpu = rt_cpu_index(i); + total_time += pcpu->cpu_stat.user + pcpu->cpu_stat.system + pcpu->cpu_stat.idle; + } + + if (total_time > 0U) + { + /* Calculate thread usage percentage: (thread_time * 100) / total_time */ + rt_ubase_t usage = (thread_time * 100U) / total_time; + return (rt_uint8_t)(usage > 100U ? 100U : usage); + } + + return 0U; +} +#endif /* RT_USING_CPU_USAGE_TRACER */ + #if defined(RT_USING_LIBC) && defined(RT_USING_FINSH) #include /* for string service */