1. 程式人生 > >UEFI EDKII 記憶體的分配和釋放細節

UEFI EDKII 記憶體的分配和釋放細節

記憶體的分配和釋放作為一種

該函式實現了以位元組為單位的儲存空間分配,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);