Skip to content

Commit efa8171

Browse files
grahamroff-devhenrikbrixandersen
authored andcommitted
lib: libc: common: Add malloc heap stats support
Add support for retrieving heap stats for the malloc heap in the common libc malloc implementation. This provides the ability to see free and used bytes using the same structure as the kernel heap. Without this there is no method to retrieve the malloc heap usage as the relevant sys_heap structure is private. Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com>
1 parent c6ab2e2 commit efa8171

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
*
10+
* @brief Zephyr common libc malloc extensions
11+
*/
12+
13+
#ifndef ZEPHYR_LIB_LIBC_COMMON_INCLUDE_SYS_MALLOC_H_
14+
#define ZEPHYR_LIB_LIBC_COMMON_INCLUDE_SYS_MALLOC_H_
15+
16+
#include <zephyr/sys/sys_heap.h>
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
/**
23+
* @brief Get the runtime statistics of the malloc heap
24+
*
25+
* @kconfig_dep{CONFIG_SYS_HEAP_RUNTIME_STATS}
26+
*
27+
* @param stats Pointer to struct to copy statistics into
28+
* @return -EINVAL if null pointers, otherwise 0
29+
*/
30+
int malloc_runtime_stats_get(struct sys_memory_stats *stats);
31+
32+
#ifdef __cplusplus
33+
}
34+
#endif
35+
36+
#endif /* ZEPHYR_LIB_LIBC_COMMON_INCLUDE_SYS_MALLOC_H_ */

‎lib/libc/common/source/stdlib/malloc.c‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,23 @@ void free(void *ptr)
262262
malloc_unlock();
263263
}
264264

265+
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
266+
267+
int malloc_runtime_stats_get(struct sys_memory_stats *stats)
268+
{
269+
int ret;
270+
271+
malloc_lock();
272+
273+
ret = sys_heap_runtime_stats_get(&z_malloc_heap, stats);
274+
275+
malloc_unlock();
276+
277+
return ret;
278+
}
279+
280+
#endif /* CONFIG_SYS_HEAP_RUNTIME_STATS */
281+
265282
SYS_INIT(malloc_prepare, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_LIBC);
266283
#else /* No malloc arena */
267284
void *malloc(size_t size)

‎tests/lib/c_lib/common/prj.conf‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ CONFIG_ZTEST_FATAL_HOOK=y
44
CONFIG_MINIMAL_LIBC_NON_REENTRANT_FUNCTIONS=y
55
CONFIG_MINIMAL_LIBC_RAND=y
66
CONFIG_POSIX_C_LANG_SUPPORT_R=y
7+
CONFIG_SYS_HEAP_RUNTIME_STATS=y

‎tests/lib/c_lib/common/src/main.c‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
#ifdef CONFIG_NEWLIB_LIBC
4444
#include <unistd.h>
4545
#endif
46+
#ifdef CONFIG_COMMON_LIBC_MALLOC
47+
#include <sys_malloc.h>
48+
#endif
4649

4750
#define STACK_SIZE (512 + CONFIG_TEST_EXTRA_STACK_SIZE)
4851
#define LIST_LEN 2
@@ -1313,6 +1316,47 @@ ZTEST(libc_common, test_exit)
13131316
zassert_equal(a, 0, "exit failed");
13141317
#endif
13151318
}
1319+
1320+
/**
1321+
*
1322+
* @brief Test malloc and associated functions.
1323+
*
1324+
*/
1325+
ZTEST(libc_common, test_malloc)
1326+
{
1327+
#if defined(CONFIG_COMMON_LIBC_MALLOC) && CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE > 220
1328+
char *buf = NULL, *temp_buf = NULL;
1329+
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
1330+
int rc;
1331+
struct sys_memory_stats pre_malloc_stats, post_malloc_stats;
1332+
1333+
rc = malloc_runtime_stats_get(&pre_malloc_stats);
1334+
zassert_equal(rc, 0, "malloc_runtime_stats_get_failed: %d", rc);
1335+
#endif
1336+
1337+
buf = malloc(100);
1338+
zassert_not_null(buf, "malloc failed");
1339+
1340+
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS
1341+
rc = malloc_runtime_stats_get(&post_malloc_stats);
1342+
zassert_equal(rc, 0, "malloc_runtime_stats_get_failed: %d", rc);
1343+
zassert(pre_malloc_stats.free_bytes - post_malloc_stats.free_bytes >= 100,
1344+
"malloc_runtime_stats_get failed, free bytes did not reduce as expected");
1345+
zassert(post_malloc_stats.allocated_bytes - pre_malloc_stats.allocated_bytes >= 100,
1346+
"malloc_runtime_stats_get failed, used bytes did not increase as expected");
1347+
#endif
1348+
1349+
temp_buf = realloc(buf, 200);
1350+
zassert_not_null(temp_buf, "realloc failed");
1351+
if (temp_buf != NULL) {
1352+
buf = temp_buf;
1353+
}
1354+
1355+
free(buf);
1356+
#else
1357+
ztest_test_skip();
1358+
#endif /* CONFIG_COMMON_LIBC_MALLOC && CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE > 220 */
1359+
}
13161360
/**
13171361
* @}
13181362
*/

0 commit comments

Comments
 (0)