misc/assert: add backtrace dump support for mutex hold task

Signed-off-by: fangpeina <fangpeina@xiaomi.com>
This commit is contained in:
fangpeina
2024-06-18 14:24:51 +08:00
committed by Xiang Xiao
parent f7f8f6c104
commit b5145c528e
4 changed files with 91 additions and 26 deletions
+3
View File
@@ -49,6 +49,9 @@ struct mutex_s
{ {
sem_t sem; sem_t sem;
pid_t holder; pid_t holder;
#if CONFIG_LIBC_MUTEX_BACKTRACE > 0
FAR void *backtrace[CONFIG_LIBC_MUTEX_BACKTRACE];
#endif
}; };
typedef struct mutex_s mutex_t; typedef struct mutex_s mutex_t;
+7
View File
@@ -132,3 +132,10 @@ config LIBC_PATHBUFFER_MALLOC
default y default y
---help--- ---help---
Enable malloc path buffer from the heap when pathbuffer is insufficient. Enable malloc path buffer from the heap when pathbuffer is insufficient.
config LIBC_MUTEX_BACKTRACE
int "The depth of mutex backtrace"
default 0
---help---
Config the depth of backtrace, dumping the backtrace of thread which
last acquired the mutex. Disable mutex backtrace by 0.
+33
View File
@@ -59,6 +59,35 @@ static bool nxmutex_is_reset(FAR mutex_t *mutex)
return mutex->holder == NXMUTEX_RESET; return mutex->holder == NXMUTEX_RESET;
} }
/****************************************************************************
* Name: nxmutex_add_backtrace
*
* Description:
* This function add the backtrace of the holder of the mutex.
*
* Parameters:
* mutex - mutex descriptor.
*
* Return Value:
*
****************************************************************************/
#if CONFIG_LIBC_MUTEX_BACKTRACE > 0
static void nxmutex_add_backtrace(FAR mutex_t *mutex)
{
int n;
n = sched_backtrace(mutex->holder, mutex->backtrace,
CONFIG_LIBC_MUTEX_BACKTRACE, 0);
if (n < CONFIG_LIBC_MUTEX_BACKTRACE)
{
mutex->backtrace[n] = NULL;
}
}
#else
# define nxmutex_add_backtrace(mutex)
#endif
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@@ -225,6 +254,7 @@ int nxmutex_lock(FAR mutex_t *mutex)
if (ret >= 0) if (ret >= 0)
{ {
mutex->holder = _SCHED_GETTID(); mutex->holder = _SCHED_GETTID();
nxmutex_add_backtrace(mutex);
break; break;
} }
else if (ret != -EINTR && ret != -ECANCELED) else if (ret != -EINTR && ret != -ECANCELED)
@@ -268,6 +298,8 @@ int nxmutex_trylock(FAR mutex_t *mutex)
} }
mutex->holder = _SCHED_GETTID(); mutex->holder = _SCHED_GETTID();
nxmutex_add_backtrace(mutex);
return ret; return ret;
} }
@@ -319,6 +351,7 @@ int nxmutex_clocklock(FAR mutex_t *mutex, clockid_t clockid,
if (ret >= 0) if (ret >= 0)
{ {
mutex->holder = _SCHED_GETTID(); mutex->holder = _SCHED_GETTID();
nxmutex_add_backtrace(mutex);
} }
return ret; return ret;
+29 -7
View File
@@ -49,6 +49,7 @@
#include <assert.h> #include <assert.h>
#include <debug.h> #include <debug.h>
#include <execinfo.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -170,10 +171,10 @@ static void stack_dump(uintptr_t sp, uintptr_t stack_top)
} }
/**************************************************************************** /****************************************************************************
* Name: dump_stack * Name: dump_stackinfo
****************************************************************************/ ****************************************************************************/
static void dump_stack(FAR const char *tag, uintptr_t sp, static void dump_stackinfo(FAR const char *tag, uintptr_t sp,
uintptr_t base, size_t size, size_t used) uintptr_t base, size_t size, size_t used)
{ {
uintptr_t top = base + size; uintptr_t top = base + size;
@@ -272,7 +273,7 @@ static void dump_stacks(FAR struct tcb_s *rtcb, uintptr_t sp)
#if CONFIG_ARCH_INTERRUPTSTACK > 0 #if CONFIG_ARCH_INTERRUPTSTACK > 0
if (intstack_sp != 0 || force) if (intstack_sp != 0 || force)
{ {
dump_stack("IRQ", dump_stackinfo("IRQ",
intstack_sp, intstack_sp,
intstack_base, intstack_base,
intstack_size, intstack_size,
@@ -298,18 +299,17 @@ static void dump_stacks(FAR struct tcb_s *rtcb, uintptr_t sp)
#ifdef CONFIG_ARCH_KERNEL_STACK #ifdef CONFIG_ARCH_KERNEL_STACK
if (kernelstack_sp != 0 || force) if (kernelstack_sp != 0 || force)
{ {
dump_stack("Kernel", dump_stackinfo("Kernel",
kernelstack_sp, kernelstack_sp,
kernelstack_base, kernelstack_base,
kernelstack_size, kernelstack_size,
0 0);
);
} }
#endif #endif
if (tcbstack_sp != 0 || force) if (tcbstack_sp != 0 || force)
{ {
dump_stack("User", dump_stackinfo("User",
tcbstack_sp, tcbstack_sp,
tcbstack_base, tcbstack_base,
tcbstack_size, tcbstack_size,
@@ -531,6 +531,27 @@ static void dump_tasks(void)
#endif #endif
} }
/****************************************************************************
* Name: dump_lockholder
****************************************************************************/
#if CONFIG_LIBC_MUTEX_BACKTRACE > 0
static void dump_lockholder(pid_t tid)
{
char buf[CONFIG_LIBC_MUTEX_BACKTRACE * BACKTRACE_PTR_FMT_WIDTH + 1] = "";
FAR mutex_t *mutex;
mutex = (FAR mutex_t *)nxsched_get_tcb(tid)->waitobj;
backtrace_format(buf, sizeof(buf), mutex->backtrace,
CONFIG_LIBC_MUTEX_BACKTRACE);
_alert("Mutex holder(%d) backtrace:%s\n", mutex->holder, buf);
}
#else
# define dump_lockholder(tid)
#endif
/**************************************************************************** /****************************************************************************
* Name: dump_deadlock * Name: dump_deadlock
****************************************************************************/ ****************************************************************************/
@@ -548,6 +569,7 @@ static void dump_deadlock(void)
{ {
# ifdef CONFIG_SCHED_BACKTRACE # ifdef CONFIG_SCHED_BACKTRACE
sched_dumpstack(deadlock[i]); sched_dumpstack(deadlock[i]);
dump_lockholder(deadlock[i]);
# else # else
_alert("deadlock pid: %d\n", deadlock[i]); _alert("deadlock pid: %d\n", deadlock[i]);
# endif # endif