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:
parent
f307e85458
commit
c45df0a90b
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user