内存的分配和释放作为一种
该函数实现了以字节为单位的存储空间分配,EDKII 中对这种非页面的存储空间使用了如下数据结构
来管理。
//
// Each element is the sum of the 2 previous ones: this allows us to migrate
// blocks between bins by splitting them up, while not wasting too much memory
// as we would in a strict power-of-2 sequence
//
STATIC CONST UINT16 mPoolSizeTable[] = {128, 256, 384, 640, 1024, 1664, 2688, 4352, 7040, 11392, 18432, 29824
};
相同大小的pool 都被存放在同一个链表中
处理了请求分配大小超过FreeList 容量的情况,对于这种情况,直接调用page.c 文件中的CoreAllocatePoolPagesI
函数去以页面为单位分配。
将新新分配的页面拆分成所需要的大小,并将这些可分配pool 加入到FreeList 数组中去,拆分后剩余的
空间“边角料”也没有浪费,而是被加入到更小单元的FreeList 数组中去
//// Carve up remaining space into free pool blocks//Index--;while (Offset < MaxOffset) {ASSERT (Index < MAX_POOL_LIST);FSize = LIST_TO_SIZE(Index);while (Offset + FSize <= MaxOffset) {Free = (POOL_FREE *) &NewPage[Offset];Free->Signature = POOL_FREE_SIGNATURE;Free->Index = (UINT32)Index;InsertHeadList (&Pool->FreeList[Index], &Free->Link);Offset += FSize;}Index -= 1;}
Index -= 1
先尝试按最大的pool 来匹配,一直到尝试能不能匹配上128字节的内存单元。
//// Get the head & tail of the pool entry//Head = BASE_CR (Buffer, POOL_HEAD, Data);ASSERT(Head != NULL);if (Head->Signature != POOL_HEAD_SIGNATURE &&Head->Signature != POOLPAGE_HEAD_SIGNATURE) {ASSERT (Head->Signature == POOL_HEAD_SIGNATURE ||Head->Signature == POOLPAGE_HEAD_SIGNATURE);return EFI_INVALID_PARAMETER;}
该函数与AllocatePool 相对应,将已经分配的Pool 释放以便可以重新利用这些存储空间。函数
的一开始做了些Pool 结构的检查工作,只有确实是通过AllocatePool 得到的空间才可以使用
FreePool来释放。
同样,对于大尺寸的Pool, 我们直接调用CoreFreePoolPage 来释放相关页面。对于通常的
Pool , 将这些空间重新加入到FreeList 中去。
//// Put the pool entry onto the free pool list//Free = (POOL_FREE *) Head;ASSERT(Free != NULL);Free->Signature = POOL_FREE_SIGNATURE;Free->Index = (UINT32)Index;InsertHeadList (&Pool->FreeList[Index], &Free->Link);