uint64_t AllocatePage(uint64_t size, bool Below4Gb) { if(!DidInit) return AllocateFromReserved(size); auto mut = AutoMutex(mtx); OpsSinceLastCoalesce++; size_t trycount = 0; auto len = PageList->size(); begin: if(PageList->size() == 0) { HALT("Out of physical pages"); } Pair* p = PageList->front(); if(Below4Gb && p->BaseAddr >= 0xFFFFFFFF) { trycount++; PageList->erase(PageList->begin()); PageList->push_back(p); goto begin; } else if(p->LengthInPages > size) { p->LengthInPages -= size; uint64_t raddr = p->BaseAddr; p->BaseAddr += (size * 0x1000); return raddr; } else if(p->LengthInPages == size) { auto raddr = p->BaseAddr; PageList->erase(PageList->begin()); delete p; return raddr; } else { if(trycount < len) { auto fr = PageList->front(); PageList->erase(PageList->begin()); PageList->push_back(fr); trycount++; goto begin; // dirty } else { Log(1, "tried allocating %d pages, failed", size); HALT("Out of physical pages"); return 0; } } }
void MoveCursor(uint16_t x, uint16_t y) { if(x <= CharsPerLine && y <= CharsPerColumn) { AutoMutex lk = AutoMutex(Mutexes::ConsoleOutput); VT_CursorX = x; VT_CursorY = y; } }
void CoalesceFPLs() { if(!DidInit) return; // check if we even need to coalesce if(OpsSinceLastCoalesce < CoalesceThreshold) return; Log("Coalesced FPLs"); auto mut = AutoMutex(mtx); OpsSinceLastCoalesce = 0; // O(n^2) time. // essentially, loop in a loop. // for each entry in the list, loop through all the other entries to see if there's anything suitable. // if so, merge. // to make sure we don't screw with the list while in the middle of it, go back to the beginning and loop again. // this is a background process anyway so. for(size_t i = 0; i < PageList->size(); i++) { bool delp = false; // Pair* p = PageList->pop_front(); auto p = PageList->front(); PageList->erase(PageList->begin()); uint64_t base = p->BaseAddr; uint64_t end = p->BaseAddr + (p->LengthInPages * 0x1000); for(size_t k = 0; k < PageList->size(); k++) { // Pair* other = PageList->pop_front(); auto other = PageList->front(); PageList->erase(PageList->begin()); if(other->BaseAddr == end) { p->LengthInPages += other->LengthInPages; delete other; break; } else if(other->BaseAddr + (other->LengthInPages * 0x1000) == base) { other->LengthInPages += p->LengthInPages; delp = true; break; } } if(delp) { delete p; } else PageList->push_back(p); } }
void FreePage(uint64_t page, uint64_t size) { auto mut = AutoMutex(mtx); OpsSinceLastCoalesce++; uint64_t end = page + (size * 0x1000); bool ret = false; for(size_t i = 0; i < PageList->size(); i++) { Pair* pair = PageList->front(); PageList->erase_unordered(PageList->begin()); // 3 basic conditions // 1. we find a match below a pair's baseaddr // 2. we find a match above a pair's baseaddr // 3. we don't find a match if(end == pair->BaseAddr) { pair->BaseAddr = page; pair->LengthInPages += size; ret = true; } else if(pair->BaseAddr + (pair->LengthInPages * 0x1000) == page) { pair->LengthInPages += size; ret = true; } PageList->push_back(pair); if(ret) return; } // if we reach here, we haven't found a match. Pair* np = new Pair(); np->BaseAddr = page; np->LengthInPages = size; PageList->push_back(np); }
void PrintChar(uint8_t c) { if(c == 0) return; if(SERIALMIRROR){ HardwareAbstraction::Devices::SerialPort::WriteChar(c); } if(!IsInitialised()) { Kernel::HardwareAbstraction::VideoOutput::Console80x25::PrintChar(c); return; } AutoMutex lk = AutoMutex(Mutexes::ConsoleOutput); if(c == '\r') { VT_CursorX = 0; return; } if(c == '\b') { if(VT_CursorX > 0) { VT_CursorX--; DrawChar(' ', (VT_CursorX * CharWidth) + OffsetLeft, (VT_CursorY * 16), VT_Colour); } else if(VT_CursorY > 0) { VT_CursorX = CharsPerLine - 1; VT_CursorY--; DrawChar(' ', (VT_CursorX * CharWidth) + OffsetLeft, (VT_CursorY * 16), VT_Colour); } return; } if(VT_CursorY == CharsPerColumn && VT_CursorX == CharsPerLine) { // Reached end of line and no more space below VT_CursorX = 0; ScrollDown(1); if(c == '\n' || c == '\t') { ScrollDown(1); VT_CursorX = 0; return; } DrawChar(c, (VT_CursorX * CharWidth) + OffsetLeft, (VT_CursorY * 16), VT_Colour); VT_CursorX++; } else if((VT_CursorX * 8) >= ((GetResX()) - 10)) { // Reached end of line VT_CursorX = 0; VT_CursorY++; DrawChar(c, (VT_CursorX * CharWidth) + OffsetLeft, (VT_CursorY * 16), VT_Colour); VT_CursorX = 1; } else { if(c == '\n') { if(VT_CursorY < CharsPerColumn) { VT_CursorX = 0; VT_CursorY++; } else { VT_CursorX = 0; ScrollDown(1); } return; } else if(c == '\t') { if(((VT_CursorX + 4) & ~(4 - 1)) < CharsPerLine) { VT_CursorX = (VT_CursorX + 4) & ~(4 - 1); } else { VT_CursorX = 0; if(VT_CursorY < CharsPerColumn) VT_CursorY++; else ScrollDown(1); } return; } // Normal printing DrawChar(c, (VT_CursorX * CharWidth) + OffsetLeft, (VT_CursorY * 16), VT_Colour); VT_CursorX++; } return; }