mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
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
This commit is contained in:
@@ -147,6 +147,11 @@ enum note_type_e
|
|||||||
NOTE_IRQ_ENTER = 20,
|
NOTE_IRQ_ENTER = 20,
|
||||||
NOTE_IRQ_LEAVE = 21
|
NOTE_IRQ_LEAVE = 21
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP
|
||||||
|
,
|
||||||
|
NOTE_DUMP_STRING = 22,
|
||||||
|
NOTE_DUMP_BINARY = 23
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure provides the common header of each note */
|
/* This structure provides the common header of each note */
|
||||||
@@ -318,6 +323,29 @@ struct note_irqhandler_s
|
|||||||
};
|
};
|
||||||
#endif /* CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER */
|
#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
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
|
||||||
|
|
||||||
/* This is the type of the argument passed to the NOTECTL_GETMODE and
|
/* 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)
|
# define sched_note_irqhandler(i,h,e)
|
||||||
#endif
|
#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)
|
#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_enter(n,a...)
|
||||||
# define sched_note_syscall_leave(n,r)
|
# define sched_note_syscall_leave(n,r)
|
||||||
# define sched_note_irqhandler(i,h,e)
|
# 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 /* CONFIG_SCHED_INSTRUMENTATION */
|
||||||
#endif /* __INCLUDE_NUTTX_SCHED_NOTE_H */
|
#endif /* __INCLUDE_NUTTX_SCHED_NOTE_H */
|
||||||
|
|||||||
@@ -1038,6 +1038,19 @@ config SCHED_INSTRUMENTATION_IRQHANDLER
|
|||||||
|
|
||||||
void sched_note_irqhandler(int irq, FAR void *handler, bool enter);
|
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
|
config SCHED_INSTRUMENTATION_HIRES
|
||||||
bool "Use Hi-Res RTC for instrumentation"
|
bool "Use Hi-Res RTC for instrumentation"
|
||||||
default n
|
default n
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -39,6 +40,18 @@
|
|||||||
|
|
||||||
#include "sched/sched.h"
|
#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
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -789,6 +802,326 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
Reference in New Issue
Block a user