From a32d14cb9c28fbea834b0b5a70d5ab2338496f6c Mon Sep 17 00:00:00 2001 From: zhanghu6 Date: Wed, 17 Nov 2021 17:23:43 +0800 Subject: [PATCH] sched note trace: and note dump note_type NOTE_DUMP_STRING API: sched_note_string sched_note_vprintf sched_note_printf note_type NOTE_DUMP_BINARY API: sched_note_dump sched_note_vbprintf sched_note_bprintf --- include/nuttx/sched_note.h | 53 ++++++ sched/Kconfig | 13 ++ sched/sched/sched_note.c | 333 +++++++++++++++++++++++++++++++++++++ 3 files changed, 399 insertions(+) diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 1271ea5033..f96901eba4 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -147,6 +147,11 @@ enum note_type_e NOTE_IRQ_ENTER = 20, NOTE_IRQ_LEAVE = 21 #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP + , + NOTE_DUMP_STRING = 22, + NOTE_DUMP_BINARY = 23 +#endif }; /* This structure provides the common header of each note */ @@ -318,6 +323,29 @@ struct note_irqhandler_s }; #endif /* CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER */ +#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP +struct note_string_s +{ + struct note_common_s nst_cmn; /* Common note parameters */ + char nst_data[1]; /* String data terminated by '\0' */ +}; + +#define SIZEOF_NOTE_STRING(n) (sizeof(struct note_string_s) + \ + (n) * sizeof(char)) + +struct note_binary_s +{ + struct note_common_s nbi_cmn; /* Common note parameters */ + uint32_t nbi_module; /* Module number */ + uint8_t nbi_event; /* Event number */ + uint8_t nbi_data[1]; /* Binary data */ +}; + +#define SIZEOF_NOTE_BINARY(n) (sizeof(struct note_binary_s) + \ + ((n) - 1) * sizeof(uint8_t)) + +#endif /* CONFIG_SCHED_INSTRUMENTATION_DUMP */ + #ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER /* This is the type of the argument passed to the NOTECTL_GETMODE and @@ -439,6 +467,25 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter); # define sched_note_irqhandler(i,h,e) #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP +void sched_note_string(FAR const char *buf); +void sched_note_dump(uint32_t module, uint8_t event, + FAR const void *buf, size_t len); +void sched_note_vprintf(FAR const char *fmt, va_list va) printflike(1, 0); +void sched_note_vbprintf(uint32_t module, uint8_t event, + FAR const char *fmt, va_list va) printflike(3, 0); +void sched_note_printf(FAR const char *fmt, ...) printflike(1, 2); +void sched_note_bprintf(uint32_t module, uint8_t event, + FAR const char *fmt, ...) printflike(3, 4); +#else +# define sched_note_string(b) +# define sched_note_dump(m,e,b,l) +# define sched_note_vprintf(f,v) +# define sched_note_vbprintf(m,e,f,v) +# define sched_note_printf(f...) +# define sched_note_bprintf(m,e,f...) +#endif /* CONFIG_SCHED_INSTRUMENTATION_DUMP */ + #if defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT) /**************************************************************************** @@ -561,6 +608,12 @@ void sched_note_filter_irq(struct note_filter_irq_s *oldf, # define sched_note_syscall_enter(n,a...) # define sched_note_syscall_leave(n,r) # define sched_note_irqhandler(i,h,e) +# define sched_note_string(b) +# define sched_note_dump(m,e,b,l) +# define sched_note_vprintf(f,v) +# define sched_note_vbprintf(m,e,f,v) +# define sched_note_printf(f...) +# define sched_note_bprintf(m,e,f...) #endif /* CONFIG_SCHED_INSTRUMENTATION */ #endif /* __INCLUDE_NUTTX_SCHED_NOTE_H */ diff --git a/sched/Kconfig b/sched/Kconfig index 29761acae1..bf111c5e45 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1038,6 +1038,19 @@ config SCHED_INSTRUMENTATION_IRQHANDLER void sched_note_irqhandler(int irq, FAR void *handler, bool enter); +config SCHED_INSTRUMENTATION_DUMP + bool "Use note dump for instrumentation" + default n + ---help--- + Use note dump for instrumentation. + + void sched_note_string(FAR const char *buf); + void sched_note_dump(uint32_t module, uint8_t event, FAR const void *buf, size_t len); + void sched_note_vprintf(FAR const char *fmt, va_list va); + void sched_note_vbprintf(uint32_t module, uint8_t event, FAR const char *fmt, va_list va); + void sched_note_printf(FAR const char *fmt, ...) printflike(1, 2); + void sched_note_bprintf(uint32_t module, uint8_t event, FAR const char *fmt, ...); + config SCHED_INSTRUMENTATION_HIRES bool "Use Hi-Res RTC for instrumentation" default n diff --git a/sched/sched/sched_note.c b/sched/sched/sched_note.c index 59b7f7abf7..b40db72463 100644 --- a/sched/sched/sched_note.c +++ b/sched/sched/sched_note.c @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -39,6 +40,18 @@ #include "sched/sched.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_LIBC_LONG_LONG is not a valid selection of the compiler does not + * support long long types. + */ + +#ifndef CONFIG_HAVE_LONG_LONG +# undef CONFIG_LIBC_LONG_LONG +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -789,6 +802,326 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) } #endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP +void sched_note_string(FAR const char *buf) +{ + FAR struct note_string_s *note; + uint8_t data[255]; + unsigned int length; + FAR struct tcb_s *tcb = this_task(); + + if (!note_isenabled()) + { + return; + } + + note = (FAR struct note_string_s *)data; + length = SIZEOF_NOTE_STRING(strlen(buf)); + if (length > sizeof(data)) + { + length = sizeof(data); + } + + /* Format the note */ + + note_common(tcb, ¬e->nst_cmn, length, + NOTE_DUMP_STRING); + + memcpy(note->nst_data, buf, length - sizeof(struct note_string_s)); + data[length - 1] = '\0'; + + /* Add the note to circular buffer */ + + sched_note_add(note, length); +} + +void sched_note_dump(uint32_t module, uint8_t event, + FAR const void *buf, size_t len) +{ + FAR struct note_binary_s *note; + char data[255]; + unsigned int length; + FAR struct tcb_s *tcb = this_task(); + + if (!note_isenabled()) + { + return; + } + + note = (FAR struct note_binary_s *)data; + length = SIZEOF_NOTE_BINARY(len); + if (length > sizeof(data)) + { + length = sizeof(data); + } + + /* Format the note */ + + note_common(tcb, ¬e->nbi_cmn, length, + NOTE_DUMP_BINARY); + + note->nbi_module = module; + note->nbi_event = event; + memcpy(note->nbi_data, buf, length - sizeof(struct note_binary_s) + 1); + + /* Add the note to circular buffer */ + + sched_note_add(note, length); +} + +void sched_note_vprintf(FAR const char *fmt, va_list va) +{ + FAR struct note_string_s *note; + uint8_t data[255]; + unsigned int length; + FAR struct tcb_s *tcb = this_task(); + + if (!note_isenabled()) + { + return; + } + + note = (FAR struct note_string_s *)data; + length = vsnprintf(note->nst_data, + sizeof(data) - sizeof(struct note_string_s), + fmt, + va); + length = SIZEOF_NOTE_STRING(length); + if (length > sizeof(data)) + { + length = sizeof(data); + } + + /* Format the note */ + + note_common(tcb, ¬e->nst_cmn, length, + NOTE_DUMP_STRING); + + /* Add the note to circular buffer */ + + sched_note_add(note, length); +} + +void sched_note_vbprintf(uint32_t module, uint8_t event, + FAR const char *fmt, va_list va) +{ + FAR struct note_binary_s *note; + uint8_t data[255]; + begin_packed_struct union + { + char c; + short s; + int i; + long l; +#ifdef CONFIG_LIBC_LONG_LONG + long long ll; +#endif + intmax_t im; + size_t sz; + ptrdiff_t ptr; +#ifdef CONFIG_HAVE_FLOAT + float f; +#endif +#ifdef CONFIG_HAVE_DOUBLE + double d; +#endif +#ifdef CONFIG_HAVE_LONG_DOUBLE + long double ld; +#endif + } + + end_packed_struct *var; + + char c; + int length; + bool search_fmt = 0; + int next = 0; + FAR struct tcb_s *tcb = this_task(); + + if (!note_isenabled()) + { + return; + } + + note = (FAR struct note_binary_s *)data; + length = sizeof(data) - sizeof(struct note_binary_s) + 1; + + while ((c = *fmt++) != '\0') + { + if (c != '%' && search_fmt == 0) + { + continue; + } + + search_fmt = 1; + var = (FAR void *)¬e->nbi_data[next]; + + if (c == 'd' || c == 'i' || c == 'u' || + c == 'o' || c == 'x' || c == 'X') + { + if (*(fmt - 2) == 'h' && *(fmt - 3) == 'h') + { + if (next + sizeof(var->c) > length) + { + break; + } + + var->c = va_arg(va, int); + next += sizeof(var->c); + } + else if (*(fmt - 2) == 'h') + { + if (next + sizeof(var->s) > length) + { + break; + } + + var->s = va_arg(va, int); + next += sizeof(var->s); + } + else if (*(fmt - 2) == 'j') + { + if (next + sizeof(var->im) > length) + { + break; + } + + var->im = va_arg(va, intmax_t); + next += sizeof(var->im); + } +#ifdef CONFIG_LIBC_LONG_LONG + else if (*(fmt - 2) == 'l' && *(fmt - 3) == 'l') + { + if (next + sizeof(var->ll) > length) + { + break; + } + + var->ll = va_arg(va, long long); + next += sizeof(var->ll); + } +#endif + else if (*(fmt - 2) == 'l') + { + if (next + sizeof(var->l) > length) + { + break; + } + + var->l = va_arg(va, long); + next += sizeof(var->l); + } + else if (*(fmt - 2) == 'z') + { + if (next + sizeof(var->sz) > length) + { + break; + } + + var->sz = va_arg(va, size_t); + next += sizeof(var->sz); + } + else if (*(fmt - 2) == 't') + { + if (next + sizeof(var->ptr) > length) + { + break; + } + + var->ptr = va_arg(va, ptrdiff_t); + next += sizeof(var->ptr); + } + else + { + if (next + sizeof(var->i) > length) + { + break; + } + + var->i = va_arg(va, int); + next += sizeof(var->i); + } + + search_fmt = 0; + } + + if (c == 'e' || c == 'f' || c == 'g' || + c == 'E' || c == 'F' || c == 'G') + { + if (*(fmt - 2) == 'L') + { +#ifdef CONFIG_HAVE_LONG_DOUBLE + if (next + sizeof(var->ld) > length) + { + break; + } + + var->ld = va_arg(va, long double); + next += sizeof(var->ld); +#endif + } + else if (*(fmt - 2) == 'l') + { +#ifdef CONFIG_HAVE_DOUBLE + if (next + sizeof(var->d) > length) + { + break; + } + + var->d = va_arg(va, double); + next += sizeof(var->d); +#endif + } + else +#ifdef CONFIG_HAVE_FLOAT + { + if (next + sizeof(var->l) > length) + { + break; + } + + var->l = va_arg(va, double); + next += sizeof(var->l); +#endif + } + + search_fmt = 0; + } + } + + length = SIZEOF_NOTE_BINARY(next); + + /* Format the note */ + + note_common(tcb, ¬e->nbi_cmn, length, + NOTE_DUMP_BINARY); + + note->nbi_module = module; + note->nbi_event = event; + + /* Add the note to circular buffer */ + + sched_note_add(note, length); +} + +void sched_note_printf(FAR const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + sched_note_vprintf(fmt, va); + va_end(va); +} + +void sched_note_bprintf(uint32_t module, uint8_t event, + FAR const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + sched_note_vbprintf(module, event, fmt, va); + va_end(va); +} +#endif /* CONFIG_SCHED_INSTRUMENTATION_DUMP */ + #ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER /****************************************************************************