From 4dad4b84112d57cf6e77409f8e267706db446ec0 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 10 Mar 2014 14:39:49 +0100 Subject: sapi: Add profiling application level support --- cpukit/sapi/Makefile.am | 3 + cpukit/sapi/include/rtems/profiling.h | 148 +++++++++++++++++++++ cpukit/sapi/preinstall.am | 4 + cpukit/sapi/src/profilingiterate.c | 26 ++++ cpukit/sapi/src/profilingreportxml.c | 96 +++++++++++++ testsuites/sptests/Makefile.am | 1 + testsuites/sptests/configure.ac | 1 + testsuites/sptests/spprofiling01/Makefile.am | 19 +++ testsuites/sptests/spprofiling01/init.c | 63 +++++++++ testsuites/sptests/spprofiling01/spprofiling01.doc | 11 ++ testsuites/sptests/spprofiling01/spprofiling01.scn | 5 + 11 files changed, 377 insertions(+) create mode 100644 cpukit/sapi/include/rtems/profiling.h create mode 100644 cpukit/sapi/src/profilingiterate.c create mode 100644 cpukit/sapi/src/profilingreportxml.c create mode 100644 testsuites/sptests/spprofiling01/Makefile.am create mode 100644 testsuites/sptests/spprofiling01/init.c create mode 100644 testsuites/sptests/spprofiling01/spprofiling01.doc create mode 100644 testsuites/sptests/spprofiling01/spprofiling01.scn diff --git a/cpukit/sapi/Makefile.am b/cpukit/sapi/Makefile.am index 63eb60595f..19f7d87f61 100644 --- a/cpukit/sapi/Makefile.am +++ b/cpukit/sapi/Makefile.am @@ -14,6 +14,7 @@ include_rtems_HEADERS += include/rtems/init.h include_rtems_HEADERS += include/rtems/io.h include_rtems_HEADERS += include/rtems/mptables.h include_rtems_HEADERS += include/rtems/cbs.h +include_rtems_HEADERS += include/rtems/profiling.h include_rtems_HEADERS += include/rtems/rbheap.h include_rtems_HEADERS += include/rtems/rbtree.h include_rtems_HEADERS += include/rtems/sptables.h @@ -36,6 +37,8 @@ libsapi_a_SOURCES += src/chainsmp.c libsapi_a_SOURCES += src/cpucounterconverter.c libsapi_a_SOURCES += src/delayticks.c libsapi_a_SOURCES += src/delaynano.c +libsapi_a_SOURCES += src/profilingiterate.c +libsapi_a_SOURCES += src/profilingreportxml.c libsapi_a_CPPFLAGS = $(AM_CPPFLAGS) include $(srcdir)/preinstall.am diff --git a/cpukit/sapi/include/rtems/profiling.h b/cpukit/sapi/include/rtems/profiling.h new file mode 100644 index 0000000000..b2bdf10a98 --- /dev/null +++ b/cpukit/sapi/include/rtems/profiling.h @@ -0,0 +1,148 @@ +/** + * @file + * + * @ingroup Profiling + * + * @brief Profiling API + */ + +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef _RTEMS_PROFILING_H +#define _RTEMS_PROFILING_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup Profiling Profiling Support + * + * @brief The profiling support offers functions to report profiling + * information available in the system. + * + * Profiling support is by default disabled. It must be enabled via the + * configure command line with the --enable-profiling option. In this + * case the RTEMS_PROFILING pre-processor symbol is defined and profiling + * statistics will be gathered during system run-time. The profiling support + * increases the time of critical sections and has some memory overhead. The + * overhead should be acceptable for most applications. The aim of the + * profiling implementation is to be available even for production systems so + * that verification is simplified. + * + * Profiling information includes critical timing values such as the maximum + * time of disabled thread dispatching which is a measure for the thread + * dispatch latency. On SMP configurations statistics of all SMP locks in the + * system are available. + * + * Profiling information can be retrieved via rtems_profiling_iterate() and + * reported as an XML dump via rtems_profiling_report_xml(). These functions + * are always available, but actual profiling data is only available if enabled + * at build configuration time. + * + * @{ + */ + +/** + * @brief Type of profiling data. + */ +typedef enum { +} rtems_profiling_type; + +/** + * @brief The profiling data header. + */ +typedef struct { + /** + * @brief The profiling data type. + */ + rtems_profiling_type type; +} rtems_profiling_header; + +/** + * @brief Collection of profiling data. + */ +typedef union { + /** + * @brief Header to specify the actual profiling data. + */ + rtems_profiling_header header; +} rtems_profiling_data; + +/** + * @brief Visitor function for the profiling iteration. + * + * @param[in, out] arg The visitor argument. + * @param[in] data The current profiling data. + * + * @see rtems_profiling_iterate(). + */ +typedef void (*rtems_profiling_visitor)( + void *arg, + const rtems_profiling_data *data +); + +/** + * @brief Iterates through all profiling data of the system. + * + * @param[in] visitor The visitor. + * @param[in, out] visitor_arg The visitor argument. + */ +void rtems_profiling_iterate( + rtems_profiling_visitor visitor, + void *visitor_arg +); + +/** + * @brief Function for formatted output. + * + * @param[in, out] arg Some argument. + * @param[in] format The output format as specified by printf(). + * @param[in] ... More parameters according to format. + * + * @returns As specified by printf(). + * + * @see rtems_profiling_report_xml(). + */ +typedef int (*rtems_profiling_printf)(void *arg, const char *format, ...); + +/** + * @brief Reports profiling data as XML. + * + * @param[in] name The name of the profiling report. + * @param[in] printf_func The formatted output function. + * @param[in, out] printf_arg The formatted output function argument. + * @param[in] indentation_level The current indentation level. + * @param[in] indentation The string used for indentation. + * + * @returns As specified by printf(). + */ +int rtems_profiling_report_xml( + const char *name, + rtems_profiling_printf printf_func, + void *printf_arg, + uint32_t indentation_level, + const char *indentation +); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_PROFILING_H */ diff --git a/cpukit/sapi/preinstall.am b/cpukit/sapi/preinstall.am index 79eceef405..d05ab256a1 100644 --- a/cpukit/sapi/preinstall.am +++ b/cpukit/sapi/preinstall.am @@ -72,6 +72,10 @@ $(PROJECT_INCLUDE)/rtems/cbs.h: include/rtems/cbs.h $(PROJECT_INCLUDE)/rtems/$(d $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/cbs.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/cbs.h +$(PROJECT_INCLUDE)/rtems/profiling.h: include/rtems/profiling.h $(PROJECT_INCLUDE)/rtems/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/profiling.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/profiling.h + $(PROJECT_INCLUDE)/rtems/rbheap.h: include/rtems/rbheap.h $(PROJECT_INCLUDE)/rtems/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rbheap.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rbheap.h diff --git a/cpukit/sapi/src/profilingiterate.c b/cpukit/sapi/src/profilingiterate.c new file mode 100644 index 0000000000..e528932db9 --- /dev/null +++ b/cpukit/sapi/src/profilingiterate.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include + +void rtems_profiling_iterate( + rtems_profiling_visitor visitor, + void *visitor_arg +) +{ +} diff --git a/cpukit/sapi/src/profilingreportxml.c b/cpukit/sapi/src/profilingreportxml.c new file mode 100644 index 0000000000..d3fe7f7652 --- /dev/null +++ b/cpukit/sapi/src/profilingreportxml.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include + +#ifdef RTEMS_PROFILING + +typedef struct { + rtems_profiling_printf printf_func; + void *printf_arg; + uint32_t indentation_level; + const char *indentation; + int retval; +} context; + +static void update_retval(context *ctx, int rv) +{ + if (rv > 0 && ctx->retval >= 0) { + ctx->retval += rv; + } +} + +static void indent(context *ctx, uint32_t indentation_level) +{ + uint32_t n = ctx->indentation_level + indentation_level; + uint32_t i; + + for (i = 0; i < n; ++i) { + int rv = (*ctx->printf_func)(ctx->printf_arg, "%s", ctx->indentation); + + update_retval(ctx, rv); + } +} + +static void report(void *arg, const rtems_profiling_data *data) +{ + context *ctx = arg; +} + +#endif /* RTEMS_PROFILING */ + +int rtems_profiling_report_xml( + const char *name, + rtems_profiling_printf printf_func, + void *printf_arg, + uint32_t indentation_level, + const char *indentation +) +{ +#ifdef RTEMS_PROFILING + context ctx_instance = { + .printf_func = printf_func, + .printf_arg = printf_arg, + .indentation_level = indentation_level, + .indentation = indentation, + .retval = 0 + }; + context *ctx = &ctx_instance; + int rv; + + indent(ctx, 0); + rv = (*printf_func)(printf_arg, "\n", name); + update_retval(ctx, rv); + + rtems_profiling_iterate(report, ctx); + + indent(ctx, 0); + rv = (*printf_func)(printf_arg, "\n"); + update_retval(ctx, rv); + + return ctx->retval; +#else /* RTEMS_PROFILING */ + (void) name; + (void) printf_func; + (void) printf_arg; + (void) indentation_level; + (void) indentation; + + return 0; +#endif /* RTEMS_PROFILING */ +} diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index 3aa133072c..d57ae69488 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -30,6 +30,7 @@ SUBDIRS = \ spsimplesched03 spnsext01 spedfsched01 spedfsched02 spedfsched03 \ spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01 \ spregion_err01 sppartition_err01 +SUBDIRS += spprofiling01 SUBDIRS += spcache01 SUBDIRS += sptls03 SUBDIRS += spcpucounter01 diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index fe9f81651c..5f98ba7573 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -36,6 +36,7 @@ AM_CONDITIONAL(HAS_CPUSET,test x"${ac_cv_header_sys_cpuset_h}" = x"yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +spprofiling01/Makefile spcache01/Makefile sptls03/Makefile spcpucounter01/Makefile diff --git a/testsuites/sptests/spprofiling01/Makefile.am b/testsuites/sptests/spprofiling01/Makefile.am new file mode 100644 index 0000000000..872e50a712 --- /dev/null +++ b/testsuites/sptests/spprofiling01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = spprofiling01 +spprofiling01_SOURCES = init.c + +dist_rtems_tests_DATA = spprofiling01.scn spprofiling01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(spprofiling01_OBJECTS) +LINK_LIBS = $(spprofiling01_LDLIBS) + +spprofiling01$(EXEEXT): $(spprofiling01_OBJECTS) $(spprofiling01_DEPENDENCIES) + @rm -f spprofiling01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/spprofiling01/init.c b/testsuites/sptests/spprofiling01/init.c new file mode 100644 index 0000000000..a1af66bba2 --- /dev/null +++ b/testsuites/sptests/spprofiling01/init.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include +#include + +#include + +#include "tmacros.h" + +static void test(void) +{ + rtems_status_code sc; + int rv; + + sc = rtems_task_wake_after(3); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + rv = rtems_profiling_report_xml("X", rtems_printf_plugin, NULL, 1, " "); + printf("characters produced by rtems_profiling_report_xml(): %i\n", rv); +} + +static void Init(rtems_task_argument arg) +{ + puts("\n\n*** TEST SPPROFILING 1 ***"); + + test(); + + puts("*** END OF TEST SPPROFILING 1 ***"); + + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + +#define CONFIGURE_MAXIMUM_TASKS 1 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/sptests/spprofiling01/spprofiling01.doc b/testsuites/sptests/spprofiling01/spprofiling01.doc new file mode 100644 index 0000000000..2614c645af --- /dev/null +++ b/testsuites/sptests/spprofiling01/spprofiling01.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: spprofiling01 + +directives: + + - rtems_profiling_report_xml() + +concepts: + + - Ensure that rtems_profiling_report_xml() yields the expected output. diff --git a/testsuites/sptests/spprofiling01/spprofiling01.scn b/testsuites/sptests/spprofiling01/spprofiling01.scn new file mode 100644 index 0000000000..2c289db941 --- /dev/null +++ b/testsuites/sptests/spprofiling01/spprofiling01.scn @@ -0,0 +1,5 @@ +*** TEST SPPROFILING 1 *** + + +characters produced by rtems_profiling_report_xml(): 50 +*** END OF TEST SPPROFILING 1 *** -- cgit v1.2.3