Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions components/finsh/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]));
Expand All @@ -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*/

Expand Down Expand Up @@ -243,24 +248,34 @@ 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
/ thread->stack_size,
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
}
}
Expand Down
3 changes: 3 additions & 0 deletions include/rtthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 5 additions & 3 deletions src/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 47 additions & 0 deletions src/kservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Comment on lines +576 to +578
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential integer overflow in multiplication operation. / 乘法操作可能存在整数溢出。

English: The multiplication thread_time * 100U could overflow if thread_time is large. Consider using 64-bit arithmetic or checking for overflow before multiplication to prevent incorrect results.
中文:如果 thread_time 很大,乘法操作 thread_time * 100U 可能会溢出。建议使用 64 位算术或在乘法前检查溢出,以防止错误结果。

Example/示例:

rt_uint64_t usage64 = ((rt_uint64_t)thread_time * 100U) / total_time;
rt_ubase_t usage = (rt_ubase_t)(usage64 > 100U ? 100U : usage64);
Suggested change
/* 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);
/* Calculate thread usage percentage: (thread_time * 100) / total_time, using 64-bit arithmetic to avoid overflow */
rt_uint64_t usage64 = ((rt_uint64_t)thread_time * 100U) / total_time;
rt_ubase_t usage = (rt_ubase_t)(usage64 > 100U ? 100U : usage64);
return (rt_uint8_t)usage;

Copilot uses AI. Check for mistakes.
}

return 0U;
}
#endif /* RT_USING_CPU_USAGE_TRACER */

#if defined(RT_USING_LIBC) && defined(RT_USING_FINSH)
#include <stdlib.h> /* for string service */

Expand Down
Loading