⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
      Error(L"Unable to translate bus address to physical address!\n");
    }
  }
  else {
    Error(L"Unable to allocate virtual address for memory region 0!\n");
  }

  Exit(L"InitializeVideoMem");

  return FnRetVal;
}

LPVOID
VideoAlloc(
  ULONG Bytes,
  ULONG Alignment
  )
{
  // VideoAlloc
  // This function allocates video memory. It does so by locating a free node
  // of the appropriate size and turning it into an allocated node. It will
  // split the remaining piece of the free node into a new free node.

  // Local variables.

  LPVOID ReturnPointer = NULL;  // Return value for this function.
  VID_NODE * CurrentNode = NULL;
  VID_NODE ** PreviousNext = NULL;
  VID_NODE * LeftoverNode = NULL;

  // Check parameters. - Bytes can be anything. !TODO! Alignment.

  Enter(L"VideoAlloc");

  // !TODO! Alignment

  if (FindFreeNode(Bytes, &CurrentNode, &PreviousNext)) {

    // Work on the free node bins. We may need to split off a new node and
    // re-insert it into the free bins.

    if (CurrentNode->Size - Bytes != 0) {

      LeftoverNode = SystemAlloc(sizeof(VID_NODE));
      if (LeftoverNode) {

        LeftoverNode->Memory = (LPVOID)((BYTE *)CurrentNode->Memory + Bytes);
        LeftoverNode->Size = CurrentNode->Size - Bytes;
          
        // Leftovers are not aligned to anything.

        LeftoverNode->Alignment = 0;

        // Fixup the CurrentNode.

        CurrentNode->Size = Bytes;

        // !TODO! Alignemnt?
      }
      else {
        Error(L"System memory allocation failure!\n");
        // This call does not return.
      }
    }

    // Remove the current node by making the next pointer in the node before
    // us (could be a pointer to the l_FreeBin array,) point to the node
    // that's next to the current one (Could be NULL.)

    *PreviousNext = CurrentNode->Next;
    CurrentNode->Next = NULL;

    // Add the leftover node to the bin structure. This must happen AFTER the 
    // current node has been removed to insure the pointers we got back from
    // FindFreeNode are still valid.

    if (LeftoverNode) {
      InsertFreeNode(LeftoverNode);
    }

    // Add the current node to the free node hash table.

    InsertAllocatedNode(CurrentNode);

    // Done.

    ReturnPointer = CurrentNode->Memory;
    l_FreeVidMemory -= Bytes;
  }

  Exit(L"VideoAlloc");  

  return ReturnPointer;
}

void
VideoFree(
  LPVOID Pointer
  )
{
  // VideoFree
  // This function frees video memory allocations made with VideoAlloc. It
  // moves the allocated node into the correct bin in the free nodes
  // structure. Someday, we should probably attempt to compact memory
  // at this point. !TODO! (Buddy system?)

  // Local variables.

  VID_NODE * CurrentNode = NULL;
  VID_NODE ** PreviousNext = NULL;

  // Check parameters. Pointer can be anything (if we don't find the node,
  // we handle it below.)

  Enter(L"VideoFree");

  if (FindAllocatedNode(Pointer, &CurrentNode, &PreviousNext)) {

    // We need to remove the node from the allocated hash table.

    *PreviousNext = CurrentNode->Next;
    CurrentNode->Next = NULL;

    // !TODO! Buddy system coalesce?
    // !TODO! Alignment?

    // Add the node back into the free bins.

    InsertFreeNode(CurrentNode);

    // Done.

    l_FreeVidMemory += CurrentNode->Size;
  }
  else {
    Message(L"Unable to locate pointer in allocated hash table.\n");
  }

  Exit(L"VideoFree");
}

ULONG
GetTotalVideoMem()
{
  // GetTotalVideoMem
  // Returns the total amount of video memory avialable to the Permedia3 in
  // bytes. Inlined, so there is no Enter/Exit semantics.

  return (l_TotalVidMemory);
}

ULONG
GetFreeVideoMem()
{
  // GetFreeVideoMem
  // Returns the total amount of unallocated video memory, in bytes. Inlined,
  // so there is no Enter or Exit.

  return (l_FreeVidMemory);
}

