mirror of
https://github.com/joncampbell123/dosbox-x.git
synced 2025-10-14 10:48:18 +08:00
RegionAllocTracking: Add parameter to specify a maxmimum dynamic (non-fixed) memory address. Above this address, only fixed allocations are allowed
This commit is contained in:
@@ -17,6 +17,7 @@ public:
|
||||
public:
|
||||
RegionAllocTracking();
|
||||
public:
|
||||
void setMaxDynamicAllocationAddress(Bitu _new_max);
|
||||
Bitu getMemory(Bitu bytes,const char *who,Bitu alignment,Bitu must_be_at);
|
||||
void initSetRange(Bitu start,Bitu end);
|
||||
Bitu freeUnusedMinToLoc(Bitu phys);
|
||||
@@ -29,6 +30,7 @@ public:
|
||||
std::string name;
|
||||
std::vector<Block> alist;
|
||||
Bitu _min,_max;
|
||||
Bitu _max_nonfixed; /* above this address, only permit fixed memory allocation */
|
||||
bool topDownAlloc;
|
||||
public:
|
||||
static const Bitu alloc_failed = ~((Bitu)0);
|
||||
|
@@ -37,7 +37,14 @@ typedef SSIZE_T ssize_t;
|
||||
RegionAllocTracking::Block::Block() : start(0), end(0), free(true) {
|
||||
}
|
||||
|
||||
RegionAllocTracking::RegionAllocTracking() : _min(0), _max(~((Bitu)0)), topDownAlloc(false) {
|
||||
RegionAllocTracking::RegionAllocTracking() : _min(0), _max(~((Bitu)0)), _max_nonfixed(~((Bitu)0)), topDownAlloc(false) {
|
||||
}
|
||||
|
||||
void RegionAllocTracking::setMaxDynamicAllocationAddress(Bitu _new_max) {
|
||||
if (_new_max != 0) /* nonzero to set */
|
||||
_max_nonfixed = _new_max;
|
||||
else /* zero to clear */
|
||||
_max_nonfixed = ~((Bitu)0);
|
||||
}
|
||||
|
||||
Bitu RegionAllocTracking::getMemory(Bitu bytes,const char *who,Bitu alignment,Bitu must_be_at) {
|
||||
@@ -67,15 +74,41 @@ Bitu RegionAllocTracking::getMemory(Bitu bytes,const char *who,Bitu alignment,Bi
|
||||
|
||||
/* if must_be_at != 0 the caller wants a block at a very specific location */
|
||||
if (must_be_at != 0) {
|
||||
/* well, is there room to fit the forced block? if it starts before
|
||||
* this block or the forced block would end past the block then, no. */
|
||||
if (must_be_at < blk.start || (must_be_at+bytes-1u) > blk.end) {
|
||||
base = must_be_at;
|
||||
assert(alignment == 1u);
|
||||
}
|
||||
else {
|
||||
if (topDownAlloc) {
|
||||
base = blk.end + 1u - bytes; /* allocate downward from the top */
|
||||
assert(base >= blk.start);
|
||||
|
||||
if (_max_nonfixed < _max) {
|
||||
/* if instructed to by caller, disallow any dynamic allocation above a certain memory limit */
|
||||
if ((_max_nonfixed + 1u) >= bytes) {
|
||||
const Bitu nbase = _max_nonfixed + 1u - bytes;
|
||||
if (base > nbase) base = nbase;
|
||||
}
|
||||
else {
|
||||
base = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
base = blk.start; /* allocate upward from the bottom */
|
||||
assert(base <= blk.end);
|
||||
base += alignment - 1u; /* alignment round up */
|
||||
|
||||
/* TODO: max_nonfixed... */
|
||||
}
|
||||
}
|
||||
|
||||
base &= ~(alignment - 1u); /* NTS: alignment == 16 means ~0xF or 0xFFFF0 */
|
||||
if (base < blk.start || (base+bytes-1u) > blk.end) {
|
||||
if (topDownAlloc) si--;
|
||||
else si++;
|
||||
continue;
|
||||
}
|
||||
|
||||
base = must_be_at;
|
||||
if (base == blk.start && (base+bytes-1u) == blk.end) { /* easy case: perfect match */
|
||||
blk.free = false;
|
||||
blk.who = who;
|
||||
@@ -109,69 +142,6 @@ Bitu RegionAllocTracking::getMemory(Bitu bytes,const char *who,Bitu alignment,Bi
|
||||
newblk2.who = who;
|
||||
alist.insert(alist.begin()+(std::vector<RegionAllocTracking::Block>::difference_type)si+1u,newblk2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (topDownAlloc) {
|
||||
base = blk.end + 1u - bytes; /* allocate downward from the top */
|
||||
assert(base >= blk.start);
|
||||
}
|
||||
else {
|
||||
base = blk.start; /* allocate upward from the bottom */
|
||||
assert(base <= blk.end);
|
||||
base += alignment - 1u; /* alignment round up */
|
||||
}
|
||||
|
||||
base &= ~(alignment - 1u); /* NTS: alignment == 16 means ~0xF or 0xFFFF0 */
|
||||
if (base < blk.start || (base+bytes-1u) > blk.end) { /* if not possible after alignment, then skip */
|
||||
if (topDownAlloc) si--;
|
||||
else si++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (topDownAlloc) {
|
||||
/* easy case: base matches start, just take the block! */
|
||||
if (base == blk.start) {
|
||||
blk.free = false;
|
||||
blk.who = who;
|
||||
return blk.start;
|
||||
}
|
||||
|
||||
/* not-so-easy: need to split the block and claim the upper half */
|
||||
RegionAllocTracking::Block newblk = blk; /* this becomes the new block we insert */
|
||||
newblk.start = base;
|
||||
newblk.free = false;
|
||||
newblk.who = who;
|
||||
blk.end = base - 1u;
|
||||
|
||||
if (blk.start > blk.end) {
|
||||
sanityCheck();
|
||||
abort();
|
||||
}
|
||||
|
||||
alist.insert(alist.begin()+(std::vector<RegionAllocTracking::Block>::difference_type)si+1,newblk);
|
||||
}
|
||||
else {
|
||||
if ((base+bytes-1u) == blk.end) {
|
||||
blk.free = false;
|
||||
blk.who = who;
|
||||
return blk.start;
|
||||
}
|
||||
|
||||
/* not-so-easy: need to split the block and claim the lower half */
|
||||
RegionAllocTracking::Block newblk = blk; /* this becomes the new block we insert */
|
||||
newblk.start = base+bytes;
|
||||
blk.free = false;
|
||||
blk.who = who;
|
||||
blk.end = base+bytes-1u;
|
||||
|
||||
if (blk.start > blk.end) {
|
||||
sanityCheck();
|
||||
abort();
|
||||
}
|
||||
|
||||
alist.insert(alist.begin()+(std::vector<RegionAllocTracking::Block>::difference_type)si+1u,newblk);
|
||||
}
|
||||
}
|
||||
|
||||
LOG(LOG_BIOS,LOG_DEBUG)("getMemory in '%s' (0x%05x bytes,\"%s\",align=%u,mustbe=0x%05x) = 0x%05x",name.c_str(),(int)bytes,who,(int)alignment,(int)must_be_at,(int)base);
|
||||
sanityCheck();
|
||||
@@ -210,6 +180,7 @@ void RegionAllocTracking::initSetRange(Bitu start,Bitu end) {
|
||||
alist.clear();
|
||||
_min = start;
|
||||
_max = end;
|
||||
_max_nonfixed = end;
|
||||
|
||||
x.end = _max;
|
||||
x.free = true;
|
||||
|
Reference in New Issue
Block a user