Skip to content

Hunk Memory, The memory allocator (Refacator ideas)

Victor Roemer edited this page Aug 4, 2022 · 4 revisions

In practice, the hunk memory is just a pre-allocated mempool for the mutable state of the game engine and it's modules.

/*
============================
CL_StartHunkUsers

After the server has cleared the hunk, these will need to be restarted
This is the only place that any of these functions are called from
============================
*/

void CL_StartHunkUsers(bool rendererOnly)

        cls.rendererStarted = true;
        CL_InitRenderer();


        cls.soundStarted = true;
        S_Init();

        cls.soundRegistered = true;
        S_BeginRegistration();

        cls.uiStarted = true;
        CL_InitUI();

Rediculous amount of stuff happening

Com_InitHunkMemory

void Com_InitHunkMemory( void )
{
1. Hunk Initializer needs to operate independently of any other engine components.
 
    // make sure the file system has allocated and "not" freed any temp blocks
    // this allows the config and product id files ( journal files too ) to be loaded
    // by the file system without redunant routines in the file system utilizing different
    // memory systems
    if (FS_LoadStack() != 0)
        Com_Error( ERR_FATAL, "Hunk initialization failed. File system load stack not zero");

2. Must not be consuming user input directly

    // allocate the stack based hunk allocator
    cv = Cvar_Get( "com_hunkMegs", DEF_COMHUNKMEGS_S, CVAR_LATCH | CVAR_ARCHIVE );
    Cvar_SetDescription(cv, "The size of the hunk memory segment");

3. again, more user input

    // if we are not dedicated min allocation is 56, otherwise min is 1
    if (com_dedicated && com_dedicated->integer)
    {
        nMinAlloc = MIN_DEDICATED_COMHUNKMEGS;
        pMsg = "Minimum com_hunkMegs for a dedicated server is %i, allocating %i megs.\n";
    }
    else
    {
        nMinAlloc = MIN_COMHUNKMEGS;
        pMsg = "Minimum com_hunkMegs is %i, allocating %i megs.\n";
    }

4. This is probably okay

    s_hunkData = (byte*)calloc( s_hunkTotal + 31, 1 );
    if ( !s_hunkData )
    {
        Com_Error( ERR_FATAL, "Hunk data failed to allocate %i megs", s_hunkTotal / (1024*1024) );
    }
    // cacheline align
    s_hunkData = (byte *) ( ( (intptr_t)s_hunkData + 31 ) & ~31 );
    Hunk_Clear();


5. But this is not

    Cmd_AddCommand( "meminfo", Com_Meminfo_f );
    Cmd_AddCommand( "zonelog", Z_LogHeap );
    Cmd_AddCommand( "hunklog", Hunk_Log );
    Cmd_AddCommand( "hunksmalllog", Hunk_SmallLog );

}

Init should probably be called only a single time ever, from main().

Hunk Clear

void Hunk_Clear( void )
{
#ifndef DEDICATED
    CL_ShutdownCGame();
    CL_ShutdownUI();
#endif
     SV_ShutdownGameProgs();
#ifndef DEDICATED
    CIN_CloseAllVideos();
#endif
  1. All the shutdown calls need to be lifted

Reset state of the allocated address space.

Hunk_Log

void Hunk_Log( void)

Remove this altogether

Hunk_SetMark, Hunk_ClearToMark

/*
===================
Hunk_SetMark

The server calls this after the level and game VM have been loaded
===================
*/
void Hunk_SetMark( void )

/*
=================
Hunk_ClearToMark

The client calls this before starting a vid_restart or snd_restart
=================
*/
void Hunk_ClearToMark( void )

Set's a offset to the games allocated memory positions. Used to optimize easure?

Hunk_SwapBanks

static void Hunk_SwapBanks( void )
{
    hunkUsed_t *swap;

    // can't swap banks if there is any temp already allocated
    if ( hunk_temp->temp != hunk_temp->permanent )
        return;

    // if we have a larger highwater mark on this side, start making
    // our permanent allocations here and use the other side for temp
    if ( hunk_temp->tempHighwater - hunk_temp->permanent
            > hunk_permanent->tempHighwater - hunk_permanent->permanent )
    {
        swap = hunk_temp;
        hunk_temp = hunk_permanent;
        hunk_permanent = swap;
    }
}

Fascinating function

Hunk Alloc

/*
=================
Hunk_Alloc

Allocate permanent (until the hunk is cleared) memory
=================
*/
#ifdef HUNK_DEBUG
void *Hunk_AllocDebug( int size, ha_pref preference, const char *label, const char *file, int line )
#else
void *Hunk_Alloc( int size, ha_pref preference )
#endif
{

    // can't do preference if there is any temp allocated
    if (preference == h_dontcare || hunk_temp->temp != hunk_temp->permanent) {
        Hunk_SwapBanks();
    } else {
        if (preference == h_low && hunk_permanent != &hunk_low) {
            Hunk_SwapBanks();
        } else if (preference == h_high && hunk_permanent != &hunk_high) {
            Hunk_SwapBanks();
        }
    }

What is happening,