mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 08:38:38 +08:00
misc/assert: add backtrace dump support for mutex hold task
Signed-off-by: fangpeina <fangpeina@xiaomi.com>
This commit is contained in:
parent
f7f8f6c104
commit
b5145c528e
4 changed files with 91 additions and 26 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <execinfo.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
@ -170,11 +171,11 @@ 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,
|
||||
uintptr_t base, size_t size, size_t used)
|
||||
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,16 +273,16 @@ 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",
|
||||
intstack_sp,
|
||||
intstack_base,
|
||||
intstack_size,
|
||||
dump_stackinfo("IRQ",
|
||||
intstack_sp,
|
||||
intstack_base,
|
||||
intstack_size,
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
up_check_intstack(cpu)
|
||||
up_check_intstack(cpu)
|
||||
#else
|
||||
0
|
||||
0
|
||||
#endif
|
||||
);
|
||||
);
|
||||
|
||||
/* Try to restore SP from current_regs if assert from interrupt. */
|
||||
|
||||
|
@ -298,27 +299,26 @@ 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",
|
||||
kernelstack_sp,
|
||||
kernelstack_base,
|
||||
kernelstack_size,
|
||||
0
|
||||
);
|
||||
dump_stackinfo("Kernel",
|
||||
kernelstack_sp,
|
||||
kernelstack_base,
|
||||
kernelstack_size,
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (tcbstack_sp != 0 || force)
|
||||
{
|
||||
dump_stack("User",
|
||||
tcbstack_sp,
|
||||
tcbstack_base,
|
||||
tcbstack_size,
|
||||
dump_stackinfo("User",
|
||||
tcbstack_sp,
|
||||
tcbstack_base,
|
||||
tcbstack_size,
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
up_check_tcbstack(rtcb)
|
||||
up_check_tcbstack(rtcb)
|
||||
#else
|
||||
0
|
||||
0
|
||||
#endif
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue