Skip to content

Commit

Permalink
sys: add malloc_monitor, deprecate malloc_tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
mguetschow committed Mar 26, 2024
1 parent e6f03db commit f31f820
Show file tree
Hide file tree
Showing 16 changed files with 656 additions and 2 deletions.
4 changes: 4 additions & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,11 @@ PSEUDOMODULES += libc_gettimeofday
## @defgroup pseudomodule_malloc_tracing malloc_tracing
## @brief Debug dynamic memory management by hooking in a print into each call
## of malloc(), calloc(), realloc() and free
## @{
## @deprecated Use module `malloc_monitor` with verbous configuration instead;
## will be removed after 2024.07 release.
PSEUDOMODULES += malloc_tracing
## @}

## @defgroup pseudomodule_mpu_stack_guard mpu_stack_guard
## @brief MPU based stack guard
Expand Down
1 change: 1 addition & 0 deletions sys/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ rsource "evtimer/Kconfig"
rsource "log_color/Kconfig"
rsource "log_printfnoformat/Kconfig"
rsource "luid/Kconfig"
rsource "malloc_monitor/Kconfig"
rsource "malloc_thread_safe/Kconfig"
rsource "matstat/Kconfig"
rsource "memarray/Kconfig"
Expand Down
59 changes: 59 additions & 0 deletions sys/include/malloc_monitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2024 TU Dresden
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_malloc_monitor
* @{
*/

#ifndef MALLOC_MONITOR_H
#define MALLOC_MONITOR_H

#include <assert.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "architecture.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Obtain current heap memory usage.
*
* @return current heap memory usage in bytes
*/
size_t malloc_monitor_get_usage_current(void);

/**
* @brief Obtain maximum heap memory usage since last call to
* @ref malloc_monitor_reset_high_watermark().
*
* @return maximum heap memory usage in bytes
*/
size_t malloc_monitor_get_usage_high_watermark(void);

/**
* @brief Reset maximum heap memory usage.
*
* After calling this function, @ref malloc_monitor_get_usage_high_watermark()
* will return @ref malloc_monitor_get_usage_current() until further changes
* to heap memory usage.
*/
void malloc_monitor_reset_high_watermark(void);

#ifdef __cplusplus
}
#endif

#endif /* MALLOC_MONITOR_H */

/**
* @}
*/
73 changes: 73 additions & 0 deletions sys/include/malloc_monitor_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2024 TU Dresden
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_malloc_monitor_internals Heap Memory Usage Monitor internals
* @ingroup sys_malloc_monitor
* @{
*
* @brief internals for monitoring heap memory usage (calls to malloc/calloc/realloc/free)
* @author Mikolai Gütschow <mikolai.guetschow@tu-dresden.de>
*/

#ifndef MALLOC_MONITOR_INTERNAL_H
#define MALLOC_MONITOR_INTERNAL_H

#include <assert.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "architecture.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Record malloc/calloc/realloc call increasing heap usage.
*
* @param[in] ptr pointer to newly allocated memory
* @param[in] size size of newly allocated memory
* @param[in] pc PC of calling function
* @param[in] func_prefix prefix identifying memory function, one of "m","c","re"
*
* @internal
*/
void malloc_monitor_add(void *ptr, size_t size, uinttxtptr_t pc, char *func_prefix);

/**
* @brief Record free/realloc call decreasing heap usage.
*
* @param[in] ptr pointer to memory that is being freed
* @param[in] pc PC of calling function
*
* @internal
*/
void malloc_monitor_rm(void *ptr, uinttxtptr_t pc);

/**
* @brief Record realloc call either increasing or decreasing heap usage.
*
* @param[in] ptr_old pointer to previously allocated memory
* @param[in] ptr_new pointer to newly allocated memory
* @param[in] size_new size of newly allocated memory
* @param[in] pc PC of calling function
*
* @internal
*/
void malloc_monitor_mv(void *ptr_old, void *ptr_new, size_t size_new, uinttxtptr_t pc);

#ifdef __cplusplus
}
#endif

#endif /* MALLOC_MONITOR_INTERNAL_H */

/**
* @}
*/
23 changes: 23 additions & 0 deletions sys/malloc_monitor/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (C) 2024 TU Dresden
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#

