diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index 7414166542..2777acd606 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -94,6 +94,8 @@ ((drv)->ops->irqhandler(drv, irq, handler, enter), true)) #define note_heap(drv, event, data, mem, size, used) \ ((drv)->ops->heap && ((drv)->ops->heap(drv, event, data, mem, size, used), true)) +#define note_wdog(drv, event, handler, arg) \ + ((drv)->ops->wdog && ((drv)->ops->wdog(drv, event, handler, arg), true)) #define note_string(drv, ip, buf) \ ((drv)->ops->string && ((drv)->ops->string(drv, ip, buf), true)) #define note_event(drv, ip, event, buf, len) \ @@ -1354,6 +1356,41 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) } #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_WDOG +void sched_note_wdog(uint8_t event, FAR void *handler, FAR const void *arg) +{ + FAR struct note_driver_s **driver; + struct note_wdog_s note; + bool formatted = false; + FAR struct tcb_s *tcb = this_task(); + + for (driver = g_note_drivers; *driver; driver++) + { + if (note_wdog(*driver, event, handler, arg)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nwd_cmn, sizeof(note), event); + note.handler = (uintptr_t)handler; + note.arg = (uintptr_t)arg; + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(note)); + } +} +#endif + #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, size_t size, size_t used) @@ -1385,7 +1422,7 @@ void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, if (!formatted) { formatted = true; - note_common(tcb, ¬e.nmm_cmn, sizeof(note), event); + note_common(tcb, ¬e.nhp_cmn, sizeof(note), event); note.heap = heap; note.mem = mem; note.size = size; diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index e9b60333ab..582cec5e73 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -901,6 +901,27 @@ static int noteram_dump_one(FAR uint8_t *p, FAR struct lib_outstream_s *s, break; #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_WDOG + case NOTE_WDOG_START: + case NOTE_WDOG_CANCEL: + case NOTE_WDOG_ENTER: + case NOTE_WDOG_LEAVE: + { + FAR struct note_wdog_s *nw; + FAR const char *name[] = + { + "start", "cancel", "enter", "leave", + }; + + nw = (FAR struct note_wdog_s *)p; + ret += noteram_dump_header(s, note, ctx); + ret += lib_sprintf(s, "tracing_mark_write: I|%d|wdog: %s-%pS %p\n", + pid, name[note->nc_type - NOTE_WDOG_START], + (FAR void *)nw->handler, (FAR void *)nw->arg); + } + break; +#endif + #ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION case NOTE_CSECTION_ENTER: case NOTE_CSECTION_LEAVE: @@ -1031,7 +1052,7 @@ static int noteram_dump_one(FAR uint8_t *p, FAR struct lib_outstream_s *s, "add", "remove", "malloc", "free" }; - ret += noteram_dump_header(s, &nmm->nmm_cmn, ctx); + ret += noteram_dump_header(s, &nmm->nhp_cmn, ctx); ret += lib_sprintf(s, "tracing_mark_write: C|%d|Heap Usage|%d|%s" ": heap: %p size:%" PRIiPTR ", address: %p\n", pid, nmm->used, diff --git a/drivers/segger/note_sysview.c b/drivers/segger/note_sysview.c index 95ded2b2eb..a00dcbe8e1 100644 --- a/drivers/segger/note_sysview.c +++ b/drivers/segger/note_sysview.c @@ -119,6 +119,9 @@ static const struct note_driver_ops_s g_note_sysview_ops = #ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER note_sysview_irqhandler, /* irqhandler */ #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_WDOG + NULL, /* wdog */ +#endif #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP note_sysview_heap, /* heap */ #endif diff --git a/include/nuttx/note/note_driver.h b/include/nuttx/note/note_driver.h index cefe5e95b3..db983570e0 100644 --- a/include/nuttx/note/note_driver.h +++ b/include/nuttx/note/note_driver.h @@ -89,6 +89,10 @@ struct note_driver_ops_s CODE void (*irqhandler)(FAR struct note_driver_s *drv, int irq, FAR void *handler, bool enter); #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_WDOG + CODE void (*wdog)(FAR struct note_driver_s *drv, uint8_t event, + FAR void *handler, FAR const void *arg); +#endif #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP CODE void (*heap)(FAR struct note_driver_s *drv, uint8_t event, FAR void *heap, FAR void *mem, size_t size, diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index b49207ccf0..0ee171a2a9 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -186,6 +186,10 @@ enum note_type_e NOTE_SYSCALL_LEAVE, NOTE_IRQ_ENTER, NOTE_IRQ_LEAVE, + NOTE_WDOG_START, + NOTE_WDOG_CANCEL, + NOTE_WDOG_ENTER, + NOTE_WDOG_LEAVE, NOTE_HEAP_ADD, NOTE_HEAP_REMOVE, NOTE_HEAP_ALLOC, @@ -384,9 +388,16 @@ struct note_irqhandler_s uint8_t nih_irq; /* IRQ number */ }; +struct note_wdog_s +{ + struct note_common_s nwd_cmn; /* Common note parameters */ + uintptr_t handler; + uintptr_t arg; +}; + struct note_heap_s { - struct note_common_s nmm_cmn; /* Common note parameters */ + struct note_common_s nhp_cmn; /* Common note parameters */ FAR void *heap; FAR void *mem; size_t size; @@ -555,6 +566,12 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter); # define sched_note_irqhandler(i,h,e) #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_WDOG +void sched_note_wdog(uint8_t event, FAR void *handler, FAR const void *arg); +#else +# define sched_note_wdog(e,h,a) +#endif + #ifdef CONFIG_SCHED_INSTRUMENTATION_HEAP void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem, size_t size, size_t used); diff --git a/sched/Kconfig b/sched/Kconfig index 1fca42e460..728f161b95 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1292,6 +1292,14 @@ config SCHED_INSTRUMENTATION_HEAP void sched_note_heap(uint8_t event, FAR void* heap, FAR void *mem, size_t size, size_t curused); +config SCHED_INSTRUMENTATION_WDOG + bool "Watchdog timer monitor hooks" + default n + ---help--- + Enables additional hooks for watchdog timer. + + void sched_note_wdog(uint8_t event, FAR void *handler, FAR const void *arg); + config SCHED_INSTRUMENTATION_DUMP bool "Use note dump for instrumentation" default n diff --git a/sched/wdog/wd_cancel.c b/sched/wdog/wd_cancel.c index 65c063cd56..538fa03e6b 100644 --- a/sched/wdog/wd_cancel.c +++ b/sched/wdog/wd_cancel.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "sched/sched.h" #include "wdog/wdog.h" @@ -95,6 +96,9 @@ int wd_cancel_irq(FAR struct wdog_s *wdog) return -EINVAL; } + sched_note_wdog(NOTE_WDOG_CANCEL, (FAR void *)wdog->func, + (FAR void *)(uintptr_t)wdog->expired); + /* Prohibit timer interactions with the timer queue until the * cancellation is complete */ diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c index fd703e6c97..739cec16a2 100644 --- a/sched/wdog/wd_start.c +++ b/sched/wdog/wd_start.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "sched/sched.h" #include "wdog/wdog.h" @@ -56,9 +57,11 @@ { \ clock_t start; \ clock_t elapsed; \ + sched_note_wdog(NOTE_WDOG_ENTER, func, (FAR void *)arg); \ start = perf_gettime(); \ func(arg); \ elapsed = perf_gettime() - start; \ + sched_note_wdog(NOTE_WDOG_LEAVE, func, (FAR void *)arg); \ if (elapsed > CONFIG_SCHED_CRITMONITOR_MAXTIME_WDOG) \ { \ CRITMONITOR_PANIC("WDOG %p, %s IRQ, execute too long %ju\n", \ @@ -68,7 +71,15 @@ } \ while (0) #else -# define CALL_FUNC(func, arg) func(arg) +# define CALL_FUNC(func, arg) \ + do \ + { \ + sched_note_wdog(NOTE_WDOG_ENTER, func, (FAR void *)arg); \ + func(arg); \ + sched_note_wdog(NOTE_WDOG_LEAVE, func, (FAR void *)arg); \ + } \ + while (0) + #endif /**************************************************************************** @@ -319,6 +330,8 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks, wd_insert(wdog, ticks, wdentry, arg); #endif leave_critical_section(flags); + + sched_note_wdog(NOTE_WDOG_START, wdentry, (FAR void *)(uintptr_t)ticks); return OK; }