diff --git a/src/kservice.c b/src/kservice.c index 5a5ea24331d..c37509cb623 100644 --- a/src/kservice.c +++ b/src/kservice.c @@ -747,10 +747,64 @@ rt_uint8_t rt_thread_get_usage(rt_thread_t thread) #if defined(RT_USING_LIBC) && defined(RT_USING_FINSH) #include /* for string service */ -static void cmd_backtrace(int argc, char** argv) +struct cmd_backtrace_find_ctx { rt_uintptr_t pid; + rt_thread_t thread; +}; + +static rt_err_t cmd_backtrace_match_thread(struct rt_object *object, void *data) +{ + struct cmd_backtrace_find_ctx *ctx = data; + + if ((rt_uintptr_t)object == ctx->pid) + { + ctx->thread = (rt_thread_t)object; + + return 1; + } + + return RT_EOK; +} + +static rt_bool_t cmd_backtrace_parse_pid(const char *arg, rt_uintptr_t *pid) +{ char *end_ptr; + rt_uintptr_t value; + + if ((arg == RT_NULL) || (pid == RT_NULL)) + { + return RT_FALSE; + } + + value = (rt_uintptr_t)strtoul(arg, &end_ptr, 0); + if ((end_ptr == arg) || (*end_ptr != '\0') || (value == 0)) + { + return RT_FALSE; + } + + *pid = value; + + return RT_TRUE; +} + +static rt_thread_t cmd_backtrace_find_thread(rt_uintptr_t pid) +{ + struct cmd_backtrace_find_ctx ctx = + { + .pid = pid, + .thread = RT_NULL, + }; + + rt_object_for_each(RT_Object_Class_Thread, cmd_backtrace_match_thread, &ctx); + + return ctx.thread; +} + +static void cmd_backtrace(int argc, char** argv) +{ + rt_uintptr_t pid; + rt_thread_t target; if (argc != 2) { @@ -770,21 +824,22 @@ static void cmd_backtrace(int argc, char** argv) } } - pid = strtoul(argv[1], &end_ptr, 0); - if (end_ptr == argv[1]) + if (!cmd_backtrace_parse_pid(argv[1], &pid)) { rt_kprintf("Invalid input: %s\n", argv[1]); return ; } - if (pid && rt_object_get_type((void *)pid) == RT_Object_Class_Thread) + target = cmd_backtrace_find_thread(pid); + if (target != RT_NULL) { - rt_thread_t target = (rt_thread_t)pid; - rt_kprintf("backtrace %s(0x%lx), from %s\n", target->parent.name, pid, argv[1]); + rt_kprintf("backtrace %s(0x%lx), from %s\n", target->parent.name, (unsigned long)pid, argv[1]); rt_backtrace_thread(target); } else - rt_kprintf("Invalid pid: %ld\n", pid); + { + rt_kprintf("Invalid pid: %lx\n", (unsigned long)pid); + } } MSH_CMD_EXPORT_ALIAS(cmd_backtrace, backtrace, print backtrace of a thread);