diff --git a/arch/Kconfig b/arch/Kconfig index cba3ce3e1cd..f242466e4df 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -344,6 +344,10 @@ config ARCH_HAVE_SYSCALL_HOOKS required if CONFIG_SCHED_INSTRUMENTATION_SYSCALL is enabled. Refer to sched/Kconfig for additional information. +config ARCH_HAVE_BACKTRACE + bool + default n + config ARCH_FPU bool "FPU support" default y diff --git a/include/execinfo.h b/include/execinfo.h index 9ada133433a..0f7df0780ce 100644 --- a/include/execinfo.h +++ b/include/execinfo.h @@ -21,6 +21,31 @@ #ifndef __INCLUDE_EXECINFO_H #define __INCLUDE_EXECINFO_H +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_SCHED_BACKTRACE) + +/* Store up to SIZE return address of the current back trace in + * ARRAY and return the exact number of values stored. + */ + +#define backtrace(buffer, size) sched_backtrace(gettid(), buffer, size) +#define dump_stack() sched_dumpstack(gettid()) + +#else +# define backtrace(buffer, size) 0 +# define dump_stack() +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -34,18 +59,6 @@ extern "C" #define EXTERN extern #endif -#if defined(CONFIG_SCHED_BACKTRACE) - -/* Store up to SIZE return address of the current program state in - * ARRAY and return the exact number of values stored. - */ - -extern int backtrace(FAR void **buffer, int size); -extern void dump_stack(void); -#else -# define dump_stack() -#endif - #undef EXTERN #if defined(__cplusplus) } diff --git a/include/sched.h b/include/sched.h index 306d88abc22..842ce4d3c13 100644 --- a/include/sched.h +++ b/include/sched.h @@ -262,6 +262,11 @@ int sched_lockcount(void); bool sched_idletask(void); +/* Task Backtrace */ + +int sched_backtrace(pid_t tid, FAR void **buffer, int size); +void sched_dumpstack(pid_t tid); + #undef EXTERN #if defined(__cplusplus) } diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 17268a549a1..022c8d33fd3 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -44,6 +44,10 @@ SYSCALL_LOOKUP(sched_unlock, 0) SYSCALL_LOOKUP(sched_yield, 0) SYSCALL_LOOKUP(nxsched_get_stackinfo, 2) +#ifdef CONFIG_SCHED_BACKTRACE + SYSCALL_LOOKUP(sched_backtrace, 3) +#endif + #ifdef CONFIG_SMP SYSCALL_LOOKUP(sched_getaffinity, 3) SYSCALL_LOOKUP(sched_getcpu, 0) diff --git a/libs/libc/sched/Make.defs b/libs/libc/sched/Make.defs index ea9efa914a9..690d871ec77 100644 --- a/libs/libc/sched/Make.defs +++ b/libs/libc/sched/Make.defs @@ -35,7 +35,7 @@ CSRCS += task_startup.c endif ifeq ($(CONFIG_SCHED_BACKTRACE),y) -CSRCS += lib_dumpstack.c lib_backtrace.c +CSRCS += sched_dumpstack.c sched_backtrace.c endif # Add the sched directory to the build diff --git a/libs/libc/sched/sched_backtrace.c b/libs/libc/sched/sched_backtrace.c index 7b8671bf958..bc318cd02d3 100644 --- a/libs/libc/sched/sched_backtrace.c +++ b/libs/libc/sched/sched_backtrace.c @@ -28,6 +28,10 @@ #include #include +#include + +#if !defined(CONFIG_ARCH_HAVE_BACKTRACE) + /**************************************************************************** * Private Data Types ****************************************************************************/ @@ -95,14 +99,23 @@ backtrace_helper(FAR struct _Unwind_Context *ctx, FAR void *a) * Public Functions ****************************************************************************/ -/* Store up to SIZE return address of the current program state in - * ARRAY and return the exact number of values stored. - */ +/**************************************************************************** + * Name: sched_backtrace + * + * Description: + * Get thread backtrace from specified tid. + * + ****************************************************************************/ -int backtrace(FAR void **buffer, int size) +int sched_backtrace(pid_t tid, FAR void **buffer, int size) { struct trace_arg arg; + if (tid != gettid()) + { + return 0; + } + arg.array = buffer; arg.cfa = 0; arg.size = size; @@ -126,3 +139,5 @@ int backtrace(FAR void **buffer, int size) return arg.cnt != -1 ? arg.cnt : 0; } + +#endif /* !CONFIG_ARCH_HAVE_BACKTRACE */ diff --git a/libs/libc/sched/sched_dumpstack.c b/libs/libc/sched/sched_dumpstack.c index ca7f02df183..ad8355bfb95 100644 --- a/libs/libc/sched/sched_dumpstack.c +++ b/libs/libc/sched/sched_dumpstack.c @@ -41,7 +41,15 @@ * Public Functions ****************************************************************************/ -void dump_stack(void) +/**************************************************************************** + * Name: sched_dumpstack + * + * Description: + * Dump thread backtrace from specified tid. + * + ****************************************************************************/ + +void sched_dumpstack(pid_t tid) { FAR void *address[DUMP_DEPTH]; char line[DUMP_LINESIZE + 1]; @@ -49,7 +57,7 @@ void dump_stack(void) int size; int i; - size = backtrace(address, DUMP_DEPTH); + size = sched_backtrace(tid, address, DUMP_DEPTH); if (size <= 0) { return; @@ -61,7 +69,8 @@ void dump_stack(void) DUMP_FORMAT, DUMP_WIDTH, address[i]); if (i == size - 1 || ret % DUMP_LINESIZE == 0) { - syslog(LOG_INFO, "[CallStack %d]: %s\n", i / DUMP_NITEM, line); + syslog(LOG_INFO, "[BackTrace|%2d|%d]: %s\n", + tid, i / DUMP_NITEM, line); ret = 0; } } diff --git a/sched/sched/Make.defs b/sched/sched/Make.defs index d42d37985e8..6477f639632 100644 --- a/sched/sched/Make.defs +++ b/sched/sched/Make.defs @@ -98,6 +98,10 @@ ifeq ($(CONFIG_SCHED_CRITMONITOR),y) CSRCS += sched_critmonitor.c endif +ifeq ($(CONFIG_ARCH_HAVE_BACKTRACE),y) +CSRCS += sched_backtrace.c +endif + # Include sched build support DEPPATH += --dep-path sched diff --git a/sched/sched/sched_backtrace.c b/sched/sched/sched_backtrace.c new file mode 100644 index 00000000000..a887b7805b9 --- /dev/null +++ b/sched/sched/sched_backtrace.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * sched/sched/sched_backtrace.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "sched.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sched_backtrace + * + * Description: + * Get thread backtrace from specified tid. + * Store up to SIZE return address of the current program state in + * ARRAY and return the exact number of values stored. + * + ****************************************************************************/ + +int sched_backtrace(pid_t tid, FAR void **buffer, int size) +{ + FAR struct tcb_s *rtcb; + + if (tid < 0) + { + rtcb = running_task(); + } + else + { + rtcb = nxsched_get_tcb(tid); + } + + if (rtcb == NULL) + { + return 0; + } + + return up_backtrace(rtcb, buffer, size); +} diff --git a/syscall/syscall.csv b/syscall/syscall.csv index fdd1b98d1ee..282f6aeb202 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -134,6 +134,7 @@ "sched_setscheduler","sched.h","","int","pid_t","int","const struct sched_param *" "sched_unlock","sched.h","","int" "sched_yield","sched.h","","int" +"sched_backtrace","sched.h","defined(CONFIG_SCHED_BACKTRACE)","int","pid_t","FAR void **","int" "seekdir","dirent.h","","void","FAR DIR *","off_t" "select","sys/select.h","","int","int","FAR fd_set *","FAR fd_set *","FAR fd_set *","FAR struct timeval *" "sem_clockwait","semaphore.h","","int","FAR sem_t *","clockid_t","FAR const struct timespec *"