Skip to content

Commit 5af4195

Browse files
committed
Added support of allocators names
1 parent a647846 commit 5af4195

3 files changed

Lines changed: 70 additions & 7 deletions

File tree

inc/dmod_sal.h

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ extern "C" {
6767
* @{
6868
*/
6969
#if defined(DMOD_MODULE_NAME)
70-
# define Dmod_Malloc(Size) Dmod_MallocEx(Size, Dmod_GetCurrentModuleName())
71-
# define Dmod_Realloc(Ptr, Size) Dmod_ReallocEx(Ptr, Size, Dmod_GetCurrentModuleName())
72-
# define Dmod_AlignedMalloc(Size, Alignment) Dmod_AlignedMallocEx(Size, Alignment, Dmod_GetCurrentModuleName(DMOD_MODULE_NAME))
70+
# define Dmod_Malloc(Size) Dmod_MallocEx(Size, Dmod_GetCurrentAllocatorName())
71+
# define Dmod_Realloc(Ptr, Size) Dmod_ReallocEx(Ptr, Size, Dmod_GetCurrentAllocatorName())
72+
# define Dmod_AlignedMalloc(Size, Alignment) Dmod_AlignedMallocEx(Size, Alignment, Dmod_GetCurrentAllocatorName(DMOD_MODULE_NAME))
7373
# define Dmod_Free(Ptr) Dmod_FreeEx(Ptr, false)
7474
#else
7575
DMOD_BUILTIN_API(Dmod, 1.0, void*, _Malloc , ( size_t Size ) );
@@ -199,13 +199,36 @@ DMOD_BUILTIN_API(Dmod, 1.0, size_t, _ReadKernel, ( void* Buffer, size_t Size )
199199
# define Dmod_GetCurrentModuleName() Dmod_GetCurrentModuleNameEx(NULL)
200200
#endif
201201

202+
/**
203+
* @brief Name used to attribute heap allocations (Dmod_Malloc/Dmod_MallocEx/...) to their owner.
204+
*
205+
* This is deliberately a *separate* identity from Dmod_GetCurrentModuleName(): the module name
206+
* is not unique when the same module is loaded more than once at the same time (e.g. a shell
207+
* spawning another instance of itself in the background) - two independent Dmod_Context_t's
208+
* end up sharing one name. Allocation tracking (dmheap and similar) keys everything off this
209+
* string, including bulk-freeing all of a module's memory on unload (Dmod_FreeModule) - if two
210+
* live instances shared that key, unloading one would free memory the other is still using.
211+
*
212+
* The default (weak) implementation just falls back to the module name, same as
213+
* Dmod_GetCurrentModuleName() - a platform without real process tracking has no way to tell two
214+
* instances apart anyway. A real implementation (see the dmosi glue layer) can return something
215+
* that also incorporates the current process's identity (e.g. name + PID), which is unique per
216+
* spawned instance even when the module name repeats.
217+
*/
218+
#ifdef DMOD_MODULE_NAME
219+
# define Dmod_GetCurrentAllocatorName() Dmod_GetCurrentAllocatorNameEx(DMOD_MODULE_NAME)
220+
#else
221+
# define Dmod_GetCurrentAllocatorName() Dmod_GetCurrentAllocatorNameEx(NULL)
222+
#endif
223+
202224
DMOD_BUILTIN_API(Dmod, 1.0, const char*, _GetEnv, ( const char* Name ) );
203225
DMOD_BUILTIN_API(Dmod, 1.0, int, _SetEnv, ( const char* Name, const char* Value, int Overwrite ) );
204226
DMOD_BUILTIN_API(Dmod, 1.0, int, _Unsetenv, ( const char* Name ) );
205227
DMOD_BUILTIN_API(Dmod, 1.0, const char*, _GetNextEnvName, ( const char* Last ) );
206228
DMOD_BUILTIN_API(Dmod, 1.0, int, _EnvCtx_Push, ( void ) );
207229
DMOD_BUILTIN_API(Dmod, 1.0, int, _EnvCtx_Pop, ( void ) );
208230
DMOD_BUILTIN_API(Dmod, 1.0, const char*, _GetCurrentModuleNameEx, ( const char* Default ) );
231+
DMOD_BUILTIN_API(Dmod, 1.0, const char*, _GetCurrentAllocatorNameEx, ( const char* Default ) );
209232

210233
//! @}
211234

src/system/dmod_system.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -716,8 +716,21 @@ Dmod_Context_t* Dmod_LoadModuleByName(const char* ModuleName)
716716

717717
if(Dmod_Mgr_IsLoaded(ModuleName))
718718
{
719-
DMOD_LOG_INFO("Module %s is already loaded\n", ModuleName);
720-
return Dmod_Context_Get(ModuleName);
719+
Dmod_Context_t* existing = Dmod_Context_Get(ModuleName);
720+
721+
// Only Library modules are shared singletons (drivers etc. must stay one
722+
// instance). Application modules are not: reusing an already-loaded
723+
// Application's context here would hand out the SAME context (and so the
724+
// same Dmod_Run() mutex) to a second, concurrent invocation - which would
725+
// then block forever waiting for a mutex the first, still-running instance
726+
// never releases, instead of getting its own independent run. So for an
727+
// Application module that's already loaded, fall through and load a fresh,
728+
// independent context instead of reusing this one.
729+
if( existing != NULL && Dmod_GetModuleType( existing ) != Dmod_ModuleType_Application )
730+
{
731+
DMOD_LOG_INFO("Module %s is already loaded\n", ModuleName);
732+
return existing;
733+
}
721734
}
722735

723736
Dmod_SearchNode_t* searchNode = Dmod_Hlp_PrepareModulesSearchNodes();
@@ -783,8 +796,17 @@ Dmod_Context_t* Dmod_LoadModuleFromPackage(const char* ModuleName, const char* P
783796

784797
if(Dmod_Mgr_IsLoaded(ModuleName))
785798
{
786-
DMOD_LOG_INFO("Module %s is already loaded\n", ModuleName);
787-
return Dmod_Context_Get(ModuleName);
799+
Dmod_Context_t* existing = Dmod_Context_Get(ModuleName);
800+
801+
// See the matching comment in Dmod_LoadModuleByName: only Library modules
802+
// are shared singletons - an already-loaded Application module keeps its
803+
// own context so a concurrent second run doesn't deadlock on the first
804+
// instance's Dmod_Run() mutex.
805+
if( existing != NULL && Dmod_GetModuleType( existing ) != Dmod_ModuleType_Application )
806+
{
807+
DMOD_LOG_INFO("Module %s is already loaded\n", ModuleName);
808+
return existing;
809+
}
788810
}
789811

790812
Dmod_Context_t* context = Dmod_LoadFromPackage( PackageName, ModuleName );

src/system/if/dmod_if_env.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,22 @@ DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, const char*, _GetCurrentModuleNameEx,
247247
{
248248
/* The default implementation simply returns the provided default name. */
249249
return Default;
250+
}
251+
252+
/**
253+
* @brief Get the name used to attribute heap allocations to their owner
254+
*
255+
* This is a weak implementation with no real process tracking to draw on, so it can't
256+
* tell apart two concurrently loaded instances of the same module - it just falls back
257+
* to the module name, same as Dmod_GetCurrentModuleNameEx(). The real implementation
258+
* should be provided by the dmosi layer, which can incorporate process identity (e.g.
259+
* name + PID) to give each spawned instance its own unique allocator name.
260+
*
261+
* @param Default The default name to return if no better allocator name is available
262+
*
263+
* @return The current allocator name, or Default if it cannot be determined
264+
*/
265+
DMOD_INPUT_WEAK_API_DECLARATION(Dmod, 1.0, const char*, _GetCurrentAllocatorNameEx, ( const char* Default ))
266+
{
267+
return Default;
250268
}

0 commit comments

Comments
 (0)