libc: add instrument api support

Add registration function instrumentation API,
which can achieve instrumentation of entering and
exiting functions through the compiler's functionality.

We can use CONFIG_ARCH_INSTRUMENT_ALL to add instrumentation for all
source, or add '-finstrument-functions' to CFLAGS for Part of the
source.

Notice:
1. use CONFIG_ARCH_INSTRUMENT_ALL must mark _start or entry noinstrument_function,
   becuase bss not set.
2. Make sure your callbacks are not instrumented recursively.

use instrument_register to register entry function and exit function.
They will be called by the instrumented function

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao
2023-10-08 18:20:43 +08:00
committed by Xiang Xiao
parent 404616d621
commit 7dfbd14eba
37 changed files with 403 additions and 43 deletions
+43 -23
View File
@@ -40,9 +40,14 @@
#include <nuttx/note/notelog_driver.h>
#include <nuttx/spinlock.h>
#include <nuttx/sched_note.h>
#include <nuttx/instrument.h>
#include "sched/sched.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_DRIVERS_NOTERAM) + defined(CONFIG_DRIVERS_NOTELOG) + \
defined(CONFIG_DRIVERS_NOTESNAP) + defined(CONFIG_DRIVERS_NOTERTT) + \
defined(CONFIG_SEGGER_SYSVIEW) > CONFIG_DRIVERS_NOTE_MAX
@@ -150,6 +155,18 @@ struct note_taskname_s
* Private Data
****************************************************************************/
#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
static void note_driver_instrument_enter(FAR void *this_fn,
FAR void *call_site, FAR void *arg) noinstrument_function;
static void note_driver_instrument_leave(FAR void *this_fn,
FAR void *call_site, FAR void *arg) noinstrument_function;
static struct instrument_s g_note_instrument =
{
.entry = note_driver_instrument_enter,
.exit = note_driver_instrument_leave,
};
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
static struct note_filter_s g_note_filter =
{
@@ -1924,6 +1941,22 @@ FAR const char *note_get_taskname(pid_t pid)
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
static void note_driver_instrument_enter(FAR void *this_fn,
FAR void *call_site,
FAR void *arg)
{
sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "B");
}
static void note_driver_instrument_leave(FAR void *this_fn,
FAR void *call_site,
FAR void *arg)
{
sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "E");
}
#endif
/****************************************************************************
* Name: note_driver_register
****************************************************************************/
@@ -1931,8 +1964,17 @@ FAR const char *note_get_taskname(pid_t pid)
int note_driver_register(FAR struct note_driver_s *driver)
{
int i;
DEBUGASSERT(driver);
#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
static bool initialized;
if (!initialized)
{
instrument_register(g_note_instrument)
initialized = true;
}
#endif
DEBUGASSERT(driver);
for (i = 0; i < CONFIG_DRIVERS_NOTE_MAX; i++)
{
if (g_note_drivers[i] == NULL)
@@ -1945,25 +1987,3 @@ int note_driver_register(FAR struct note_driver_s *driver)
return -ENOMEM;
}
#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
/****************************************************************************
* Name: __cyg_profile_func_enter
****************************************************************************/
void noinstrument_function
__cyg_profile_func_enter(void *this_fn, void *call_site)
{
sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "B");
}
/****************************************************************************
* Name: __cyg_profile_func_exit
****************************************************************************/
void noinstrument_function
__cyg_profile_func_exit(void *this_fn, void *call_site)
{
sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "E");
}
#endif