Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions Generals/Code/GameEngine/Source/Common/System/GameMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,12 @@ static Bool theMainInitFlag = false;
// PRIVATE PROTOTYPES
// ----------------------------------------------------------------------------

/// @todo srj -- make this work for 8
#define MEM_BOUND_ALIGNMENT 4
// User data alignment, matches the 8 byte alignment that operator new guarantees on 32 bit MSVC
#define MEM_BOUND_ALIGNMENT 8
static_assert((MEM_BOUND_ALIGNMENT & (MEM_BOUND_ALIGNMENT-1)) == 0, "MEM_BOUND_ALIGNMENT must be a power of two");
#ifdef MEMORYPOOL_BOUNDINGWALL
static_assert(WALLSIZE % MEM_BOUND_ALIGNMENT == 0, "WALLSIZE must keep user data aligned");
#endif

static Int roundUpMemBound(Int i);
static void *sysAllocate(Int numBytes);
Expand Down Expand Up @@ -256,6 +260,7 @@ static void* sysAllocateDoNotZero(Int numBytes)
void* p = ::GlobalAlloc(GMEM_FIXED, numBytes);
if (!p)
throw ERROR_OUT_OF_MEMORY;
DEBUG_ASSERTCRASH(((size_t)p & (MEM_BOUND_ALIGNMENT-1)) == 0, ("system allocation is not %d byte aligned", MEM_BOUND_ALIGNMENT));
#ifdef MEMORYPOOL_DEBUG
{
USE_PERF_TIMER(MemoryPoolDebugging)
Expand Down Expand Up @@ -481,6 +486,15 @@ class MemoryPoolSingleBlock
#endif

};

// Offset from a block to its user data, padded so that the user data stays aligned
#ifdef MEMORYPOOL_BOUNDINGWALL
static const Int SINGLEBLOCK_USERDATA_OFFSET = (sizeof(MemoryPoolSingleBlock) + WALLSIZE + MEM_BOUND_ALIGNMENT-1) & ~(MEM_BOUND_ALIGNMENT-1);
#else
static const Int SINGLEBLOCK_USERDATA_OFFSET = (sizeof(MemoryPoolSingleBlock) + MEM_BOUND_ALIGNMENT-1) & ~(MEM_BOUND_ALIGNMENT-1);
#endif
static_assert(SINGLEBLOCK_USERDATA_OFFSET % MEM_BOUND_ALIGNMENT == 0, "SINGLEBLOCK_USERDATA_OFFSET must keep user data aligned");

