WIP Two-Level Segregated Fit (TLSF) implementation
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled
This commit is contained in:
37
src/heap.cpp
37
src/heap.cpp
@@ -150,23 +150,50 @@ void Heap::removeFreeBlock(TLSFBlock* block)
|
|||||||
// Allocate `size` bytes
|
// Allocate `size` bytes
|
||||||
std::byte* Heap::alloc(size_t size)
|
std::byte* Heap::alloc(size_t size)
|
||||||
{
|
{
|
||||||
|
if (size < 16) {
|
||||||
|
size = 16;
|
||||||
|
}
|
||||||
TLSFIndex* index = (TLSFIndex*)m_region.getAddress();
|
TLSFIndex* index = (TLSFIndex*)m_region.getAddress();
|
||||||
|
|
||||||
|
// size: 0b0000000000010000 (16)
|
||||||
|
// bit_ceil(size): 0b0000000000010000
|
||||||
|
// - 1 ... 0b0000000000001111
|
||||||
|
// ~ ... 0b1111111111110000
|
||||||
|
|
||||||
// size: 0b0000001110011101 (925)
|
// size: 0b0000001110011101 (925)
|
||||||
// bit_ceil(size): 0b0000010000000000
|
// bit_ceil(size): 0b0000010000000000
|
||||||
// - 1 ... 0b0000001111111111
|
// - 1 ... 0b0000001111111111
|
||||||
// ~ ... 0b1111110000000000
|
// ~ ... 0b1111110000000000
|
||||||
|
|
||||||
uint64_t possibleFirstLevels = ~(std::bit_ceil(size) - 1);
|
uint64_t possibleFirstLevels = ~(std::bit_floor(size) - 1);
|
||||||
uint64_t freeFirstLevels = index->firstLevelFreeBitMap & possibleFirstLevels;
|
uint64_t freeFirstLevels = index->firstLevelFreeBitMap & possibleFirstLevels;
|
||||||
uint64_t selectedFirstLevel = std::countr_zero(freeFirstLevels);
|
uint64_t selectedFirstLevel = std::countr_zero(freeFirstLevels);
|
||||||
if (selectedFirstLevel < 5) {
|
if (selectedFirstLevel == 64) {
|
||||||
selectedFirstLevel = 0;
|
// No first level with free blocks of sufficient size.
|
||||||
} else {
|
return nullptr;
|
||||||
selectedFirstLevel -= 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t firstLevelBufferMinSize = 1ULL << selectedFirstLevel;
|
||||||
|
uint64_t secondLevelMask = 0b1111ULL;
|
||||||
|
if (size > firstLevelBufferMinSize) {
|
||||||
|
uint64_t delta = size - firstLevelBufferMinSize;
|
||||||
|
secondLevelMask = (delta >> (selectedFirstLevel - 4)) & 0b1111ULL;
|
||||||
|
}
|
||||||
|
uint64_t possibleSecondLevels = secondLevelMask & index->secondLevelFreeBitMap[selectedFirstLevel - 4];
|
||||||
|
uint64_t selectedSecondLevel = std::countr_zero(possibleSecondLevels);
|
||||||
|
if (selectedSecondLevel == 64) {
|
||||||
|
// No free blocks available at this first level.
|
||||||
|
|
||||||
|
// Select the next highest available first level.
|
||||||
|
selectedFirstLevel = std::countr_zero(freeFirstLevels & ~(1ULL << selectedFirstLevel));
|
||||||
|
if (selectedFirstLevel == 64) {
|
||||||
|
// No other first level with free blocks of sufficient size.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any buffer at the second level will fit this allocation.
|
||||||
|
selectedSecondLevel = std::countr_zero(index->secondLevelFreeBitMap[selectedFirstLevel - 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return nullptr; // not implemented
|
return nullptr; // not implemented
|
||||||
|
|||||||
Reference in New Issue
Block a user