note: print without relying on format strings
Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
This commit is contained in:
parent
57a385a994
commit
5d8cdeaea8
@ -87,6 +87,11 @@ config DRIVERS_NOTERAM_CRASH_DUMP
|
|||||||
|
|
||||||
endif # DRIVERS_NOTERAM
|
endif # DRIVERS_NOTERAM
|
||||||
|
|
||||||
|
config DRIVERS_NOTE_STRIP_FORMAT
|
||||||
|
bool "Strip sched_note_printf format string"
|
||||||
|
---help---
|
||||||
|
Strip sched_note_printf format string.
|
||||||
|
|
||||||
config DRIVERS_NOTELOG
|
config DRIVERS_NOTELOG
|
||||||
bool "Note syslog driver"
|
bool "Note syslog driver"
|
||||||
---help---
|
---help---
|
||||||
|
@ -1483,39 +1483,14 @@ void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
|
void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
|
||||||
FAR const char *fmt, va_list va)
|
uint32_t type, va_list va)
|
||||||
{
|
{
|
||||||
FAR struct note_printf_s *note;
|
FAR struct note_printf_s *note;
|
||||||
FAR struct note_driver_s **driver;
|
FAR struct note_driver_s **driver;
|
||||||
bool formatted = false;
|
bool formatted = false;
|
||||||
uint8_t data[255];
|
uint8_t data[255];
|
||||||
begin_packed_struct union
|
size_t length = 0;
|
||||||
{
|
|
||||||
int i;
|
|
||||||
long l;
|
|
||||||
#ifdef CONFIG_HAVE_LONG_LONG
|
|
||||||
long long ll;
|
|
||||||
#endif
|
|
||||||
intmax_t im;
|
|
||||||
size_t sz;
|
|
||||||
ptrdiff_t ptr;
|
|
||||||
FAR void *p;
|
|
||||||
#ifdef CONFIG_HAVE_DOUBLE
|
|
||||||
double d;
|
|
||||||
# ifdef CONFIG_HAVE_LONG_DOUBLE
|
|
||||||
long double ld;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
end_packed_struct *var;
|
|
||||||
|
|
||||||
char c;
|
|
||||||
size_t length;
|
|
||||||
size_t next = 0;
|
|
||||||
bool infmt = false;
|
|
||||||
FAR const char *p = fmt;
|
|
||||||
FAR struct tcb_s *tcb = this_task();
|
FAR struct tcb_s *tcb = this_task();
|
||||||
|
|
||||||
if (!note_isenabled_dump(tag))
|
if (!note_isenabled_dump(tag))
|
||||||
@ -1539,10 +1514,98 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
|
|||||||
|
|
||||||
if (!formatted)
|
if (!formatted)
|
||||||
{
|
{
|
||||||
|
begin_packed_struct union
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
long l;
|
||||||
|
#ifdef CONFIG_HAVE_LONG_LONG
|
||||||
|
long long ll;
|
||||||
|
#endif
|
||||||
|
intmax_t im;
|
||||||
|
size_t sz;
|
||||||
|
ptrdiff_t ptr;
|
||||||
|
FAR void *p;
|
||||||
|
FAR const char *s;
|
||||||
|
#ifdef CONFIG_HAVE_DOUBLE
|
||||||
|
double d;
|
||||||
|
# ifdef CONFIG_HAVE_LONG_DOUBLE
|
||||||
|
long double ld;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
end_packed_struct *var;
|
||||||
|
size_t next = 0;
|
||||||
formatted = true;
|
formatted = true;
|
||||||
note = (FAR struct note_printf_s *)data;
|
note = (FAR struct note_printf_s *)data;
|
||||||
length = sizeof(data) - SIZEOF_NOTE_PRINTF(0);
|
length = sizeof(data) - SIZEOF_NOTE_PRINTF(0);
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
size_t count = NOTE_PRINTF_GET_COUNT(type);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var = (FAR void *)¬e->npt_data[next];
|
||||||
|
switch (NOTE_PRINTF_GET_TYPE(type, i))
|
||||||
|
{
|
||||||
|
case NOTE_PRINTF_UINT32:
|
||||||
|
{
|
||||||
|
var->i = va_arg(va, int);
|
||||||
|
if (next + sizeof(var->i) > length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next += sizeof(var->i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTE_PRINTF_UINT64:
|
||||||
|
{
|
||||||
|
if (next + sizeof(var->ll) > length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var->ll = va_arg(va, long long);
|
||||||
|
next += sizeof(var->ll);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTE_PRINTF_STRING:
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
var->s = va_arg(va, FAR const char *);
|
||||||
|
len = strlen(var->s) + 1;
|
||||||
|
if (next + len > length)
|
||||||
|
{
|
||||||
|
len = length - next;
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcpy(note->npt_data + next, var->s, len);
|
||||||
|
next += len;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTE_PRINTF_DOUBLE:
|
||||||
|
{
|
||||||
|
var->d = va_arg(va, double);
|
||||||
|
if (next + sizeof(var->d) > length)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next += sizeof(var->d);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FAR const char *p = fmt;
|
||||||
|
bool infmt = false;
|
||||||
|
char c;
|
||||||
|
|
||||||
while ((c = *p++) != '\0')
|
while ((c = *p++) != '\0')
|
||||||
{
|
{
|
||||||
if (c != '%' && !infmt)
|
if (c != '%' && !infmt)
|
||||||
@ -1658,14 +1721,15 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
|
|||||||
}
|
}
|
||||||
else if (c == 's')
|
else if (c == 's')
|
||||||
{
|
{
|
||||||
FAR char *str = (FAR char *)va_arg(va, FAR char *);
|
size_t len;
|
||||||
size_t len = strlen(str) + 1;
|
var->s = va_arg(va, FAR char *);
|
||||||
|
len = strlen(var->s) + 1;
|
||||||
if (next + len > length)
|
if (next + len > length)
|
||||||
{
|
{
|
||||||
len = length - next;
|
len = length - next;
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(¬e->npt_data[next], str, len);
|
strlcpy(note->npt_data + next, var->s, len);
|
||||||
next += len;
|
next += len;
|
||||||
infmt = false;
|
infmt = false;
|
||||||
}
|
}
|
||||||
@ -1681,11 +1745,13 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
|
|||||||
infmt = false;
|
infmt = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
length = SIZEOF_NOTE_PRINTF(next);
|
length = SIZEOF_NOTE_PRINTF(next);
|
||||||
note_common(tcb, ¬e->npt_cmn, length, NOTE_DUMP_PRINTF);
|
note_common(tcb, ¬e->npt_cmn, length, NOTE_DUMP_PRINTF);
|
||||||
note->npt_ip = ip;
|
note->npt_ip = ip;
|
||||||
note->npt_fmt = fmt;
|
note->npt_fmt = fmt;
|
||||||
|
note->npt_type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the note to circular buffer */
|
/* Add the note to circular buffer */
|
||||||
@ -1694,12 +1760,12 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sched_note_printf_ip(uint32_t tag, uintptr_t ip,
|
void sched_note_printf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
|
||||||
FAR const char *fmt, ...)
|
uint32_t type, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, fmt);
|
va_start(va, type);
|
||||||
sched_note_vprintf_ip(tag, ip, fmt, va);
|
sched_note_vprintf_ip(tag, ip, fmt, type, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +728,8 @@ static int noteram_dump_printf(FAR struct lib_outstream_s *s,
|
|||||||
intmax_t im;
|
intmax_t im;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
ptrdiff_t pd;
|
ptrdiff_t pd;
|
||||||
uintptr_t p;
|
FAR void *p;
|
||||||
|
FAR const char *s;
|
||||||
#ifdef CONFIG_HAVE_DOUBLE
|
#ifdef CONFIG_HAVE_DOUBLE
|
||||||
double d;
|
double d;
|
||||||
# ifdef CONFIG_HAVE_LONG_DOUBLE
|
# ifdef CONFIG_HAVE_LONG_DOUBLE
|
||||||
@ -738,13 +739,15 @@ static int noteram_dump_printf(FAR struct lib_outstream_s *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
end_packed_struct *var;
|
end_packed_struct *var;
|
||||||
FAR const char *p = note->npt_fmt;
|
|
||||||
FAR char *data = note->npt_data;
|
|
||||||
char fmtstr[64];
|
|
||||||
bool infmt = false;
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
size_t ret = 0;
|
size_t ret = 0;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
|
if (note->npt_type == 0)
|
||||||
|
{
|
||||||
|
FAR const char *p = note->npt_fmt;
|
||||||
|
bool infmt = false;
|
||||||
|
char fmtstr[64];
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
while ((c = *p++) != '\0')
|
while ((c = *p++) != '\0')
|
||||||
@ -832,9 +835,9 @@ static int noteram_dump_printf(FAR struct lib_outstream_s *s,
|
|||||||
}
|
}
|
||||||
else if (c == 's')
|
else if (c == 's')
|
||||||
{
|
{
|
||||||
FAR const char *value = data + offset;
|
const char *str = note->npt_data + offset;
|
||||||
offset += strlen(value) + 1;
|
offset += strlen(str) + 1;
|
||||||
ret += lib_sprintf(s, fmtstr, value);
|
ret += lib_sprintf(s, fmtstr, str);
|
||||||
infmt = false;
|
infmt = false;
|
||||||
}
|
}
|
||||||
else if (c == 'p')
|
else if (c == 'p')
|
||||||
@ -850,6 +853,56 @@ static int noteram_dump_printf(FAR struct lib_outstream_s *s,
|
|||||||
lib_stream_putc(s, '\n');
|
lib_stream_putc(s, '\n');
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t count = NOTE_PRINTF_GET_COUNT(note->npt_type);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
len = strlen(note->npt_fmt);
|
||||||
|
if (note->npt_fmt[len - 1] == '\n')
|
||||||
|
{
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += lib_sprintf(s, "%p", note->npt_fmt);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int type = NOTE_PRINTF_GET_TYPE(note->npt_type, i);
|
||||||
|
var = (FAR void *)(note->npt_data + offset);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NOTE_PRINTF_UINT32:
|
||||||
|
{
|
||||||
|
offset += sizeof(var->i);
|
||||||
|
ret += lib_sprintf(s, " %u", var->i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTE_PRINTF_UINT64:
|
||||||
|
{
|
||||||
|
offset += sizeof(var->ll);
|
||||||
|
ret += lib_sprintf(s, " %llu", var->ll);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTE_PRINTF_STRING:
|
||||||
|
{
|
||||||
|
const char *str = note->npt_data + offset;
|
||||||
|
offset += strlen(str) + 1;
|
||||||
|
ret += lib_sprintf(s, " %s", str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOTE_PRINTF_DOUBLE:
|
||||||
|
{
|
||||||
|
offset += sizeof(var->d);
|
||||||
|
ret += lib_sprintf(s, " %f", var->d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lib_stream_putc(s, '\n');
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@
|
|||||||
* unnecessary "weak" functions can be excluded from the link.
|
* unnecessary "weak" functions can be excluded from the link.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef CONFIG_HAVE_WEAKFUNCTIONS
|
# undef CONFIG_HAVE_WEAKFUNCTIONS
|
||||||
|
|
||||||
# if !defined(__CYGWIN__) && !defined(CONFIG_ARCH_GNU_NO_WEAKFUNCTIONS)
|
# if !defined(__CYGWIN__) && !defined(CONFIG_ARCH_GNU_NO_WEAKFUNCTIONS)
|
||||||
# define CONFIG_HAVE_WEAKFUNCTIONS 1
|
# define CONFIG_HAVE_WEAKFUNCTIONS 1
|
||||||
@ -344,6 +344,7 @@
|
|||||||
# define syslog_like(a, b) __attribute__((__format__(__syslog__, a, b)))
|
# define syslog_like(a, b) __attribute__((__format__(__syslog__, a, b)))
|
||||||
# define scanf_like(a, b) __attribute__((__format__(__scanf__, a, b)))
|
# define scanf_like(a, b) __attribute__((__format__(__scanf__, a, b)))
|
||||||
# define strftime_like(a) __attribute__((__format__(__strftime__, a, 0)))
|
# define strftime_like(a) __attribute__((__format__(__strftime__, a, 0)))
|
||||||
|
# define object_size(o, t) __builtin_object_size(o, t)
|
||||||
|
|
||||||
/* GCC does not use storage classes to qualify addressing */
|
/* GCC does not use storage classes to qualify addressing */
|
||||||
|
|
||||||
@ -612,6 +613,7 @@
|
|||||||
# define syslog_like(a, b)
|
# define syslog_like(a, b)
|
||||||
# define scanf_like(a, b)
|
# define scanf_like(a, b)
|
||||||
# define strftime_like(a)
|
# define strftime_like(a)
|
||||||
|
# define object_size(o, t) ((size_t)-1)
|
||||||
|
|
||||||
/* The reentrant attribute informs SDCC that the function
|
/* The reentrant attribute informs SDCC that the function
|
||||||
* must be reentrant. In this case, SDCC will store input
|
* must be reentrant. In this case, SDCC will store input
|
||||||
@ -756,6 +758,7 @@
|
|||||||
# define syslog_like(a, b)
|
# define syslog_like(a, b)
|
||||||
# define scanf_like(a, b)
|
# define scanf_like(a, b)
|
||||||
# define strftime_like(a)
|
# define strftime_like(a)
|
||||||
|
# define object_size(o, t) ((size_t)-1)
|
||||||
|
|
||||||
/* REVISIT: */
|
/* REVISIT: */
|
||||||
|
|
||||||
@ -871,6 +874,7 @@
|
|||||||
# define syslog_like(a, b)
|
# define syslog_like(a, b)
|
||||||
# define scanf_like(a, b)
|
# define scanf_like(a, b)
|
||||||
# define strftime_like(a)
|
# define strftime_like(a)
|
||||||
|
# define object_size(o, t) ((size_t)-1)
|
||||||
|
|
||||||
# define FAR
|
# define FAR
|
||||||
# define NEAR
|
# define NEAR
|
||||||
@ -1049,6 +1053,7 @@
|
|||||||
# define syslog_like(a, b)
|
# define syslog_like(a, b)
|
||||||
# define scanf_like(a, b)
|
# define scanf_like(a, b)
|
||||||
# define strftime_like(a)
|
# define strftime_like(a)
|
||||||
|
# define object_size(o, t) ((size_t)-1)
|
||||||
|
|
||||||
# define FAR
|
# define FAR
|
||||||
# define NEAR
|
# define NEAR
|
||||||
@ -1118,6 +1123,7 @@
|
|||||||
# define syslog_like(a, b)
|
# define syslog_like(a, b)
|
||||||
# define scanf_like(a, b)
|
# define scanf_like(a, b)
|
||||||
# define strftime_like(a)
|
# define strftime_like(a)
|
||||||
|
# define object_size(o, t) ((size_t)-1)
|
||||||
|
|
||||||
# define FAR
|
# define FAR
|
||||||
# define NEAR
|
# define NEAR
|
||||||
|
140
include/nuttx/macro.h
Normal file
140
include/nuttx/macro.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* include/nuttx/macro.h
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __INCLUDE_NUTTX_MACRO_H
|
||||||
|
#define __INCLUDE_NUTTX_MACRO_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define GET_ARG_VALUE(_00, _01, _02, _03, _04, _05, _06, _07, \
|
||||||
|
_08, _09, _10, _11, _12, _13, _14, _15, \
|
||||||
|
_16, _17, _18, _19, _20, _21, _22, _23, \
|
||||||
|
_24, _25, _26, _27, _28, _29, _30, _31, \
|
||||||
|
_32, name, ...) name
|
||||||
|
|
||||||
|
/* Get the number of arguments (up to 32) */
|
||||||
|
|
||||||
|
#define GET_ARG_COUNT(...) \
|
||||||
|
GET_ARG_VALUE(_0, ##__VA_ARGS__, 32, 31, 30, \
|
||||||
|
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
|
||||||
|
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
|
||||||
|
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||||
|
|
||||||
|
/* Reverse the arguments */
|
||||||
|
|
||||||
|
#define EXPAND(x) x
|
||||||
|
|
||||||
|
#define REVERSE_00()
|
||||||
|
#define REVERSE_01(a) a
|
||||||
|
#define REVERSE_02(a,b) b,a
|
||||||
|
#define REVERSE_03(a,...) EXPAND(REVERSE_02(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_04(a,...) EXPAND(REVERSE_03(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_05(a,...) EXPAND(REVERSE_04(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_06(a,...) EXPAND(REVERSE_05(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_07(a,...) EXPAND(REVERSE_06(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_08(a,...) EXPAND(REVERSE_07(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_09(a,...) EXPAND(REVERSE_08(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_10(a,...) EXPAND(REVERSE_09(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_11(a,...) EXPAND(REVERSE_10(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_12(a,...) EXPAND(REVERSE_11(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_13(a,...) EXPAND(REVERSE_12(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_14(a,...) EXPAND(REVERSE_13(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_15(a,...) EXPAND(REVERSE_14(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_16(a,...) EXPAND(REVERSE_15(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_17(a,...) EXPAND(REVERSE_16(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_18(a,...) EXPAND(REVERSE_17(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_19(a,...) EXPAND(REVERSE_18(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_20(a,...) EXPAND(REVERSE_19(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_21(a,...) EXPAND(REVERSE_20(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_22(a,...) EXPAND(REVERSE_21(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_23(a,...) EXPAND(REVERSE_22(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_24(a,...) EXPAND(REVERSE_23(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_25(a,...) EXPAND(REVERSE_24(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_26(a,...) EXPAND(REVERSE_25(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_27(a,...) EXPAND(REVERSE_26(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_28(a,...) EXPAND(REVERSE_27(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_29(a,...) EXPAND(REVERSE_28(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_30(a,...) EXPAND(REVERSE_29(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_31(a,...) EXPAND(REVERSE_30(__VA_ARGS__)),a
|
||||||
|
#define REVERSE_32(a,...) EXPAND(REVERSE_31(__VA_ARGS__)),a
|
||||||
|
|
||||||
|
#define REVERSE_ARG_(...) \
|
||||||
|
GET_ARG_VALUE(0, ##__VA_ARGS__, \
|
||||||
|
REVERSE_32, REVERSE_31, REVERSE_30, REVERSE_29, REVERSE_28, REVERSE_27, \
|
||||||
|
REVERSE_26, REVERSE_25, REVERSE_24, REVERSE_23, REVERSE_22, REVERSE_21, \
|
||||||
|
REVERSE_20, REVERSE_19, REVERSE_18, REVERSE_17, REVERSE_16, REVERSE_15, \
|
||||||
|
REVERSE_14, REVERSE_13, REVERSE_12, REVERSE_11, REVERSE_10, REVERSE_09, \
|
||||||
|
REVERSE_08, REVERSE_07, REVERSE_06, REVERSE_05, REVERSE_04, REVERSE_03, \
|
||||||
|
REVERSE_02, REVERSE_01, REVERSE_00)(__VA_ARGS__)
|
||||||
|
|
||||||
|
#define REVERSE_ARG(...) REVERSE_ARG_(##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Apply the macro to each argument */
|
||||||
|
|
||||||
|
#define FOREACH_00(action, count, ...) 0
|
||||||
|
#define FOREACH_01(action, count, arg, ...) action(arg, count - 1 )
|
||||||
|
#define FOREACH_02(action, count, arg, ...) action(arg, count - 2 ) FOREACH_01(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_03(action, count, arg, ...) action(arg, count - 3 ) FOREACH_02(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_04(action, count, arg, ...) action(arg, count - 4 ) FOREACH_03(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_05(action, count, arg, ...) action(arg, count - 5 ) FOREACH_04(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_06(action, count, arg, ...) action(arg, count - 6 ) FOREACH_05(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_07(action, count, arg, ...) action(arg, count - 7 ) FOREACH_06(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_08(action, count, arg, ...) action(arg, count - 8 ) FOREACH_07(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_09(action, count, arg, ...) action(arg, count - 9 ) FOREACH_08(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_10(action, count, arg, ...) action(arg, count - 10) FOREACH_09(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_11(action, count, arg, ...) action(arg, count - 11) FOREACH_10(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_12(action, count, arg, ...) action(arg, count - 12) FOREACH_11(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_13(action, count, arg, ...) action(arg, count - 13) FOREACH_12(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_14(action, count, arg, ...) action(arg, count - 14) FOREACH_13(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_15(action, count, arg, ...) action(arg, count - 15) FOREACH_14(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_16(action, count, arg, ...) action(arg, count - 16) FOREACH_15(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_17(action, count, arg, ...) action(arg, count - 17) FOREACH_16(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_18(action, count, arg, ...) action(arg, count - 18) FOREACH_17(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_19(action, count, arg, ...) action(arg, count - 19) FOREACH_18(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_20(action, count, arg, ...) action(arg, count - 20) FOREACH_19(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_21(action, count, arg, ...) action(arg, count - 21) FOREACH_20(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_22(action, count, arg, ...) action(arg, count - 22) FOREACH_21(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_23(action, count, arg, ...) action(arg, count - 23) FOREACH_22(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_24(action, count, arg, ...) action(arg, count - 24) FOREACH_23(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_25(action, count, arg, ...) action(arg, count - 25) FOREACH_24(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_26(action, count, arg, ...) action(arg, count - 26) FOREACH_25(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_27(action, count, arg, ...) action(arg, count - 27) FOREACH_26(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_28(action, count, arg, ...) action(arg, count - 28) FOREACH_27(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_29(action, count, arg, ...) action(arg, count - 29) FOREACH_28(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_30(action, count, arg, ...) action(arg, count - 30) FOREACH_29(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_31(action, count, arg, ...) action(arg, count - 31) FOREACH_30(action, count, __VA_ARGS__)
|
||||||
|
#define FOREACH_32(action, count, arg, ...) action(arg, count - 32) FOREACH_31(action, count, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define FOREACH_ARG_(action, count, ...) \
|
||||||
|
GET_ARG_VALUE(0, ##__VA_ARGS__, \
|
||||||
|
FOREACH_32, FOREACH_31, FOREACH_30, FOREACH_29, FOREACH_28, FOREACH_27, \
|
||||||
|
FOREACH_26, FOREACH_25, FOREACH_24, FOREACH_23, FOREACH_22, FOREACH_21, \
|
||||||
|
FOREACH_20, FOREACH_19, FOREACH_18, FOREACH_17, FOREACH_16, FOREACH_15, \
|
||||||
|
FOREACH_14, FOREACH_13, FOREACH_12, FOREACH_11, FOREACH_10, FOREACH_09, \
|
||||||
|
FOREACH_08, FOREACH_07, FOREACH_06, FOREACH_05, FOREACH_04, FOREACH_03, \
|
||||||
|
FOREACH_02, FOREACH_01, FOREACH_00)(action, count, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define FOREACH_ARG(action, ...) \
|
||||||
|
FOREACH_ARG_(action, GET_ARG_COUNT(__VA_ARGS__), ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif /* __INCLUDE_NUTTX_MACRO_H */
|
||||||
|
|
@ -32,6 +32,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <nuttx/macro.h>
|
||||||
#include <nuttx/sched.h>
|
#include <nuttx/sched.h>
|
||||||
#include <nuttx/spinlock.h>
|
#include <nuttx/spinlock.h>
|
||||||
|
|
||||||
@ -125,15 +126,83 @@
|
|||||||
# define NOTE_FILTER_TAGMASK_ZERO(s)
|
# define NOTE_FILTER_TAGMASK_ZERO(s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Printf argument type */
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_UINT32 0
|
||||||
|
#define NOTE_PRINTF_UINT64 1
|
||||||
|
#define NOTE_PRINTF_DOUBLE 2
|
||||||
|
#define NOTE_PRINTF_STRING 3
|
||||||
|
|
||||||
|
/* Get/set printf tag. each parameter occupies 2 bits. The highest
|
||||||
|
* four bits are used to represent the number of parameters, So up to
|
||||||
|
* 14 variable arguments can be passed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_GET_TYPE(tag, index) (((tag) >> (index) * 2) & 0x03)
|
||||||
|
#define NOTE_PRINTF_GET_COUNT(tag) (((tag) >> 28) & 0x0f)
|
||||||
|
|
||||||
|
/* Check if a variable is 32-bit or 64-bit */
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_INT_TYPE(arg) (sizeof((arg) + 0) <= sizeof(uint32_t) ? \
|
||||||
|
NOTE_PRINTF_UINT32 : NOTE_PRINTF_UINT64)
|
||||||
|
|
||||||
|
/* Use object_size to mark strings of known size */
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_OBJECT_SIZE(arg) object_size((FAR void *)(uintptr_t)(arg), 2)
|
||||||
|
|
||||||
|
/* Use _Generic to determine the type of the parameter */
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_ARG_TYPE(__arg__) \
|
||||||
|
_Generic((__arg__) + 0, \
|
||||||
|
float : NOTE_PRINTF_DOUBLE, \
|
||||||
|
double: NOTE_PRINTF_DOUBLE, \
|
||||||
|
char *: ({NOTE_PRINTF_OBJECT_SIZE(__arg__) > 0 ? \
|
||||||
|
NOTE_PRINTF_STRING : \
|
||||||
|
NOTE_PRINTF_INT_TYPE(__arg__);}), \
|
||||||
|
const char *: ({NOTE_PRINTF_OBJECT_SIZE(__arg__) > 0 ? \
|
||||||
|
NOTE_PRINTF_STRING : \
|
||||||
|
NOTE_PRINTF_INT_TYPE(__arg__);}), \
|
||||||
|
default: NOTE_PRINTF_INT_TYPE(__arg__))
|
||||||
|
|
||||||
|
/* Set the type of each parameter */
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_TYPE(arg, index) + ((NOTE_PRINTF_ARG_TYPE(arg) << (index) * 2))
|
||||||
|
#define NOTE_PRINTF_TYPES(...) FOREACH_ARG(NOTE_PRINTF_TYPE, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* Using macro expansion to calculate the expression of tag, tag will
|
||||||
|
* be a constant at compile time, which will reduce the number of
|
||||||
|
* size in the code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NOTE_PRINTF_TAG(...) \
|
||||||
|
((GET_ARG_COUNT(__VA_ARGS__) << 28) + NOTE_PRINTF_TYPES(__VA_ARGS__))
|
||||||
|
|
||||||
#define SCHED_NOTE_IP \
|
#define SCHED_NOTE_IP \
|
||||||
({ __label__ __here; __here: (unsigned long)&&__here; })
|
({ __label__ __here; __here: (unsigned long)&&__here; })
|
||||||
|
|
||||||
#define sched_note_event(tag, event, buf, len) \
|
#define sched_note_event(tag, event, buf, len) \
|
||||||
sched_note_event_ip(tag, SCHED_NOTE_IP, event, buf, len)
|
sched_note_event_ip(tag, SCHED_NOTE_IP, event, buf, len)
|
||||||
#define sched_note_vprintf(tag, fmt, va) \
|
#define sched_note_vprintf(tag, fmt, va) \
|
||||||
sched_note_vprintf_ip(tag, SCHED_NOTE_IP, fmt, va)
|
sched_note_vprintf_ip(tag, SCHED_NOTE_IP, fmt, 0, va)
|
||||||
#define sched_note_printf(tag, fmt, ...) \
|
|
||||||
sched_note_printf_ip(tag, SCHED_NOTE_IP, fmt, ##__VA_ARGS__)
|
#ifdef CONFIG_DRIVERS_NOTE_STRIP_FORMAT
|
||||||
|
# define sched_note_printf(tag, fmt, ...) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
static const locate_data(".printf_format") \
|
||||||
|
char __fmt__[] = fmt; \
|
||||||
|
uint32_t __type__ = NOTE_PRINTF_TAG(__VA_ARGS__); \
|
||||||
|
static_assert(GET_ARG_COUNT(__VA_ARGS__) <= 14, \
|
||||||
|
"The number of sched_note_nprintf " \
|
||||||
|
"parameters needs to be less than 14"); \
|
||||||
|
sched_note_printf_ip(tag, SCHED_NOTE_IP, __fmt__, \
|
||||||
|
__type__, ##__VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#else
|
||||||
|
# define sched_note_printf(tag, fmt, ...) \
|
||||||
|
sched_note_printf_ip(tag, SCHED_NOTE_IP, fmt, 0, ##__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define sched_note_begin(tag) \
|
#define sched_note_begin(tag) \
|
||||||
sched_note_event(tag, NOTE_DUMP_BEGIN, NULL, 0)
|
sched_note_event(tag, NOTE_DUMP_BEGIN, NULL, 0)
|
||||||
@ -410,6 +479,7 @@ struct note_printf_s
|
|||||||
struct note_common_s npt_cmn; /* Common note parameters */
|
struct note_common_s npt_cmn; /* Common note parameters */
|
||||||
uintptr_t npt_ip; /* Instruction pointer called from */
|
uintptr_t npt_ip; /* Instruction pointer called from */
|
||||||
FAR const char *npt_fmt; /* Printf format string */
|
FAR const char *npt_fmt; /* Printf format string */
|
||||||
|
uint32_t npt_type; /* Printf parameter type */
|
||||||
char npt_data[1]; /* Print arguments */
|
char npt_data[1]; /* Print arguments */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -585,13 +655,13 @@ void sched_note_heap(uint8_t event, FAR void *heap, FAR void *mem,
|
|||||||
void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event,
|
void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event,
|
||||||
FAR const void *buf, size_t len);
|
FAR const void *buf, size_t len);
|
||||||
void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
|
void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
|
||||||
va_list va) printf_like(3, 0);
|
uint32_t type, va_list va) printf_like(3, 0);
|
||||||
void sched_note_printf_ip(uint32_t tag, uintptr_t ip,
|
void sched_note_printf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
|
||||||
FAR const char *fmt, ...) printf_like(3, 4);
|
uint32_t type, ...) printf_like(3, 5);
|
||||||
#else
|
#else
|
||||||
# define sched_note_event_ip(t,ip,e,b,l)
|
# define sched_note_event_ip(t,ip,e,b,l)
|
||||||
# define sched_note_vprintf_ip(t,ip,f,v)
|
# define sched_note_vprintf_ip(t,ip,f,p,v)
|
||||||
# define sched_note_printf_ip(t,ip,f,...)
|
# define sched_note_printf_ip(t,ip,f,p,...)
|
||||||
#endif /* CONFIG_SCHED_INSTRUMENTATION_DUMP */
|
#endif /* CONFIG_SCHED_INSTRUMENTATION_DUMP */
|
||||||
|
|
||||||
#if defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT)
|
#if defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT)
|
||||||
|
@ -1307,8 +1307,8 @@ config SCHED_INSTRUMENTATION_DUMP
|
|||||||
Use note dump for instrumentation.
|
Use note dump for instrumentation.
|
||||||
|
|
||||||
void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event, FAR const void *buf, size_t len);
|
void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event, FAR const void *buf, size_t len);
|
||||||
void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt, va_list va) printf_like(3, 0);
|
void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt, uint32_t type, va_list va) printf_like(3, 0);
|
||||||
void sched_note_printf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt, ...) printf_like(3, 4);
|
void sched_note_printf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt, uint32_t type, ...) printf_like(3, 5);
|
||||||
|
|
||||||
config SCHED_INSTRUMENTATION_FUNCTION
|
config SCHED_INSTRUMENTATION_FUNCTION
|
||||||
bool "Enable function auto-tracing"
|
bool "Enable function auto-tracing"
|
||||||
|
Loading…
Reference in New Issue
Block a user