From a2029c781cb3714da580ff9ef517dd6f45ed1b7a Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Mon, 17 May 2021 16:29:16 -0700 Subject: [PATCH] Enable profiling for the linux port --- FreeRTOS/Demo/Posix_GCC/Makefile | 129 ++++++++++++++++++------------ FreeRTOS/Demo/Posix_GCC/Readme.md | 64 +++++++++++++++ FreeRTOS/Demo/Posix_GCC/main.c | 36 ++++++++- 3 files changed, 174 insertions(+), 55 deletions(-) create mode 100644 FreeRTOS/Demo/Posix_GCC/Readme.md diff --git a/FreeRTOS/Demo/Posix_GCC/Makefile b/FreeRTOS/Demo/Posix_GCC/Makefile index 993fa5ad00..d965736620 100644 --- a/FreeRTOS/Demo/Posix_GCC/Makefile +++ b/FreeRTOS/Demo/Posix_GCC/Makefile @@ -1,65 +1,87 @@ -CC := gcc -BIN := posix_demo +CC := gcc +BIN := posix_demo -BUILD_DIR := build +BUILD_DIR := ./build +BUILD_DIR_ABS := $(abspath $(BUILD_DIR)) -FREERTOS_DIR_REL := ../../../FreeRTOS -FREERTOS_DIR := $(abspath $(FREERTOS_DIR_REL)) +FREERTOS_DIR_REL := ../../../FreeRTOS +FREERTOS_DIR := $(abspath $(FREERTOS_DIR_REL)) FREERTOS_PLUS_DIR_REL := ../../../FreeRTOS-Plus -FREERTOS_PLUS_DIR := $(abspath $(FREERTOS_PLUS_DIR_REL)) +FREERTOS_PLUS_DIR := $(abspath $(FREERTOS_PLUS_DIR_REL)) -INCLUDE_DIRS := -I. -INCLUDE_DIRS += -I${FREERTOS_DIR}/Source/include -INCLUDE_DIRS += -I${FREERTOS_DIR}/Source/portable/ThirdParty/GCC/Posix -INCLUDE_DIRS += -I${FREERTOS_DIR}/Source/portable/ThirdParty/GCC/Posix/utils -INCLUDE_DIRS += -I${FREERTOS_DIR}/Demo/Common/include -INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/Include +KERNEL_DIR := ${FREERTOS_DIR}/Source -SOURCE_FILES := $(wildcard *.c) -SOURCE_FILES += $(wildcard ${FREERTOS_DIR}/Source/*.c) +INCLUDE_DIRS := -I. +INCLUDE_DIRS += -I${KERNEL_DIR}/include +INCLUDE_DIRS += -I${KERNEL_DIR}/portable/ThirdParty/GCC/Posix +INCLUDE_DIRS += -I${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/utils +INCLUDE_DIRS += -I${FREERTOS_DIR}/Demo/Common/include +INCLUDE_DIRS += -I${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/Include + +SOURCE_FILES := $(wildcard *.c) +SOURCE_FILES += $(wildcard ${FREERTOS_DIR}/Source/*.c) # Memory manager (use malloc() / free() ) -SOURCE_FILES += ${FREERTOS_DIR}/Source/portable/MemMang/heap_3.c +SOURCE_FILES += ${KERNEL_DIR}/portable/MemMang/heap_3.c # posix port -SOURCE_FILES += ${FREERTOS_DIR}/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c -SOURCE_FILES += ${FREERTOS_DIR}/Source/portable/ThirdParty/GCC/Posix/port.c +SOURCE_FILES += ${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c +SOURCE_FILES += ${KERNEL_DIR}/portable/ThirdParty/GCC/Posix/port.c # Demo library. -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/AbortDelay.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/BlockQ.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/blocktim.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/countsem.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/death.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/dynamic.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/EventGroupsDemo.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/flop.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/GenQTest.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/integer.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/IntSemTest.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferAMP.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferDemo.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/PollQ.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QPeek.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueOverwrite.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSet.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSetPolling.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/recmutex.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/semtest.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StaticAllocation.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferDemo.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferInterrupt.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TaskNotify.c -SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TimerDemo.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/AbortDelay.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/BlockQ.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/blocktim.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/countsem.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/death.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/dynamic.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/EventGroupsDemo.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/flop.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/GenQTest.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/integer.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/IntSemTest.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferAMP.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/MessageBufferDemo.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/PollQ.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QPeek.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueOverwrite.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSet.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/QueueSetPolling.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/recmutex.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/semtest.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StaticAllocation.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferDemo.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/StreamBufferInterrupt.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TaskNotify.c +SOURCE_FILES += ${FREERTOS_DIR}/Demo/Common/Minimal/TimerDemo.c # Trace library. -SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcKernelPort.c -SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c -SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c -SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c +SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcKernelPort.c +SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcSnapshotRecorder.c +SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/trcStreamingRecorder.c +SOURCE_FILES += ${FREERTOS_PLUS_DIR}/Source/FreeRTOS-Plus-Trace/streamports/File/trcStreamingPort.c -CFLAGS := -ggdb3 -O0 -DprojCOVERAGE_TEST=0 -D_WINDOWS_ -LDFLAGS := -ggdb3 -O0 -pthread +CFLAGS := -ggdb3 -DprojCOVERAGE_TEST=0 -D_WINDOWS_ +LDFLAGS := -ggdb3 -pthread +CPPFLAGS := $(INCLUDE_DIRS) -DBUILD_DIR=\"$(BUILD_DIR_ABS)\" + +ifdef PROFILE + CFLAGS += -pg -O0 + LDFLAGS += -pg -O0 +else + CFLAGS += -O3 + LDFLAGS += -O3 +endif + +ifdef SANITIZE_ADDRESS + CFLAGS += -fsanitize=address -fsanitize=alignment + LDFLAGS += -fsanitize=address -fsanitize=alignment +endif + +ifdef SANITIZE_LEAK + LDFLAGS += -fsanitize=leak +endif + OBJ_FILES = $(SOURCE_FILES:%.c=$(BUILD_DIR)/%.o) @@ -69,14 +91,13 @@ ${BIN} : $(BUILD_DIR)/$(BIN) ${BUILD_DIR}/${BIN} : ${OBJ_FILES} -mkdir -p ${@D} - $(CC) $^ $(CFLAGS) $(INCLUDE_DIRS) ${LDFLAGS} -o $@ - + $(CC) $^ ${LDFLAGS} -o $@ -include ${DEP_FILE} -${BUILD_DIR}/%.o : %.c +${BUILD_DIR}/%.o : %.c Makefile -mkdir -p $(@D) - $(CC) $(CFLAGS) ${INCLUDE_DIRS} -MMD -c $< -o $@ + $(CC) $(CPPFLAGS) $(CFLAGS) -MMD -c $< -o $@ .PHONY: clean @@ -84,6 +105,10 @@ clean: -rm -rf $(BUILD_DIR) +GPROF_OPTIONS := --directory-path=$(INCLUDE_DIRS) +profile: + gprof -a -p --all-lines $(GPROF_OPTIONS) $(BUILD_DIR)/$(BIN) $(BUILD_DIR)/gmon.out > $(BUILD_DIR)/prof_flat.txt + gprof -a --graph $(GPROF_OPTIONS) $(BUILD_DIR)/$(BIN) $(BUILD_DIR)/gmon.out > $(BUILD_DIR)/prof_call_graph.txt diff --git a/FreeRTOS/Demo/Posix_GCC/Readme.md b/FreeRTOS/Demo/Posix_GCC/Readme.md new file mode 100644 index 0000000000..a3bb352b7a --- /dev/null +++ b/FreeRTOS/Demo/Posix_GCC/Readme.md @@ -0,0 +1,64 @@ +# Profilig your application + +## Introduction [(from the official gprof doc)](https://sourceware.org/binutils/docs/gprof/Introduction.html#Introduction) +Profiling allows you to learn where your program spent its time and which +functions called which other functions while it was executing. This information +can show you which pieces of your program are slower than you expected, and +might be candidates for rewriting to make your program execute faster. It can +also tell you which functions are being called more or less often than you +expected. This may help you spot bugs that had otherwise been unnoticed. + +## Requirements +### gprof +Version as tested: GNU gprof (GNU Binutils) 2.36 +### make +Version as tested: GNU Make 3.82 +### gcc +Version as tested: gcc (GCC) 11.0.0 + +## Generating Profiles +``` +$ make PROFILE=1 +``` +Run your application +``` +$ ./build/possix_demo +``` +Since FreeRTOS and its application never come to an end and typically run +forever. The user has to kill the application with **Ctrl_C** when they feel +satisfied that the application achieved its indented task. Killing the +application will force the profiling file *gmon.out* to be generated +automatically. +In order to make sense of this file, the user has to convert the file with: +``` +$ make profile +``` +two (2) files *prof_call_graph.txt* and *prof_flat.txt* will be generated in the +build directory. +In order to understand the outputs generated, the best way is to read the +official documentation of gprof [here](https://sourceware.org/binutils/docs/gprof/Output.html#Output) + + +# Run your application with Sanitizers +## Introduction +* AddressSanitizer, a fast memory error detector. Memory +access instructions are instrumented to detect out-of-bounds and use-after-free +bugs +* LeakSanitizer, a memory leak detector. This option only matters for linking of +executables and the executable is linked against a library that overrides malloc +and other allocator functions + +## Requirements +### gcc +Version as tested: gcc (GCC) 11.0.0 +## Building and Running the Application +``` +$ make SANITIZE_ADDRESS=1 +or +$ make SANITIZE_LEAK=1 +``` +Then run your program normally. +``` +$ ./build/possix_demo +``` +If an error is detected by the sanitizer, a report showing the error will be printed to stdout. diff --git a/FreeRTOS/Demo/Posix_GCC/main.c b/FreeRTOS/Demo/Posix_GCC/main.c index 01acbf4890..8f1fd8aa66 100644 --- a/FreeRTOS/Demo/Posix_GCC/main.c +++ b/FreeRTOS/Demo/Posix_GCC/main.c @@ -55,6 +55,8 @@ #include #include #include +#include +#include /* FreeRTOS kernel includes. */ #include "FreeRTOS.h" @@ -68,6 +70,12 @@ #define mainSELECTED_APPLICATION BLINKY_DEMO +#ifdef BUILD_DIR + #define BUILD BUILD_DIR +#else + #define BUILD "./" +#endif + /* This demo uses heap_3.c (the libc provided malloc() and free()). */ /*-----------------------------------------------------------*/ @@ -103,6 +111,12 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, */ static void prvSaveTraceFile( void ); +/* + * Signal handler for Ctrl_C to cause the program to exit, and generate the + * profiling info. + */ +static void handle_sigint(int signal); + /*-----------------------------------------------------------*/ /* When configSUPPORT_STATIC_ALLOCATION is set to 1 the application writer can @@ -117,8 +131,13 @@ static BaseType_t xTraceRunning = pdTRUE; /*-----------------------------------------------------------*/ + + int main( void ) { + /* SIGINT is not blocked by the posix port */ + signal( SIGINT, handle_sigint ); + /* Do not include trace code when performing a code coverage analysis. */ #if ( projCOVERAGE_TEST != 1 ) { @@ -231,13 +250,13 @@ void vApplicationTickHook( void ) void traceOnEnter() { - int ret; + int xReturn; struct timeval tv = { 0L, 0L }; fd_set fds; FD_ZERO(&fds); FD_SET(0, &fds); - ret = select(1, &fds, NULL, NULL, &tv); - if ( ret > 0 ) + xReturn = select(1, &fds, NULL, NULL, &tv); + if ( xReturn > 0 ) { if( xTraceRunning == pdTRUE ) { @@ -386,3 +405,14 @@ the stack and so not exists after this function exits. */ configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } + +void handle_sigint( int signal ) +{ + int xReturn; + xReturn = chdir( BUILD ); /* changing dir to place gmon.out inside build */ + if( xReturn == -1 ) + { + printf( "chdir into %s error is %d\n", BUILD, errno ); + } + exit( 1 ); +}