Enable profiling for the linux port

This commit is contained in:
Alfred Gedeon
2021-05-17 16:29:16 -07:00
committed by alfred gedeon
parent 784fb8c157
commit a2029c781c
3 changed files with 174 additions and 55 deletions

View File

@ -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

View File

@ -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.

View File

@ -55,6 +55,8 @@
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <signal.h>
#include <errno.h>
/* 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 );
}