menuconfig MODULE_SYS_MALLOC_MONITOR
bool "Heap Memory Usage Monitor"

config MODULE_SYS_MALLOC_MONITOR_SIZE
int "Monitor Size"
default 100
depends on MODULE_SYS_MALLOC_MONITOR
help
Specifies maximum number of pointers that can be monitored at once.

config MODULE_SYS_MALLOC_MONITOR_VERBOSE
bool "Verbose"
default false
depends on MODULE_SYS_MALLOC_MONITOR
help
Print detailed log of calls to malloc/realloc/free
1 change: 1 addition & 0 deletions sys/malloc_monitor/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base
1 change: 1 addition & 0 deletions sys/malloc_monitor/Makefile.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
USEMODULE += malloc_thread_safe
72 changes: 72 additions & 0 deletions sys/malloc_monitor/doc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* @defgroup sys_malloc_monitor Heap Memory Usage Monitor
* @ingroup sys_memory_management
* @brief This module allows to monitor the dynamic memory usage of a certain piece of code.
* @warning This module automatically selects @ref sys_malloc_ts and naturally
* incurs a certain runtime overhead. It is not meant for production usage.
* @author Mikolai Gütschow <mikolai.guetschow@tu-dresden.de>
*
* # Description
*
* This module allows to monitor the dynamic memory usage of a certain piece of code.
* It works by hooking into (wrappers to) @ref malloc(), @ref calloc(), @ref realloc(),
* and @ref free() calls to internally record the current and all-time maximum heap memory usage.
*
* Note that in general dynamic memory management is a bad idea on the constrained devices RIOT
* is targeting. So maybe it is better to just adapt your code to use static memory management instead.
*
* # Usage
*
* Enable the module with `USEMODULE += malloc_monitor`.
*
* Add `#include "malloc_monitor.h"` to the file in which you want to monitor dynamic memory usage.
* Use @ref malloc_monitor_get_usage_current() to retrieve the size of the currently allocated
* heap memory in bytes. @ref malloc_monitor_get_usage_high_watermark() returns the all-time maximum
* since startup or the last call to @ref malloc_monitor_reset_high_watermark().
*
* Note that `malloc_monitor` currently has no notion of threads and will at any point in time report
* the global dynamic memory usage, not the one used by the currently running thread.
* Thread-safety is achieved through usage of @ref sys_malloc_ts, though.
*
* ## Example
*
* Imagine you want to investigate the dynamic memory consumption of a certain function `func()`.
* The following snippet could get you started:
*
* ```c
* #include <stddef.h>
* #include <stdio.h>
*
* #include "malloc_monitor.h"
*
* int main(void)
* {
* size_t before = malloc_monitor_get_usage_current();
* size_t before_max = malloc_monitor_get_usage_high_watermark();
* func();
* size_t after = malloc_monitor_get_usage_current();
* size_t after_max = malloc_monitor_get_usage_high_watermark();
*
* if (after != before) {
* puts("func() " (after < before ? "decreased" : "increased") " global dynamic memory usage.");
* }
* printf("The maximal dynamic memory usage of func() was %d bytes.", after_max - before_max);
* }
* ```
*
* For further usage examples, refer to the corresponding tests in `tests/sys/malloc_monitor`.
*
* # Configuration
*
* The maximum number of pointers that can be monitored at once can be set with Kconfig
* in System > Heap Memory Usage Monitor > Monitor Size or by setting the corresponding
* CFlag in your application's Makefile as `CFLAGS += CONFIG_MODULE_SYS_MALLOC_MONITOR_SIZE=42`.
* It defaults to 100.
*
* For more fine-grained debugging of invalid calls to @ref free(), duplicated calls to @ref free(),
* or memory leaks, the module can be configured to print information on every call to @ref malloc(),
* @ref calloc(), @ref realloc(), or @ref free() by setting System > Heap Memory Usage Monitor > Verbose
* or adding `CFLAGS += CONFIG_MODULE_SYS_MALLOC_MONITOR_VERBOSE=1` to your Makefile.
* `malloc_monitor` defaults to be non-verbose.
*
*/
Loading

0 comments on commit f31f820

Please sign in to comment.