BOOL
FindFreeNode(
  ULONG        Bytes,
  VID_NODE **  CurrentNodeIndirect,
  VID_NODE *** PreviousNextIndirect
  )
{
  // FindFreeNode
  // This function searches the free node bin structure for a node just
  // larger than the size passed in. It returns the pointer to that node in
  // CurrentNodeIndirect and a pointer to the pointer to the current node in
  // the bin list in PreviousNextIndirect this allows us to treat head nodes
  // the same as Next pointers in VID_NODE structures.

  // Local variables.

  BOOL GotNode = FALSE;  // Return value for this function.
  ULONG BinIndex;

  // Check parameters.

  // Bytes can be anything.
  AssertWritePtr(CurrentNodeIndirect, sizeof(VID_NODE*));
  AssertWritePtr(PreviousNextIndirect, sizeof(VID_NODE**));

  Enter(L"FindFreeNode");

  // Simple check. Do we have the memory to do this? (Fragmentation is not
  // considered, the call still may fail.)

  if (Bytes < l_FreeVidMemory) {

    // Find the appropriate bin.

    BinIndex = 0;
    while (Bytes > l_VidBinsSizes[++BinIndex]);

    // Work the bins. If we can find an appropriate node in this bin, use
    // it. If not, step up to the next larger bin. 
    
    while (!GotNode && 
           BinIndex < VID_BIN_COUNT) {

      // Search this bin for a node big enough to fit this allocation (first 
      // fit policy.)

      *CurrentNodeIndirect = l_VidBins[BinIndex];
      *PreviousNextIndirect = &l_VidBins[BinIndex];

      while (*CurrentNodeIndirect != NULL &&
             (*CurrentNodeIndirect)->Size < Bytes) {
        *PreviousNextIndirect = &((*CurrentNodeIndirect)->Next);
        *CurrentNodeIndirect = (*CurrentNodeIndirect)->Next;
      }

      // Check the search results.

      if (*CurrentNodeIndirect != NULL) {

        GotNode = TRUE;
      }
      else {

        // Step up to the next biggest bin.

        BinIndex++;
      }
    }
  }
  else {
    Message(L"Not enough memory to satisfy request.\n");
  }

  Exit(L"FindFreeNode");

  return GotNode;
}

BOOL
FindAllocatedNode(
  LPVOID       Pointer,
  VID_NODE **  CurrentNodeIndirect,
  VID_NODE *** PreviousNextIndirect
  )
{
  // FindAllocatedNode
  // This function uses the Hash function to attempt to locate an allocated
  // node in the table. It returns a pointer to that node through
  // CurrentNodeIndirect and pointer to the pointer to that node through
  // PreviousNextIndirect. The function returns TRUE if it finds the
  // allocation, FALSE if not.

  // Local variables.

  BOOL GotNode;  // Return value for this function.
  ULONG PointerHash;

  // Check parameters.

  // Pointer can be anything - If we don't find it, we fail the call.
  AssertWritePtr(CurrentNodeIndirect, sizeof(VID_NODE*));
  AssertWritePtr(PreviousNextIndirect, sizeof(VID_NODE**));

  Enter(L"FindAllocatedNode");

  // Get the hash table entry where this pointer's node would live.

  PointerHash = Hash(Pointer);

  // Search the list in that entry for the node.

  *CurrentNodeIndirect = l_VidHash[PointerHash];
  *PreviousNextIndirect = &l_VidHash[PointerHash];

  while (*CurrentNodeIndirect != NULL &&
         (*CurrentNodeIndirect)->Memory != Pointer) {
    *PreviousNextIndirect = &((*CurrentNodeIndirect)->Next);
    *CurrentNodeIndirect = (*CurrentNodeIndirect)->Next;
  }

  // Did we get it?

  GotNode = (*CurrentNodeIndirect != NULL);

  Exit(L"FindAllocatedNode");

  return GotNode;  
}

void
InsertAllocatedNode(
  VID_NODE * Node
  )
{
  // InsertAllocatedNode
  // This function takes a VID_NODE and inserts it into the allocated node
  // table. It cannot fail. The process is simple: figure out which hash
  // table entry the node needs to go into and insert it into the list
  // at that node.

  // Local variables.

  ULONG PointerHash;

  // Check parameters.

  AssertReadPtr(Node, sizeof(VID_NODE));

  Enter(L"InsertAllocatedNode");

  // Get the hash table entry where this pointer's node would live.

  PointerHash = Hash(Node->Memory);

  // Insert the new node as the head of the list in that entry.

  Node->Next = l_VidHash[PointerHash];
  l_VidHash[PointerHash] = Node;

  Exit(L"InsertAllocatedNode");
}

void
InsertFreeNode(
  VID_NODE * Node
  )
{
  // InsertFreeNode
  // This function takes a VID_NODE and inserts it into the appropriate free
  // bin, based on size. It is not allowed to fail. The process is quite
  // simple. Locate the appropriate bin and insert the node into the list as
  // the new head node, making the old head node our Next.

  // Local variables.

  ULONG BinIndex = 0;

  // Check parameters.

  AssertReadPtr(Node, sizeof(VID_NODE));

  Enter(L"InsertFreeNode");

  // Locate the correct bin.

  while (Node->Size > l_VidBinsSizes[++BinIndex]);

  // Insert the node into the bin we have located as it's new head.

  Node->Next = l_VidBins[BinIndex];
  l_VidBins[BinIndex] = Node;

  Exit(L"InsertFreeNode");
}

__inline ULONG
Hash(
  LPVOID Pointer
  )
{
  // Hash
  // This function turns a pointer to video memory into a suitable hash value
  // for the allopcated node table. It does not use the Enter/Exit semantics
  // because it's inline, and not really a function.

  // Check parameters - Pointer can be anything.

  return ((ULONG)(Pointer) % VID_HASH_ENTRIES);
}

ULONG
VirtualToOffset(
  LPVOID Pointer
  )
{
  // VirtualToOffset
  // Given a virtual address of video memory location, this function returns
  // the offset of that memory location in the memory (from 0.) No Enter/Exit
  // semantics becuase this should be inlined.

  // !TODO! This code will change if we ever use Aperture2.

  // Check parameters.

  AssertVideoPtr(Pointer);

  return ((ULONG)Pointer - (ULONG)l_Aperture1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -