1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-20 13:54:14 +01:00

Made CPageAlloc return aligned pointers if required

--HG--
branch : hookman_autogen
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/branches/hookman_autogen%40579
This commit is contained in:
Pavol Marko 2007-11-25 01:20:00 +00:00
parent f307e85458
commit c45df0a90b
3 changed files with 65 additions and 23 deletions

View File

@ -46,14 +46,37 @@ namespace SourceHook
};
typedef List<AllocationUnit> AUList;
struct AllocatedRegion
{
void *startPtr;
size_t size;
bool isolated; // may contain only one AU
size_t minAlignment;
AUList allocUnits;
void CheckGap(size_t gap_begin, size_t gap_end, size_t reqsize,
size_t &smallestgap_pos, size_t &smallestgap_size, size_t &outAlignBytes)
{
size_t gapsize = gap_end - gap_begin;
// How many bytes do we actually need here?
// = requested size + alignment bytes
size_t neededSize = reqsize;
size_t alignBytes = minAlignment - ((reinterpret_cast<intptr_t>(startPtr) + gap_begin) % minAlignment);
alignBytes %= minAlignment;
neededSize += alignBytes;
if (gap_end - gap_begin >= neededSize)
{
if (gap_end - gap_begin < smallestgap_size)
{
smallestgap_size = gap_end - gap_begin;
smallestgap_pos = gap_begin;
outAlignBytes = alignBytes;
}
}
}
bool TryAlloc(size_t reqsize, void * &outAddr)
{
// Check for isolated
@ -64,33 +87,20 @@ namespace SourceHook
size_t lastend = 0;
size_t smallestgap_pos = size + 1;
size_t smallestgap_size = size + 1;
size_t alignmentbytes = 0;
for (AUList::iterator iter = allocUnits.begin(); iter != allocUnits.end(); ++iter)
{
if (iter->begin_offset - lastend >= reqsize)
{
if (iter->begin_offset - lastend < smallestgap_size)
{
smallestgap_size = iter->begin_offset - lastend;
smallestgap_pos = lastend;
}
}
CheckGap(lastend, iter->begin_offset, reqsize, smallestgap_pos, smallestgap_size, alignmentbytes);
lastend = iter->begin_offset + iter->size;
}
if (size - lastend >= reqsize)
{
if (size - lastend < smallestgap_size)
{
smallestgap_size = size - lastend;
smallestgap_pos = lastend;
}
}
CheckGap(lastend, size, reqsize, smallestgap_pos, smallestgap_size, alignmentbytes);
if (smallestgap_pos < size)
{
outAddr = reinterpret_cast<void*>(reinterpret_cast<char*>(startPtr) + smallestgap_pos);
allocUnits.push_sorted( AllocationUnit(smallestgap_pos, reqsize) );
outAddr = reinterpret_cast<void*>(reinterpret_cast<char*>(startPtr) + smallestgap_pos + alignmentbytes);
allocUnits.push_sorted( AllocationUnit(smallestgap_pos, reqsize + alignmentbytes) );
return true;
}
else
@ -104,11 +114,16 @@ namespace SourceHook
if (addr < startPtr || addr >= reinterpret_cast<void*>(reinterpret_cast<char*>(startPtr) + size))
return false;
size_t offs = reinterpret_cast<char*>(addr) - reinterpret_cast<char*>(startPtr);
intptr_t start = reinterpret_cast<intptr_t>(startPtr);
for (AUList::iterator iter = allocUnits.begin(); iter != allocUnits.end(); ++iter)
{
if (iter->begin_offset == offs)
size_t AUBegin = start + iter->begin_offset;
void *alignedAUBegin = reinterpret_cast<void*>(
AUBegin + ((minAlignment - AUBegin % minAlignment) % minAlignment)
);
if (addr == alignedAUBegin)
{
allocUnits.erase(iter);
return true;
@ -135,6 +150,7 @@ namespace SourceHook
typedef List<AllocatedRegion> ARList;
size_t m_MinAlignment;
size_t m_PageSize;
ARList m_Regions;
@ -143,6 +159,7 @@ namespace SourceHook
AllocatedRegion newRegion;
newRegion.startPtr = 0;
newRegion.isolated = isolated;
newRegion.minAlignment = m_MinAlignment;
// Compute real size -> align up to m_PageSize boundary
@ -190,7 +207,7 @@ namespace SourceHook
}
public:
CPageAlloc()
CPageAlloc(size_t minAlignment = 1 /* power of 2 */ ) : m_MinAlignment(minAlignment)
{
#ifdef __linux__
m_PageSize = sysconf(_SC_PAGESIZE);

View File

@ -36,7 +36,7 @@ namespace SourceHook
{
namespace Impl
{
CPageAlloc GenBuffer::ms_Allocator;
CPageAlloc GenBuffer::ms_Allocator(16);
template <class T>
jit_int32_t DownCastPtr(T ptr)

View File

@ -1200,5 +1200,30 @@ bool TestCPageAlloc(std::string &error)
memset((void*)test4[2], 0, ps / 4);
// alignement tests
CPageAlloc alloc1(1);
CPageAlloc alloc4(4);
CPageAlloc alloc16(16);
void *last1 = alloc1.Alloc(1);
void *last4 = alloc4.Alloc(4);
void *last16 = alloc16.Alloc(16);
void *cur;
for (int i = 0; i < 20; ++i)
{
cur = alloc1.Alloc(1);
CHECK_COND(reinterpret_cast<intptr_t>(cur) == reinterpret_cast<intptr_t>(last1) + 1, "Part 4.1");
last1 = cur;
cur = alloc4.Alloc(1);
CHECK_COND(reinterpret_cast<intptr_t>(cur) == reinterpret_cast<intptr_t>(last4) + 4, "Part 4.2");
last4 = cur;
cur = alloc16.Alloc(1);
CHECK_COND(reinterpret_cast<intptr_t>(cur) == reinterpret_cast<intptr_t>(last16) + 16, "Part 4.3");
last16 = cur;
}
alloc16.Free(alloc16.Alloc(1));
return true;
}