f543f28bf0
Signed-off-by: Chloe M. <chloe@mensia.org>
106 lines
2.4 KiB
C
106 lines
2.4 KiB
C
/*
|
|
* Copyright (c) 2026, Chloe M.
|
|
* Provided under the BSD-3 clause.
|
|
*
|
|
* Description: Virtual address descriptor management
|
|
* Author: Chloe M.
|
|
*/
|
|
|
|
#include <mm/vad.h>
|
|
#include <hal/page.h>
|
|
|
|
/* Prototypes */
|
|
static LONG VadCmp(MM_VAD *V0, MM_VAD *V1);
|
|
|
|
/* RBT generation */
|
|
RB_PROTOTYPE(VadTree, _MM_VAD, TreeLink, VadCmp);
|
|
RB_GENERATE(VadTree, _MM_VAD, TreeLink, VadCmp);
|
|
|
|
static LONG
|
|
VadCmp(MM_VAD *V0, MM_VAD *V1)
|
|
{
|
|
MM_RANGE *Range0, *Range1;
|
|
|
|
Range0 = &V0->Range;
|
|
Range1 = &V1->Range;
|
|
|
|
return (Range0->VirtualBase < Range1->VirtualBase)
|
|
? -1
|
|
: Range0->VirtualBase > Range1->VirtualBase;
|
|
}
|
|
|
|
VOID
|
|
MmVadTreeInit(MM_VAD_TREE *Tree)
|
|
{
|
|
if (Tree == NULL) {
|
|
return;
|
|
}
|
|
|
|
Tree->Elements = 0;
|
|
RB_INIT(&Tree->Head);
|
|
}
|
|
|
|
PT_STATUS
|
|
MmVadTreeInsert(MM_VAD_TREE *Tree, MM_VAD *Vad)
|
|
{
|
|
if (Tree == NULL || Vad == NULL) {
|
|
return STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
RB_INSERT(VadTree, &Tree->Head, Vad);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
MM_VAD *
|
|
MmVadTreeAllocate(MM_VAD_TREE *Tree, USIZE PageCount)
|
|
{
|
|
MM_VAD *VadBase, *VadIter;
|
|
MM_VAD *VadTmp, *VadNext;
|
|
MM_RANGE *RangeIter;
|
|
UPTR RangeStart, RangeEnd;
|
|
USIZE PagesFound = 0;
|
|
USIZE RangeDelta;
|
|
|
|
if (Tree == NULL || PageCount == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
VadBase = NULL;
|
|
RB_FOREACH(VadIter, VadTree, &Tree->Head) {
|
|
RangeIter = &VadIter->Range;
|
|
RangeStart = RangeIter->VirtualBase;
|
|
RangeEnd = RangeIter->VirtualBase + RangeIter->Length;
|
|
RangeDelta = RangeEnd - RangeStart;
|
|
|
|
/*
|
|
* Do we have exactly a page here? Track that if so, otherwise
|
|
* reset what we've already tracked.
|
|
*/
|
|
if (RangeDelta == PAGESIZE) {
|
|
if (VadBase == NULL)
|
|
VadBase = (MM_VAD *)RangeIter->VirtualBase;
|
|
++PagesFound;
|
|
} else {
|
|
VadBase = NULL;
|
|
--PagesFound;
|
|
}
|
|
|
|
/*
|
|
* If we have found what we requested, remove the entire
|
|
* range and return the base.
|
|
*/
|
|
if (PagesFound >= PageCount) {
|
|
VadTmp = VadBase;
|
|
while (VadTmp != VadIter) {
|
|
VadNext = RB_NEXT(VadTree, &Tree->Head, VadTmp);
|
|
RB_REMOVE(VadTree, &Tree->Head, VadTmp);
|
|
VadTmp = VadNext;
|
|
}
|
|
RB_REMOVE(VadTree, &Tree->Head, VadTmp);
|
|
return VadBase;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|