diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index 4a45f1ed9c..0a04aec23c 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -792,9 +792,10 @@ static ssize_t proc_critmon(FAR struct proc_file_s *procfile, /* Generate output for maximum time pre-emption disabled */ - linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu,", + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu %p,", (unsigned long)maxtime.tv_sec, - (unsigned long)maxtime.tv_nsec); + (unsigned long)maxtime.tv_nsec, + tcb->premp_max_caller); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); @@ -827,9 +828,10 @@ static ssize_t proc_critmon(FAR struct proc_file_s *procfile, /* Generate output for maximum time in a critical section */ - linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu,", + linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%lu.%09lu %p,", (unsigned long)maxtime.tv_sec, - (unsigned long)maxtime.tv_nsec); + (unsigned long)maxtime.tv_nsec, + tcb->crit_max_caller); copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining, &offset); diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index e78a16ce80..bf844ed7ed 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -663,11 +663,15 @@ struct tcb_s #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 clock_t premp_start; /* Time when preemption disabled */ clock_t premp_max; /* Max time preemption disabled */ + void *premp_caller; /* Caller of preemption disabled */ + void *premp_max_caller; /* Caller of max preemption */ #endif #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 clock_t crit_start; /* Time critical section entered */ clock_t crit_max; /* Max time in critical section */ + void *crit_caller; /* Caller of critical section */ + void *crit_max_caller; /* Caller of max critical section */ #endif /* State save areas *******************************************************/ diff --git a/sched/irq/irq_csection.c b/sched/irq/irq_csection.c index 7209ddc87b..3397741a76 100644 --- a/sched/irq/irq_csection.c +++ b/sched/irq/irq_csection.c @@ -383,7 +383,7 @@ try_again_in_irq: /* Note that we have entered the critical section */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 - nxsched_critmon_csection(rtcb, true); + nxsched_critmon_csection(rtcb, true, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION sched_note_csection(rtcb, true); @@ -423,7 +423,7 @@ irqstate_t enter_critical_section(void) /* Note that we have entered the critical section */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 - nxsched_critmon_csection(rtcb, true); + nxsched_critmon_csection(rtcb, true, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION sched_note_csection(rtcb, true); @@ -524,7 +524,7 @@ void leave_critical_section(irqstate_t flags) /* No.. Note that we have left the critical section */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 - nxsched_critmon_csection(rtcb, false); + nxsched_critmon_csection(rtcb, false, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION sched_note_csection(rtcb, false); @@ -578,7 +578,7 @@ void leave_critical_section(irqstate_t flags) /* Note that we have left the critical section */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 - nxsched_critmon_csection(rtcb, false); + nxsched_critmon_csection(rtcb, false, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION sched_note_csection(rtcb, false); diff --git a/sched/sched/sched.h b/sched/sched/sched.h index 64abe7ba98..79c01eeada 100644 --- a/sched/sched/sched.h +++ b/sched/sched/sched.h @@ -447,11 +447,13 @@ void nxsched_suspend_critmon(FAR struct tcb_s *tcb); #endif #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 -void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state); +void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state, + FAR void *caller); #endif #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 -void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state); +void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state, + FAR void *caller); #endif /* TCB operations */ diff --git a/sched/sched/sched_critmonitor.c b/sched/sched/sched_critmonitor.c index 72b9cf1669..16ae7287fe 100644 --- a/sched/sched/sched_critmonitor.c +++ b/sched/sched/sched_critmonitor.c @@ -180,11 +180,13 @@ static void nxsched_critmon_cpuload(FAR struct tcb_s *tcb, clock_t current, * Assumptions: * - Called within a critical section. * - Never called from an interrupt handler + * - Caller is the address of the function that is changing the pre-emption * ****************************************************************************/ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 -void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state) +void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state, + FAR void *caller) { int cpu = this_cpu(); @@ -195,6 +197,7 @@ void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state) /* Disabling.. Save the thread start time */ tcb->premp_start = perf_gettime(); + tcb->premp_caller = caller; g_premp_start[cpu] = tcb->premp_start; } else @@ -206,7 +209,8 @@ void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state) if (elapsed > tcb->premp_max) { - tcb->premp_max = elapsed; + tcb->premp_max = elapsed; + tcb->premp_max_caller = tcb->premp_caller; CHECK_PREEMPTION(tcb->pid, elapsed); } @@ -230,11 +234,13 @@ void nxsched_critmon_preemption(FAR struct tcb_s *tcb, bool state) * Assumptions: * - Called within a critical section. * - Never called from an interrupt handler + * - Caller is the address of the function that is entering the critical * ****************************************************************************/ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_CSECTION >= 0 -void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state) +void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state, + FAR void *caller) { int cpu = this_cpu(); @@ -245,6 +251,7 @@ void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state) /* Entering... Save the start time. */ tcb->crit_start = perf_gettime(); + tcb->crit_caller = caller; g_crit_start[cpu] = tcb->crit_start; } else @@ -256,7 +263,8 @@ void nxsched_critmon_csection(FAR struct tcb_s *tcb, bool state) if (elapsed > tcb->crit_max) { - tcb->crit_max = elapsed; + tcb->crit_max = elapsed; + tcb->crit_max_caller = tcb->crit_caller; CHECK_CSECTION(tcb->pid, elapsed); } @@ -386,7 +394,8 @@ void nxsched_suspend_critmon(FAR struct tcb_s *tcb) elapsed = current - tcb->premp_start; if (elapsed > tcb->premp_max) { - tcb->premp_max = elapsed; + tcb->premp_max = elapsed; + tcb->premp_max_caller = tcb->premp_caller; CHECK_PREEMPTION(tcb->pid, elapsed); } } @@ -401,7 +410,8 @@ void nxsched_suspend_critmon(FAR struct tcb_s *tcb) elapsed = current - tcb->crit_start; if (elapsed > tcb->crit_max) { - tcb->crit_max = elapsed; + tcb->crit_max = elapsed; + tcb->crit_max_caller = tcb->crit_caller; CHECK_CSECTION(tcb->pid, elapsed); } } diff --git a/sched/sched/sched_lock.c b/sched/sched/sched_lock.c index 692eaa0d8e..0833b5746b 100644 --- a/sched/sched/sched_lock.c +++ b/sched/sched/sched_lock.c @@ -159,10 +159,10 @@ int sched_lock(void) /* Note that we have pre-emption locked */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 - nxsched_critmon_preemption(rtcb, true); + nxsched_critmon_preemption(rtcb, true, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION - sched_note_premption(rtcb, true); + sched_note_premption(rtcb, true); #endif } @@ -213,7 +213,7 @@ int sched_lock(void) /* Note that we have pre-emption locked */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 - nxsched_critmon_preemption(rtcb, true); + nxsched_critmon_preemption(rtcb, true, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION sched_note_premption(rtcb, true); diff --git a/sched/sched/sched_unlock.c b/sched/sched/sched_unlock.c index 2f53774f34..0c42dd6be3 100644 --- a/sched/sched/sched_unlock.c +++ b/sched/sched/sched_unlock.c @@ -93,7 +93,7 @@ int sched_unlock(void) /* Note that we no longer have pre-emption disabled. */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 - nxsched_critmon_preemption(rtcb, false); + nxsched_critmon_preemption(rtcb, false, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION sched_note_premption(rtcb, false); @@ -250,7 +250,7 @@ int sched_unlock(void) /* Note that we no longer have pre-emption disabled. */ #if CONFIG_SCHED_CRITMONITOR_MAXTIME_PREEMPTION >= 0 - nxsched_critmon_preemption(rtcb, false); + nxsched_critmon_preemption(rtcb, false, return_address(0)); #endif #ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION sched_note_premption(rtcb, false);