Handle multiple pages in a row being too full

* When resetting pagesets in a granular fashion from the chunk allocator, it's
  possible to almost (or completely) exhaust a page but not have it be bumped
  out of the free list, then one more new full free pages is pushed. When that
  free page is exhausted we'll retire it then assume the next one is usable -
  but it is still not valid. We need to loop until we find a page with enough
  space.
This commit is contained in:
baldurk
2020-11-25 16:56:16 +00:00
parent ecafa4f129
commit 3f394aa5df
2 changed files with 17 additions and 12 deletions
+11 -10
View File
@@ -1142,18 +1142,19 @@ byte *ChunkAllocator::AllocateFromPages(bool chunkAlloc, size_t size)
if(size > BufferPageSize)
return NULL;
if(!freePages.empty())
while(!freePages.empty())
{
// if the last free page can't satisfy this allocation, retire it to the full list
if((chunkAlloc && GetRemainingChunkBytes(freePages.back()) < size) ||
(!chunkAlloc && GetRemainingBufferBytes(freePages.back()) < size))
{
// mark this page as used in the current set
usedPages.push_back(freePages.back().ID);
// if the last free page can satisfy this allocation, stop iterating as we'll use it.
if(GetRemainingBytes(chunkAlloc, freePages.back()) >= size)
break;
fullPages.push_back(freePages.back());
freePages.pop_back();
}
// otherwise the last page doesn't have enough free, so remove it from the free list
// mark this page as used in the current set
usedPages.push_back(freePages.back().ID);
fullPages.push_back(freePages.back());
freePages.pop_back();
}
// if there are no free pages, allocate a new one
+6 -2
View File
@@ -1585,14 +1585,18 @@ private:
// includes it there
rdcarray<uint32_t> usedPages;
size_t GetRemainingBufferBytes(const Page &p)
inline size_t GetRemainingBufferBytes(const Page &p)
{
return BufferPageSize - (p.bufferHead - p.bufferBase);
}
size_t GetRemainingChunkBytes(const Page &p)
inline size_t GetRemainingChunkBytes(const Page &p)
{
return ChunkPageSize - (p.chunkHead - p.chunkBase);
}
inline size_t GetRemainingBytes(bool chunkAlloc, const Page &p)
{
return chunkAlloc ? GetRemainingChunkBytes(p) : GetRemainingBufferBytes(p);
}
byte *AllocateFromPages(bool chunkAlloc, size_t size);
};