sched: add CONFIG_SCHED_CRITMONITOR_XX for debugging system lantency

Change-Id: Id2a75db28caf1a89552e33391bd90f85cde08dbd
Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd
2021-04-29 19:41:27 +08:00
committed by liuhaitao
parent 74d29cf864
commit 534d1bb3d2
5 changed files with 160 additions and 2 deletions
+52
View File
@@ -736,6 +736,58 @@ config SCHED_CRITMONITOR
The second interface simply converts an elapsed time into well known
units for presentation by the ProcFS file system.
if SCHED_CRITMONITOR
config SCHED_CRITMONITOR_MAXTIME_THREAD
int "THREAD max execution time"
default 0
---help---
Thread execution time should be smaller than
SCHED_CRITMONITOR_MAXTIME_THREAD, or system will give a warnning.
For debugging system lantency, 0 means disabled.
config SCHED_CRITMONITOR_MAXTIME_WQUEUE
int "WORK queue max execution time"
default SCHED_CRITMONITOR_MAXTIME_THREAD
---help---
Worker execution time should be smaller than
SCHED_CRITMONITOR_MAXTIME_WQUEUE, or system will give a warnning.
For debugging system lantency, 0 means disabled.
config SCHED_CRITMONITOR_MAXTIME_PREEMPTION
int "Pre-emption (sched_lock) max holding time"
default SCHED_CRITMONITOR_MAXTIME_WQUEUE
---help---
Pre-emption holding time should be smaller than
SCHED_CRITMONITOR_MAXTIME_PREEMPTION, or system will give a warnning.
For debugging system lantency, 0 means disabled.
config SCHED_CRITMONITOR_MAXTIME_CSECTION
int "Csection (enter_critical_section) max holding time"
default SCHED_CRITMONITOR_MAXTIME_PREEMPTION
---help---
Csection holding time should be smaller than
SCHED_CRITMONITOR_MAXTIME_CSECTION, or system will give a warnning.
For debugging system lantency, 0 means disabled.
config SCHED_CRITMONITOR_MAXTIME_IRQ
int "IRQ max execution time"
default SCHED_CRITMONITOR_MAXTIME_CSECTION
---help---
IRQ handler execution time should be smaller than
SCHED_CRITMONITOR_MAXTIME_IRQ, or system will give a warnning.
For debugging system lantency, 0 means disabled.
config SCHED_CRITMONITOR_MAXTIME_WDOG
int "WDOG callback max execution time"
default SCHED_CRITMONITOR_MAXTIME_IRQ
---help---
Wdog callback execution time should be smaller than
SCHED_CRITMONITOR_MAXTIME_WDOG, or system will give a warnning.
For debugging system lantency, 0 means disabled.
endif # SCHED_CRITMONITOR
config SCHED_CPULOAD
bool "Enable CPU load monitoring"
default n
+6
View File
@@ -83,6 +83,12 @@
{ \
g_irqvector[ndx].time = delta.tv_nsec; \
} \
if (CONFIG_SCHED_CRITMONITOR_MAXTIME_IRQ > 0 && \
elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_IRQ) \
{ \
serr("IRQ %d(%p), execute time too long %"PRIu32"\n", \
irq, vector, elapsed); \
} \
} \
while (0)
#else
+59
View File
@@ -31,6 +31,58 @@
#ifdef CONFIG_SCHED_CRITMONITOR
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION > 0
# define CHECK_PREEMPTION(pid, elapsed) \
do \
{ \
if (pid > 0 && \
elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION) \
{ \
serr("PID %d hold sched lock too long %"PRIu32"\n", \
pid, elapsed); \
} \
} \
while (0)
#else
# define CHECK_PREEMPTION(pid, elapsed)
#endif
#if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION > 0
# define CHECK_CSECTION(pid, elapsed) \
do \
{ \
if (pid > 0 && \
elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION) \
{ \
serr("PID %d hold critical section too long %"PRIu32"\n", \
pid, elapsed); \
} \
} \
while (0)
#else
# define CHECK_CSECTION(pid, elapsed)
#endif
#if CONFIG_SCHED_CRITMONITOR_MAXTIME_THREAD > 0
# define CHECK_THREAD(pid, elapsed) \
do \
{ \
if (pid > 0 && \
elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_THREAD) \
{ \
serr("PID %d execute too long %"PRIu32"\n", \
pid, elapsed); \
} \
} \
while (0)
#else
# define CHECK_THREAD(pid, elapsed)
#endif
/****************************************************************************
* Private Data
****************************************************************************/
@@ -111,6 +163,7 @@ void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state)
if (elapsed > tcb->premp_max)
{
tcb->premp_max = elapsed;
CHECK_PREEMPTION(tcb->pid, elapsed);
}
/* Check for the global max elapsed time */
@@ -175,6 +228,7 @@ void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state)
if (elapsed > tcb->crit_max)
{
tcb->crit_max = elapsed;
CHECK_CSECTION(tcb->pid, elapsed);
}
/* Check for the global max elapsed time */
@@ -242,6 +296,7 @@ void nxsched_resume_critmon(FAR struct tcb_s *tcb)
if (elapsed > g_premp_max[cpu])
{
g_premp_max[cpu] = elapsed;
CHECK_PREEMPTION(tcb->pid, elapsed);
}
}
@@ -269,6 +324,7 @@ void nxsched_resume_critmon(FAR struct tcb_s *tcb)
if (elapsed > g_crit_max[cpu])
{
g_crit_max[cpu] = elapsed;
CHECK_CSECTION(tcb->pid, elapsed);
}
}
}
@@ -295,6 +351,7 @@ void nxsched_suspend_critmon(FAR struct tcb_s *tcb)
if (elapsed > tcb->run_max)
{
tcb->run_max = elapsed;
CHECK_THREAD(tcb->pid, elapsed);
}
/* Did this task disable preemption? */
@@ -309,6 +366,7 @@ void nxsched_suspend_critmon(FAR struct tcb_s *tcb)
if (elapsed > tcb->premp_max)
{
tcb->premp_max = elapsed;
CHECK_PREEMPTION(tcb->pid, elapsed);
}
}
@@ -324,6 +382,7 @@ void nxsched_suspend_critmon(FAR struct tcb_s *tcb)
if (elapsed > tcb->crit_max)
{
tcb->crit_max = elapsed;
CHECK_CSECTION(tcb->pid, elapsed);
}
}
}
+21 -1
View File
@@ -50,6 +50,26 @@
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#if CONFIG_SCHED_CRITMONITOR_MAXTIME_WDOG > 0
# define CALL_FUNC(func, arg) \
do \
{ \
uint32_t start; \
uint32_t elapsed; \
start = up_critmon_gettime(); \
func(arg); \
elapsed = up_critmon_gettime() - start; \
if (elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_WDOG) \
{ \
serr("WDOG %p, %s IRQ, execute too long %"PRIu32"\n", \
func, up_interrupt_context() ? "IN" : "NOT", elapsed); \
} \
} \
while (0)
#else
# define CALL_FUNC(func, arg) func(arg)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -104,7 +124,7 @@ static inline void wd_expiration(void)
/* Execute the watchdog function */
up_setpicbase(wdog->picbase);
wdog->func(wdog->arg);
CALL_FUNC(wdog->func, wdog->arg);
}
}
}
+22 -1
View File
@@ -24,6 +24,7 @@
#include <nuttx/config.h>
#include <debug.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>
@@ -63,6 +64,26 @@
# define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#if CONFIG_SCHED_CRITMONITOR_MAXTIME_WQUEUE > 0
# define CALL_WORKER(worker, arg) \
do \
{ \
uint32_t start; \
uint32_t elapsed; \
start = up_critmon_gettime(); \
worker(arg); \
elapsed = up_critmon_gettime() - start; \
if (elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_WQUEUE) \
{ \
serr("WORKER %p execute too long %"PRIu32"\n", \
worker, elapsed); \
} \
} \
while (0)
#else
# define CALL_WORKER(worker, arg) worker(arg)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -154,7 +175,7 @@ void work_process(FAR struct kwork_wqueue_s *wqueue, int wndx)
*/
leave_critical_section(flags);
worker(arg);
CALL_WORKER(worker, arg);
/* Now, unfortunately, since we re-enabled interrupts we don't
* know the state of the work list and we will have to start