// ----------------------------------------------------------------------------
class MemoryPoolBlob
{
Expand Down Expand Up @@ -551,11 +565,7 @@ inline void **BlockCheckpointInfo::getStacktraceInfo() { return m_stacktrace; }
*/
inline void* MemoryPoolSingleBlock::getUserDataNoDbg()
{
char* p = ((char*)this) + sizeof(MemoryPoolSingleBlock);
#ifdef MEMORYPOOL_BOUNDINGWALL
p += WALLSIZE;
#endif
return (void*)p;
return ((char*)this) + SINGLEBLOCK_USERDATA_OFFSET;
}

/**
Expand All @@ -567,6 +577,7 @@ inline void* MemoryPoolSingleBlock::getUserData()
// yes, verify the block in this case for plain debug mode (not intense-verify mode)
#ifdef MEMORYPOOL_DEBUG
debugVerifyBlock();
DEBUG_ASSERTCRASH(((size_t)getUserDataNoDbg() & (MEM_BOUND_ALIGNMENT-1)) == 0, ("user data is not %d byte aligned", MEM_BOUND_ALIGNMENT));
#endif
return getUserDataNoDbg();
}
Expand All @@ -577,9 +588,9 @@ inline void* MemoryPoolSingleBlock::getUserData()
*/
inline /*static*/ Int MemoryPoolSingleBlock::calcRawBlockSize(Int logicalSize)
{
Int s = ::roundUpMemBound(logicalSize) + sizeof(MemoryPoolSingleBlock);
Int s = ::roundUpMemBound(logicalSize) + SINGLEBLOCK_USERDATA_OFFSET;
#ifdef MEMORYPOOL_BOUNDINGWALL
s += WALLSIZE*2;
s += WALLSIZE;
#endif
return s;
}
Expand Down Expand Up @@ -922,11 +933,7 @@ void MemoryPoolSingleBlock::initBlock(Int logicalSize, MemoryPoolBlob *owningBlo
DEBUG_ASSERTCRASH(pUserData, ("null pUserData"));
if (!pUserData)
return NULL;
char* p = ((char*)pUserData) - sizeof(MemoryPoolSingleBlock);
#ifdef MEMORYPOOL_BOUNDINGWALL
p -= WALLSIZE;
#endif
MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)p;
MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)(((char*)pUserData) - SINGLEBLOCK_USERDATA_OFFSET);
// yes, verify the block in this case for plain debug mode (not intense-verify mode)
#ifdef MEMORYPOOL_DEBUG
block->debugVerifyBlock();
Expand Down Expand Up @@ -1539,7 +1546,7 @@ void MemoryPool::init(MemoryPoolFactory *factory, const char *poolName, Int allo
{
m_factory = factory;
m_poolName = poolName;
m_allocationSize = ::roundUpMemBound(allocationSize); // round up to four-byte boundary
m_allocationSize = ::roundUpMemBound(allocationSize);
m_initialAllocationCount = initialAllocationCount;
m_overflowAllocationCount = overflowAllocationCount;
m_usedBlocksInPool = 0;
Expand Down Expand Up @@ -1575,7 +1582,7 @@ MemoryPool::~MemoryPool()
*/
MemoryPoolBlob* MemoryPool::createBlob(Int allocationCount)
{
DEBUG_ASSERTCRASH(allocationCount > 0 && allocationCount%MEM_BOUND_ALIGNMENT==0, ("bad allocationCount (must be >0 and evenly divisible by %d)",MEM_BOUND_ALIGNMENT));
DEBUG_ASSERTCRASH(allocationCount > 0 && allocationCount%4==0, ("bad allocationCount (must be >0 and evenly divisible by %d)",4));

MemoryPoolBlob* blob = new (::sysAllocate(sizeof(MemoryPoolBlob))) MemoryPoolBlob; // will throw on failure

Expand Down Expand Up @@ -2662,7 +2669,7 @@ MemoryPool *MemoryPoolFactory::createMemoryPool(const char *poolName, Int alloca
MemoryPool *pool = findMemoryPool(poolName);
if (pool)
{
DEBUG_ASSERTCRASH(allocationSize == pool->getAllocationSize(), ("pool size mismatch"));
DEBUG_ASSERTCRASH(::roundUpMemBound(allocationSize) == pool->getAllocationSize(), ("pool size mismatch"));
return pool;
}

Expand Down Expand Up @@ -3563,23 +3570,23 @@ void* createW3DMemPool(const char *poolName, int allocationSize)
++theLinkTester;
preMainInitMemoryManager();
MemoryPool* pool = TheMemoryPoolFactory->createMemoryPool(poolName, allocationSize, 0, 0);
DEBUG_ASSERTCRASH(pool && pool->getAllocationSize() == allocationSize, ("bad w3d pool"));
DEBUG_ASSERTCRASH(pool && pool->getAllocationSize() == ::roundUpMemBound(allocationSize), ("bad w3d pool"));
return pool;
}

//-----------------------------------------------------------------------------
void* allocateFromW3DMemPool(void* pool, int allocationSize)
{
DEBUG_ASSERTCRASH(pool, ("pool is null"));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == allocationSize, ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == ::roundUpMemBound(allocationSize), ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
return ((MemoryPool*)pool)->allocateBlock("allocateFromW3DMemPool");
}

//-----------------------------------------------------------------------------
void* allocateFromW3DMemPool(void* pool, int allocationSize, const char* msg, int unused)
{
DEBUG_ASSERTCRASH(pool, ("pool is null"));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == allocationSize, ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == ::roundUpMemBound(allocationSize), ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
return ((MemoryPool*)pool)->allocateBlock(msg);
}

Expand Down
49 changes: 28 additions & 21 deletions GeneralsMD/Code/GameEngine/Source/Common/System/GameMemory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,12 @@ static Bool theMainInitFlag = false;
// PRIVATE PROTOTYPES
// ----------------------------------------------------------------------------

/// @todo srj -- make this work for 8
#define MEM_BOUND_ALIGNMENT 4
// User data alignment, matches the 8 byte alignment that operator new guarantees on 32 bit MSVC
#define MEM_BOUND_ALIGNMENT 8
static_assert((MEM_BOUND_ALIGNMENT & (MEM_BOUND_ALIGNMENT-1)) == 0, "MEM_BOUND_ALIGNMENT must be a power of two");
#ifdef MEMORYPOOL_BOUNDINGWALL
static_assert(WALLSIZE % MEM_BOUND_ALIGNMENT == 0, "WALLSIZE must keep user data aligned");
#endif

static Int roundUpMemBound(Int i);
static void *sysAllocateDoNotZero(Int numBytes);
Expand Down Expand Up @@ -236,6 +240,7 @@ static void* sysAllocateDoNotZero(Int numBytes)
void* p = ::GlobalAlloc(GMEM_FIXED, numBytes);
if (!p)
throw ERROR_OUT_OF_MEMORY;
DEBUG_ASSERTCRASH(((size_t)p & (MEM_BOUND_ALIGNMENT-1)) == 0, ("system allocation is not %d byte aligned", MEM_BOUND_ALIGNMENT));
#ifdef MEMORYPOOL_DEBUG
{
USE_PERF_TIMER(MemoryPoolDebugging)
Expand Down Expand Up @@ -461,6 +466,15 @@ class MemoryPoolSingleBlock
#endif

};

// Offset from a block to its user data, padded so that the user data stays aligned
#ifdef MEMORYPOOL_BOUNDINGWALL
static const Int SINGLEBLOCK_USERDATA_OFFSET = (sizeof(MemoryPoolSingleBlock) + WALLSIZE + MEM_BOUND_ALIGNMENT-1) & ~(MEM_BOUND_ALIGNMENT-1);
#else
static const Int SINGLEBLOCK_USERDATA_OFFSET = (sizeof(MemoryPoolSingleBlock) + MEM_BOUND_ALIGNMENT-1) & ~(MEM_BOUND_ALIGNMENT-1);
#endif
static_assert(SINGLEBLOCK_USERDATA_OFFSET % MEM_BOUND_ALIGNMENT == 0, "SINGLEBLOCK_USERDATA_OFFSET must keep user data aligned");

// ----------------------------------------------------------------------------
class MemoryPoolBlob
{
Expand Down Expand Up @@ -531,11 +545,7 @@ inline void **BlockCheckpointInfo::getStacktraceInfo() { return m_stacktrace; }
*/
inline void* MemoryPoolSingleBlock::getUserDataNoDbg()
{
char* p = ((char*)this) + sizeof(MemoryPoolSingleBlock);
#ifdef MEMORYPOOL_BOUNDINGWALL
p += WALLSIZE;
#endif
return (void*)p;
return ((char*)this) + SINGLEBLOCK_USERDATA_OFFSET;
}

/**
Expand All @@ -547,6 +557,7 @@ inline void* MemoryPoolSingleBlock::getUserData()
// yes, verify the block in this case for plain debug mode (not intense-verify mode)
#ifdef MEMORYPOOL_DEBUG
debugVerifyBlock();
DEBUG_ASSERTCRASH(((size_t)getUserDataNoDbg() & (MEM_BOUND_ALIGNMENT-1)) == 0, ("user data is not %d byte aligned", MEM_BOUND_ALIGNMENT));
#endif
return getUserDataNoDbg();
}
Expand All @@ -557,9 +568,9 @@ inline void* MemoryPoolSingleBlock::getUserData()
*/
inline /*static*/ Int MemoryPoolSingleBlock::calcRawBlockSize(Int logicalSize)
{
Int s = ::roundUpMemBound(logicalSize) + sizeof(MemoryPoolSingleBlock);
Int s = ::roundUpMemBound(logicalSize) + SINGLEBLOCK_USERDATA_OFFSET;
#ifdef MEMORYPOOL_BOUNDINGWALL
s += WALLSIZE*2;
s += WALLSIZE;
#endif
return s;
}
Expand Down Expand Up @@ -903,11 +914,7 @@ void MemoryPoolSingleBlock::initBlock(Int logicalSize, MemoryPoolBlob *owningBlo
DEBUG_ASSERTCRASH(pUserData, ("null pUserData"));
if (!pUserData)
return nullptr;
char* p = ((char*)pUserData) - sizeof(MemoryPoolSingleBlock);
#ifdef MEMORYPOOL_BOUNDINGWALL
p -= WALLSIZE;
#endif
MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)p;
MemoryPoolSingleBlock *block = (MemoryPoolSingleBlock *)(((char*)pUserData) - SINGLEBLOCK_USERDATA_OFFSET);
// yes, verify the block in this case for plain debug mode (not intense-verify mode)
#ifdef MEMORYPOOL_DEBUG
block->debugVerifyBlock();
Expand Down Expand Up @@ -1520,7 +1527,7 @@ void MemoryPool::init(MemoryPoolFactory *factory, const char *poolName, Int allo
{
m_factory = factory;
m_poolName = poolName;
m_allocationSize = ::roundUpMemBound(allocationSize); // round up to four-byte boundary
m_allocationSize = ::roundUpMemBound(allocationSize);
m_initialAllocationCount = initialAllocationCount;
m_overflowAllocationCount = overflowAllocationCount;
m_usedBlocksInPool = 0;
Expand Down Expand Up @@ -1556,7 +1563,7 @@ MemoryPool::~MemoryPool()
*/
MemoryPoolBlob* MemoryPool::createBlob(Int allocationCount)
{
DEBUG_ASSERTCRASH(allocationCount > 0 && allocationCount%MEM_BOUND_ALIGNMENT==0, ("bad allocationCount (must be >0 and evenly divisible by %d)",MEM_BOUND_ALIGNMENT));
DEBUG_ASSERTCRASH(allocationCount > 0 && allocationCount%4==0, ("bad allocationCount (must be >0 and evenly divisible by %d)",4));

MemoryPoolBlob* blob = new (::sysAllocateDoNotZero(sizeof(MemoryPoolBlob))) MemoryPoolBlob; // will throw on failure

Expand Down Expand Up @@ -2259,7 +2266,7 @@ void *DynamicMemoryAllocator::allocateBytesDoNotZeroImplementation(Int numBytes

#if defined(RTS_DEBUG)
// check alignment
if (unsigned(result)&3)
if ((size_t)result & (MEM_BOUND_ALIGNMENT-1))
throw ERROR_OUT_OF_MEMORY;
#endif

Expand Down Expand Up @@ -2662,7 +2669,7 @@ MemoryPool *MemoryPoolFactory::createMemoryPool(const char *poolName, Int alloca
MemoryPool *pool = findMemoryPool(poolName);
if (pool)
{
DEBUG_ASSERTCRASH(allocationSize == pool->getAllocationSize(), ("pool size mismatch"));
DEBUG_ASSERTCRASH(::roundUpMemBound(allocationSize) == pool->getAllocationSize(), ("pool size mismatch"));
return pool;
}

Expand Down Expand Up @@ -3562,23 +3569,23 @@ void* createW3DMemPool(const char *poolName, int allocationSize)
++theLinkTester;
preMainInitMemoryManager();
MemoryPool* pool = TheMemoryPoolFactory->createMemoryPool(poolName, allocationSize, 0, 0);
DEBUG_ASSERTCRASH(pool && pool->getAllocationSize() == allocationSize, ("bad w3d pool"));
DEBUG_ASSERTCRASH(pool && pool->getAllocationSize() == ::roundUpMemBound(allocationSize), ("bad w3d pool"));
return pool;
}

//-----------------------------------------------------------------------------
void* allocateFromW3DMemPool(void* pool, int allocationSize)
{
DEBUG_ASSERTCRASH(pool, ("pool is null"));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == allocationSize, ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == ::roundUpMemBound(allocationSize), ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
return ((MemoryPool*)pool)->allocateBlock("allocateFromW3DMemPool");
}

//-----------------------------------------------------------------------------
void* allocateFromW3DMemPool(void* pool, int allocationSize, const char* msg, int unused)
{
DEBUG_ASSERTCRASH(pool, ("pool is null"));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == allocationSize, ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
DEBUG_ASSERTCRASH(pool && ((MemoryPool*)pool)->getAllocationSize() == ::roundUpMemBound(allocationSize), ("bad w3d pool size %s",((MemoryPool*)pool)->getPoolName()));
return ((MemoryPool*)pool)->allocateBlock(msg);
}

Expand Down
Loading