diff --git a/src/memory/FrameAllocator.cc b/src/memory/FrameAllocator.cc index a862e0a..278873d 100644 --- a/src/memory/FrameAllocator.cc +++ b/src/memory/FrameAllocator.cc @@ -47,6 +47,25 @@ FrameAllocator::initialize(const StartupInformation& startupInformation) reserveRange(startupInformation.kernelStart, startupInformation.kernelSize() + mBitmapSize); } +void* +FrameAllocator::allocate() +{ + // Find the first bitmap with a free slot, and the first free slot, and return it. + const u32 pagesPerBitmap = Bitmap::length; + for (usize i = 0; i < mNumberOfPages; i += pagesPerBitmap) { + auto bitmap = mBitmap[i]; + if (!bitmap.isFull()) { + for (usize j = 0; j < pagesPerBitmap; j++) { + if (!bitmap.isSet(j)) { + bitmap.set(j); + return addressOfPage(i * pagesPerBitmap + j); + } + } + } + } + return nullptr; +} + void FrameAllocator::reserveRange(u32 start, u32 length) @@ -88,4 +107,11 @@ FrameAllocator::reserveRange(u32 start, } } +inline void* +FrameAllocator::addressOfPage(usize page) + const +{ + return reinterpret_cast(page * memory::pageSize); +} + } /* namespace kernel */ diff --git a/src/memory/FrameAllocator.hh b/src/memory/FrameAllocator.hh index e6cd407..bd07cdc 100644 --- a/src/memory/FrameAllocator.hh +++ b/src/memory/FrameAllocator.hh @@ -21,6 +21,14 @@ struct FrameAllocator void initialize(const StartupInformation& startupInformation); + /** + * Allocate a page. Find a free page, mark it in use, and return its + * address. + * + * @return The base address of a free page, or 0 if no page could be allocated. + */ + void* allocate(); + private: typedef kstd::Bitmap Bitmap; @@ -33,6 +41,9 @@ private: /** Reserve a range of memory. */ void reserveRange(u32 start, u32 length); + + /** Return the physical memory address of `page`. */ + void* addressOfPage(usize page) const; }; } /* namespace */