in src/Trinity.C/src/Storage/MemoryTrunk/MemoryTrunk.Memory.cpp [89:216]
bool MemoryTrunk::CommittedMemoryExpand(uint32_t minimum_size)
{
/**
* There are two major cases:
* 1) committed_head >= committed_tail
* Committed region consists of one part
* 2) committed_head < committed_tail
* Committed region consists of two parts
* */
uint32_t minimum_to_expand = ((head.append_head + minimum_size + Memory::PAGE_RANGE_32) & Memory::PAGE_MASK_32) - head.committed_head;
uint32_t CurrentVMAllocUnit = TrinityConfig::VMAllocUnit < minimum_to_expand ? minimum_to_expand : TrinityConfig::VMAllocUnit;
bool ret = true;
uint32_t available_space = 0;
uint32_t committed_tail_snapshot = committed_tail;
bool two_region = (head.committed_head < committed_tail_snapshot) ||
(head.committed_head == committed_tail_snapshot && committed_tail_snapshot != 0);
#pragma region Two Region
if (two_region)
{
available_space = committed_tail_snapshot - head.committed_head;
// large enough virtual memory between committed_head and committed_tail for allocating VMAllocUnit
if (CurrentVMAllocUnit <= available_space)
{
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr + head.committed_head, CurrentVMAllocUnit);
if (ret) head.committed_head += CurrentVMAllocUnit;
goto EXPAND_RETURN;
}
// Not large enough for VMAllocUnit, but enough for minimum_to_expand
if (minimum_to_expand <= available_space)
{
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr + head.committed_head, minimum_to_expand);
if (ret) head.committed_head += minimum_to_expand;
goto EXPAND_RETURN;
}
// Out of memory, try to reload later
goto RELOAD_RETURN;
}
#pragma endregion
#pragma region One Region
available_space = TrunkLength - head.committed_head;
// There is enough virtual memory between committed_head to trunk_end for VMAllocUnit
if (CurrentVMAllocUnit <= available_space)
{
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr + head.committed_head, CurrentVMAllocUnit);
if (ret) head.committed_head += CurrentVMAllocUnit;
goto EXPAND_RETURN;
}
// Not enough for VMAllocUnit, but enough for minimum_to_expand
if (minimum_to_expand <= available_space)
{
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr + head.committed_head, minimum_to_expand);
if (ret) head.committed_head += minimum_to_expand;
goto EXPAND_RETURN;
}
// There is not enough virtual memory between committed_head to trunk_end
//! Now check the space between trunk_ptr and committed_tail
// Enough available memory for VMAllocUnit
if (CurrentVMAllocUnit <= committed_tail) //available_space = committed_tail - 0
{
//First allocate the memory between committed_head to trunk_end
uint32_t padding_size = available_space;
if (padding_size)
{
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr + head.committed_head, padding_size);
if (!ret) goto EXPAND_RETURN;
}
//Then allocate memory between trunk_ptr to committed_tail
split_lock->lock();
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr, CurrentVMAllocUnit);
if (ret)
{
head.append_head = 0; //warp back to head
head.committed_head = CurrentVMAllocUnit;
}
split_lock->unlock();
goto EXPAND_RETURN;
}
// Not enough for VMAllocUnit, but enough for minimum_to_expand
if (minimum_to_expand <= committed_tail) //vailable_space = committed_tail - 0
{
//First allocate the memory between committed_head to trunk_end
uint32_t padding_size = available_space;
if (padding_size)
{
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr + head.committed_head, padding_size);
if (!ret) goto EXPAND_RETURN;
}
//Then allocate memory between trunk_ptr to committed_tail
split_lock->lock();
ret = Memory::ExpandMemoryFromCurrentPosition(trunkPtr, minimum_to_expand);
if (ret)
{
head.append_head = 0; //warp back to head
head.committed_head = minimum_to_expand;
}
split_lock->unlock();
goto EXPAND_RETURN;
}
// Out of memory
goto RELOAD_RETURN;
#pragma endregion
EXPAND_RETURN:
if (ret == false)
{
Trinity::Diagnostics::WriteLine(Diagnostics::LogLevel::Error, "CommittedMemoryExpand: MemoryTrunk {0} failed to expand. LastError = {1}", TrunkId, GetLastError());
}
return ret;
RELOAD_RETURN:
return Reload(minimum_size);
}