116 lines
2.6 KiB
C++
116 lines
2.6 KiB
C++
/**
|
|
* Author: Nathan Giddings
|
|
*
|
|
* Code adapted from personal project: https://github.com/ngiddings/quark-libmalloc/blob/master/include/libmalloc/buddy_alloc.h
|
|
*/
|
|
#ifndef PAGE_ALLOCATOR_H
|
|
#define PAGE_ALLOCATOR_H
|
|
|
|
#include "memorymap.h"
|
|
#include "types/physaddr.h"
|
|
|
|
namespace kernel::memory
|
|
{
|
|
|
|
/**
|
|
* @brief Manages the reservation and freeing of physical memory pages.
|
|
*/
|
|
class PageAllocator
|
|
{
|
|
public:
|
|
|
|
static const physaddr_t NOMEM = (physaddr_t)(~0);
|
|
|
|
static unsigned long mapSize(MemoryMap& map, unsigned long blockSize);
|
|
|
|
PageAllocator();
|
|
|
|
/**
|
|
* @brief Constructs the page allocator's internal data structures from an
|
|
* existing description of the memory layout.
|
|
*
|
|
* @param map a description of the physical memory layout
|
|
* @param mapBase location
|
|
* @param blockSize the size in bytes of a single block of memory
|
|
*/
|
|
PageAllocator(MemoryMap& map, void *mapBase, unsigned long blockSize);
|
|
|
|
/**
|
|
* @brief Reserves a chunk of memory at least `size` bytes long. The
|
|
* reserved physical memory will be contiguous; therefore, the allocator
|
|
* can potentially fail due to fragmentation.
|
|
*
|
|
* @param size the minimum number of bytes to reserve
|
|
* @return the physical address of the newly allocated chunk of memory, or
|
|
* NOMEM upon failure.
|
|
*/
|
|
physaddr_t reserve(unsigned long size);
|
|
|
|
/**
|
|
* @brief
|
|
* @param location
|
|
* @return
|
|
*/
|
|
unsigned long free(physaddr_t location);
|
|
|
|
private:
|
|
|
|
class Block
|
|
{
|
|
public:
|
|
|
|
static const unsigned long RESERVED = 0;
|
|
|
|
static const unsigned long FREE = 1;
|
|
|
|
Block();
|
|
|
|
Block(Block *linkf, Block *linkb, unsigned long kval, unsigned long tag);
|
|
|
|
Block *linkb;
|
|
|
|
Block *linkf;
|
|
|
|
unsigned long kval;
|
|
|
|
unsigned long tag;
|
|
|
|
};
|
|
|
|
/**
|
|
* @brief The number of distinct block sizes that are supported. Serves
|
|
* as the maximum possible value of `maxKVal`, and defines the size of
|
|
* the largest possible block: (2 ^ (availListSize-1)) * blockSize.
|
|
*/
|
|
static const int availListSize = 32;
|
|
|
|
Block availList[availListSize];
|
|
|
|
Block *blockMap;
|
|
|
|
unsigned long blockMapSize;
|
|
|
|
unsigned long maxKVal;
|
|
|
|
unsigned long blockSize;
|
|
|
|
unsigned long offset;
|
|
|
|
unsigned long freeBlockCount;
|
|
|
|
/**
|
|
* @brief Inserts a new block into the appropriate linked list, performing
|
|
* mergers with buddy blocks as needed.
|
|
*
|
|
* @param index
|
|
* @param k
|
|
*/
|
|
void insert(unsigned long index, unsigned long k);
|
|
|
|
};
|
|
|
|
extern PageAllocator pageAllocator;
|
|
|
|
}
|
|
|
|
#endif |