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

View file

@ -49,6 +49,9 @@ struct mutex_s
{
sem_t sem;
pid_t holder;
#if CONFIG_LIBC_MUTEX_BACKTRACE > 0
FAR void *backtrace[CONFIG_LIBC_MUTEX_BACKTRACE];
#endif
};
typedef struct mutex_s mutex_t;

View file

@ -132,3 +132,10 @@ config LIBC_PATHBUFFER_MALLOC
default y
---help---
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.

View file

@ -59,6 +59,35 @@ static bool nxmutex_is_reset(FAR mutex_t *mutex)
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
****************************************************************************/
@ -225,6 +254,7 @@ int nxmutex_lock(FAR mutex_t *mutex)
if (ret >= 0)
{
mutex->holder = _SCHED_GETTID();
nxmutex_add_backtrace(mutex);
break;
}
else if (ret != -EINTR && ret != -ECANCELED)
@ -268,6 +298,8 @@ int nxmutex_trylock(FAR mutex_t *mutex)
}
mutex->holder = _SCHED_GETTID();
nxmutex_add_backtrace(mutex);
return ret;
}
@ -319,6 +351,7 @@ int nxmutex_clocklock(FAR mutex_t *mutex, clockid_t clockid,
if (ret >= 0)
{
mutex->holder = _SCHED_GETTID();
nxmutex_add_backtrace(mutex);
}
return ret;

View file

@ -49,6 +49,7 @@
#include <assert.h>
#include <debug.h>
#include <execinfo.h>
#include <stdio.h>
#include <stdint.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 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 (intstack_sp != 0 || force)
{
dump_stack("IRQ",
dump_stackinfo("IRQ",
intstack_sp,
intstack_base,
intstack_size,
@ -298,18 +299,17 @@ static void dump_stacks(FAR struct tcb_s *rtcb, uintptr_t sp)
#ifdef CONFIG_ARCH_KERNEL_STACK
if (kernelstack_sp != 0 || force)
{
dump_stack("Kernel",
dump_stackinfo("Kernel",
kernelstack_sp,
kernelstack_base,
kernelstack_size,
0
);
0);
}
#endif
if (tcbstack_sp != 0 || force)
{
dump_stack("User",
dump_stackinfo("User",
tcbstack_sp,
tcbstack_base,
tcbstack_size,
@ -531,6 +531,27 @@ static void dump_tasks(void)
#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
****************************************************************************/
@ -546,11 +567,12 @@ static void dump_deadlock(void)
_alert("Deadlock detected\n");
while (i-- > 0)
{
#ifdef CONFIG_SCHED_BACKTRACE
# ifdef CONFIG_SCHED_BACKTRACE
sched_dumpstack(deadlock[i]);
#else
dump_lockholder(deadlock[i]);
# else
_alert("deadlock pid: %d\n", deadlock[i]);
#endif
# endif
}
}
}