/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: Virtual address descriptor management * Author: Chloe M. */ #include #include /* 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; }