From 8b9412cbbf11d25b4d3d2cbd8337e828c6eaacb3 Mon Sep 17 00:00:00 2001 From: Patryk Kubiak Date: Sat, 17 Oct 2026 20:01:08 +0200 Subject: [PATCH] Dmod_MallocTagged: memory of a kind, else the default memory Tags - kinds of memory, preferred first, separated by commas ("fast", "dma", ...) - as the system tags its heaps (dmheap: a heap's name is the list of its tags). A kind the system does not have, or one without room: the next one, at last Dmod_MallocEx()'s memory. The default implementation is Dmod_MallocEx(), so a module asks for what it gains from and works anywhere - on the host too. Co-Authored-By: Claude Opus 5.5 --- inc/dmod_sal.h | 18 +++++++++++++ src/system/if/dmod_if_mem.c | 17 ++++++++++++ tests/system/if/CMakeLists.txt | 1 + tests/system/if/tests_dmod_malloc_tagged.cpp | 28 ++++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 tests/system/if/tests_dmod_malloc_tagged.cpp diff --git a/inc/dmod_sal.h b/inc/dmod_sal.h index 7658b30..eb38a47 100644 --- a/inc/dmod_sal.h +++ b/inc/dmod_sal.h @@ -89,11 +89,29 @@ extern "C" { #define Dmod_Malloc(Size) Dmod_MallocEx(Size, DMOD_CURRENT_ALLOCATOR) #define Dmod_Realloc(Ptr, Size) Dmod_ReallocEx(Ptr, Size, DMOD_CURRENT_ALLOCATOR) #define Dmod_AlignedMalloc(Size, Alignment) Dmod_AlignedMallocEx(Size, Alignment, DMOD_CURRENT_ALLOCATOR) +#define Dmod_MallocTagged(Tags, Size) Dmod_MallocTaggedEx(Tags, Size, DMOD_CURRENT_ALLOCATOR) #define Dmod_Free(Ptr) Dmod_FreeEx(Ptr, false) DMOD_BUILTIN_API(Dmod, 1.0, void*, _MallocEx, ( size_t Size, const char* ModuleName ) ); DMOD_BUILTIN_API(Dmod, 1.0, void*, _ReallocEx, ( void* Ptr, size_t Size, const char* ModuleName ) ); DMOD_BUILTIN_API(Dmod, 1.0, void , _FreeEx , ( void* Ptr, bool Concatenate ) ); DMOD_BUILTIN_API(Dmod, 1.0, void*, _AlignedMallocEx, ( size_t Size, size_t Alignment, const char* ModuleName ) ); +/** + * @brief Allocate memory of a kind - the system's heaps tagged with it - else the default memory. + * + * Tags is a list of the kinds wanted, separated by commas, the preferred one first: "fast" + * (internal RAM worth giving to what is worked on all the time), "dma" (memory DMA reaches + * without cache maintenance), ... - as the system tags its heaps (dmheap: a heap's name is + * the list of its tags). A kind the system does not have, or one without room: the next one, + * at last what Dmod_MallocEx() gives - so a module asks for what it gains from and still works + * everywhere. Freed with Dmod_Free(). The default implementation is Dmod_MallocEx(). + * + * @param Tags The kinds of memory, preferred first (NULL or "": the default memory) + * @param Size Size of memory to allocate + * @param ModuleName Allocation owner, as Dmod_MallocEx() understands it + * + * @return Pointer to the allocated memory, NULL when there is none + */ +DMOD_BUILTIN_API(Dmod, 1.0, void*, _MallocTaggedEx, ( const char* Tags, size_t Size, const char* ModuleName ) ); DMOD_BUILTIN_API(Dmod, 1.0, void, _FreeModule, ( const char* ModuleName ) ); DMOD_BUILTIN_API(Dmod, 1.0, bool, _RetagEx, ( void* Ptr, const char* ModuleName ) ); DMOD_BUILTIN_API(Dmod, 1.0, bool, _RenameTag, ( const char* OldTag, const char* NewTag ) ); diff --git a/src/system/if/dmod_if_mem.c b/src/system/if/dmod_if_mem.c index 33dcb01..14100b3 100644 --- a/src/system/if/dmod_if_mem.c +++ b/src/system/if/dmod_if_mem.c @@ -64,6 +64,23 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void*, _MallocEx, ( size_t Size, cons #endif } +/** + * @brief Allocate memory of a kind (see dmod_sal.h) + * + * Without heaps of kinds (dmheap provides them on a device): the default memory. + * + * @param Tags Kinds of memory wanted, preferred first - not used here + * @param Size Size of memory to allocate + * @param ModuleName Name of the module requesting memory + * + * @return Pointer to allocated memory + */ +DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, void*, _MallocTaggedEx, ( const char* Tags, size_t Size, const char* ModuleName )) +{ + (void)Tags; + return Dmod_MallocEx(Size, ModuleName); +} + /** * @brief Reallocate memory * diff --git a/tests/system/if/CMakeLists.txt b/tests/system/if/CMakeLists.txt index 8b8c405..068ba44 100644 --- a/tests/system/if/CMakeLists.txt +++ b/tests/system/if/CMakeLists.txt @@ -2,6 +2,7 @@ set(TEST_SOURCES ${TEST_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_rawmem.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_mock_memory.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_malloc_tagged.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_dir.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_snprintf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tests_dmod_env.cpp diff --git a/tests/system/if/tests_dmod_malloc_tagged.cpp b/tests/system/if/tests_dmod_malloc_tagged.cpp new file mode 100644 index 0000000..0e77530 --- /dev/null +++ b/tests/system/if/tests_dmod_malloc_tagged.cpp @@ -0,0 +1,28 @@ +#define DMOD_PRIVATE +#include +#include +#include "dmod_sal.h" + +// =============================================================== +// Tests for Dmod_MallocTaggedEx +// =============================================================== + +/** + * @brief Without heaps of kinds (dmheap gives them on a device) memory of any + * kind is the default memory - a module asking for one works anywhere + */ +TEST(DmodMallocTaggedTest, WithoutHeapsOfKindsTheDefaultMemory) +{ + void* fast = Dmod_MallocTaggedEx("fast,dma", 64, "tests_dmod_malloc_tagged"); + ASSERT_NE(fast, nullptr); + memset(fast, 0xA5, 64); + Dmod_FreeEx(fast, false); + + void* any = Dmod_MallocTaggedEx(NULL, 32, "tests_dmod_malloc_tagged"); + ASSERT_NE(any, nullptr); + Dmod_FreeEx(any, false); + + any = Dmod_MallocTaggedEx("", 32, "tests_dmod_malloc_tagged"); + ASSERT_NE(any, nullptr); + Dmod_FreeEx(any, false); +}