#include "core_memory_private.h"

enum {
    HUNK_TOUCH_WORD_SHIFT = 2,
    HUNK_TOUCH_WORD_STRIDE = 64
};

void Com_TouchMemory(void)
{
    int32_t checksum;
    ptrdiff_t stopWord;
    ptrdiff_t touchWord;
    int32_t startTime;
    int32_t endTime;
    int32_t *hunkWords;

    startTime = Sys_Milliseconds();
    checksum = 0;
    hunkWords = (int32_t *)hunk_base;

    stopWord = (ptrdiff_t)hunk.lowUsed >> HUNK_TOUCH_WORD_SHIFT;
    for (touchWord = 0; touchWord < stopWord;
         touchWord += HUNK_TOUCH_WORD_STRIDE) {
        checksum += hunkWords[touchWord];
    }

    touchWord = (ptrdiff_t)(hunk.totalSize - hunk.highUsed) >>
                HUNK_TOUCH_WORD_SHIFT;
    /* ORIGINAL_BINARY_BUG: stock stops at highUsed/4 rather than totalSize/4,
     * so it normally touches none of the high allocation; preserved per
     * original-bugs/coduomp-touchmemory-high-hunk-pretouch.md. */
    stopWord = (ptrdiff_t)hunk.highUsed >> HUNK_TOUCH_WORD_SHIFT;
    for (; touchWord < stopWord;
         touchWord += HUNK_TOUCH_WORD_STRIDE) {
        checksum += hunkWords[touchWord];
    }

    endTime = Sys_Milliseconds();
    Com_Printf("Com_TouchMemory: %i msec. Using sum: %d\n",
               endTime - startTime, checksum);
}

void XModelClearData(void *rangeStart, void *rangeEnd);
void FS_ClearDataForFiles(const void *rangeStart, const void *rangeEnd);

void Hunk_RetouchMemory(void)
{
    uint8_t *rangeStart;
    uint8_t *rangeEnd;

    rangeStart = hunk_base + hunk.lowUsed;
    rangeEnd = hunk_base + hunk.totalSize - hunk.highUsed;

    XModelClearData(rangeStart, rangeEnd);
    FS_ClearDataForFiles(rangeStart, rangeEnd);
}
