mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-23 21:21:41 +00:00
Update kernel code
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# Xalloc
|
||||
|
||||
Xalloc is a custom memory allocator designed for hobby operating systems. It is written in C++ and provides a simple and efficient way to manage memory in your hobby OS.
|
||||
Xalloc is a custom memory allocator designed for hobby operating systems.
|
||||
Written in C++ and provides a simple and efficient way to manage memory in your hobby OS.
|
||||
|
||||
#### ❗ This project is still in development and is not ready for use in production environments. ❗
|
||||
|
||||
@@ -8,9 +9,11 @@ Xalloc is a custom memory allocator designed for hobby operating systems. It is
|
||||
|
||||
## Features
|
||||
|
||||
- **Simple API** - Xalloc provides a simple API for allocating and freeing memory. It is designed to be easy to use and understand.
|
||||
- **Simple API** - Simple API for allocating and freeing memory.
|
||||
|
||||
- [ ] todo complete this
|
||||
- **Efficient** - Uses a free-list to manage memory and is designed to be fast.
|
||||
|
||||
- **No dependencies** - No dependencies and is designed to be easy to integrate into your OS.
|
||||
|
||||
---
|
||||
|
||||
@@ -32,11 +35,13 @@ extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
||||
// ...
|
||||
}
|
||||
|
||||
/* Mandatory only if Xalloc_MapPages is set to true */
|
||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
/* Mandatory only if Xalloc_MapPages is set to true */
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
{
|
||||
// ...
|
||||
@@ -45,13 +50,21 @@ extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
|
||||
##### Xalloc.hpp
|
||||
```cpp
|
||||
#define Xalloc_StopOnFail <bool> /* Infinite loop on failure */
|
||||
#define Xalloc_MapPages <bool> /* Map pages on allocation */
|
||||
#define Xalloc_PAGE_SIZE <page size> /* <-- Replace with your page size */
|
||||
#define Xalloc_trace(m, ...) <trace function>
|
||||
#define Xalloc_warn(m, ...) <warning function>
|
||||
#define Xalloc_err(m, ...) <error function>
|
||||
#define Xalloc_def <define a lock> /* eg. std::mutex Xalloc_lock; */
|
||||
#define Xalloc_lock <lock function>
|
||||
#define Xalloc_unlock <unlock function>
|
||||
|
||||
#define XallocV1_def <define a lock> /* eg. std::mutex Xalloc_lock; */
|
||||
#define XallocV1_lock <lock function>
|
||||
#define XallocV1_unlock <unlock function>
|
||||
|
||||
/* Same as above */
|
||||
#define XallocV2_def <define a lock>
|
||||
#define XallocV2_lock <lock function>
|
||||
#define XallocV2_unlock <unlock function>
|
||||
```
|
||||
|
||||
### Typical usage
|
||||
@@ -135,3 +148,7 @@ If `Size` is equal to zero, and `Address` is not `nullptr`, then the call is equ
|
||||
- `Size` - The new size of the memory block in bytes.
|
||||
|
||||
---
|
||||
|
||||
## To-do
|
||||
|
||||
- [ ] Multiple free-lists for different block sizes
|
||||
|
@@ -21,20 +21,20 @@
|
||||
|
||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
|
||||
{
|
||||
return KernelAllocator.RequestPages(Pages);
|
||||
return KernelAllocator.RequestPages(Pages);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
||||
{
|
||||
KernelAllocator.FreePages(Address, Pages);
|
||||
KernelAllocator.FreePages(Address, Pages);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
||||
{
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
{
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
||||
|
@@ -22,98 +22,215 @@
|
||||
#include <lock.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
typedef long unsigned Xuint64_t;
|
||||
typedef long unsigned Xsize_t;
|
||||
typedef __UINT8_TYPE__ Xuint8_t;
|
||||
typedef __SIZE_TYPE__ Xsize_t;
|
||||
typedef __UINTPTR_TYPE__ Xuintptr_t;
|
||||
|
||||
#define Xalloc_StopOnFail true
|
||||
#define Xalloc_MapPages true
|
||||
#define Xalloc_PAGE_SIZE PAGE_SIZE
|
||||
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
|
||||
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
|
||||
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
|
||||
#define Xalloc_def NewLock(XallocLock)
|
||||
#define Xalloc_lock XallocLock.Lock(__FUNCTION__)
|
||||
#define Xalloc_unlock XallocLock.Unlock()
|
||||
|
||||
#define XallocV1_def NewLock(XallocV1Lock)
|
||||
#define XallocV1_lock XallocV1Lock.Lock(__FUNCTION__)
|
||||
#define XallocV1_unlock XallocV1Lock.Unlock()
|
||||
|
||||
#define XallocV2_def NewLock(XallocV2Lock)
|
||||
#define XallocV2_lock XallocV2Lock.Lock(__FUNCTION__)
|
||||
#define XallocV2_unlock XallocV2Lock.Unlock()
|
||||
|
||||
namespace Xalloc
|
||||
{
|
||||
class V1
|
||||
{
|
||||
private:
|
||||
void *BaseVirtualAddress = nullptr;
|
||||
void *FirstBlock = nullptr;
|
||||
void *LastBlock = nullptr;
|
||||
class V1
|
||||
{
|
||||
private:
|
||||
void *BaseVirtualAddress = nullptr;
|
||||
void *FirstBlock = nullptr;
|
||||
void *LastBlock = nullptr;
|
||||
|
||||
bool UserMapping = false;
|
||||
bool SMAPUsed = false;
|
||||
bool UserMapping = false;
|
||||
bool SMAPUsed = false;
|
||||
|
||||
public:
|
||||
/** @brief Execute "stac" instruction if the kernel has SMAP enabled */
|
||||
void Xstac();
|
||||
public:
|
||||
/** @brief Execute "stac" instruction if the kernel has SMAP enabled */
|
||||
void Xstac();
|
||||
|
||||
/** @brief Execute "clac" instruction if the kernel has SMAP enabled */
|
||||
void Xclac();
|
||||
/** @brief Execute "clac" instruction if the kernel has SMAP enabled */
|
||||
void Xclac();
|
||||
|
||||
/**
|
||||
* @brief Arrange the blocks to optimize the memory usage
|
||||
* The allocator is not arranged by default
|
||||
* to avoid performance issues.
|
||||
* This function will defragment the memory
|
||||
* and free the unused blocks.
|
||||
*
|
||||
* You should call this function when the
|
||||
* kernel is idle or when is not using
|
||||
* the allocator.
|
||||
*/
|
||||
void Arrange();
|
||||
/**
|
||||
* @brief Arrange the blocks to optimize the memory usage
|
||||
* The allocator is not arranged by default
|
||||
* to avoid performance issues.
|
||||
* This function will defragment the memory
|
||||
* and free the unused blocks.
|
||||
*
|
||||
* You should call this function when the
|
||||
* kernel is idle or when is not using
|
||||
* the allocator.
|
||||
*/
|
||||
void Arrange();
|
||||
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *malloc(Xsize_t Size);
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *malloc(Xsize_t Size);
|
||||
|
||||
/**
|
||||
* @brief Free a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to free.
|
||||
*/
|
||||
void free(void *Address);
|
||||
/**
|
||||
* @brief Free a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to free.
|
||||
*/
|
||||
void free(void *Address);
|
||||
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param NumberOfBlocks Number of blocks to allocate.
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
|
||||
/**
|
||||
* @brief Allocate a new memory block
|
||||
*
|
||||
* @param NumberOfBlocks Number of blocks to allocate.
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated block.
|
||||
*/
|
||||
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
|
||||
|
||||
/**
|
||||
* @brief Reallocate a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to reallocate.
|
||||
* @param Size New size of the block.
|
||||
* @return void* Pointer to the reallocated block.
|
||||
*/
|
||||
void *realloc(void *Address, Xsize_t Size);
|
||||
/**
|
||||
* @brief Reallocate a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to reallocate.
|
||||
* @param Size New size of the block.
|
||||
* @return void* Pointer to the reallocated block.
|
||||
*/
|
||||
void *realloc(void *Address, Xsize_t Size);
|
||||
|
||||
/**
|
||||
* @brief Construct a new Allocator object
|
||||
*
|
||||
* @param BaseVirtualAddress Virtual address to map the pages.
|
||||
* @param UserMode Map the new pages with USER flag?
|
||||
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
|
||||
*/
|
||||
V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled);
|
||||
/**
|
||||
* @brief Construct a new Allocator object
|
||||
*
|
||||
* @param BaseVirtualAddress Virtual address to map the pages.
|
||||
* @param UserMode Map the new pages with USER flag?
|
||||
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
|
||||
*/
|
||||
V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled);
|
||||
|
||||
/**
|
||||
* @brief Destroy the Allocator object
|
||||
*
|
||||
*/
|
||||
~V1();
|
||||
};
|
||||
/**
|
||||
* @brief Destroy the Allocator object
|
||||
*
|
||||
*/
|
||||
~V1();
|
||||
};
|
||||
|
||||
class V2
|
||||
{
|
||||
private:
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
int Sanity = 0xA110C;
|
||||
Block *Next = nullptr;
|
||||
bool IsFree = true;
|
||||
V2 *ctx = nullptr;
|
||||
|
||||
Xuint8_t *Data = nullptr;
|
||||
Xsize_t DataSize = 0;
|
||||
|
||||
void Check();
|
||||
Block(Xsize_t Size, V2 *ctx);
|
||||
~Block();
|
||||
void *operator new(Xsize_t);
|
||||
void operator delete(void *Address);
|
||||
} __attribute__((packed, aligned((16))));
|
||||
|
||||
/* The base address of the virtual memory */
|
||||
Xuintptr_t BaseVirtualAddress = 0x0;
|
||||
|
||||
/* The size of the heap */
|
||||
Xsize_t HeapSize = 0x0;
|
||||
|
||||
/* The used size of the heap */
|
||||
Xsize_t HeapUsed = 0x0;
|
||||
|
||||
Block *FirstBlock = nullptr;
|
||||
|
||||
Xuint8_t *AllocateHeap(Xsize_t Size);
|
||||
void FreeHeap(Xuint8_t *At, Xsize_t Size);
|
||||
|
||||
Xsize_t Align(Xsize_t Size);
|
||||
void *FindFreeBlock(Xsize_t Size,
|
||||
Block *&CurrentBlock);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Arrange the blocks to optimize the memory
|
||||
* usage.
|
||||
* The allocator is not arranged by default
|
||||
* to avoid performance issues.
|
||||
* This function will defragment the memory
|
||||
* and free the unused blocks.
|
||||
*
|
||||
* You should call this function when the
|
||||
* kernel is idle or when is not using the
|
||||
* allocator.
|
||||
*/
|
||||
void Arrange();
|
||||
|
||||
/**
|
||||
* Allocate a new memory block
|
||||
*
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated
|
||||
* block.
|
||||
*/
|
||||
void *malloc(Xsize_t Size);
|
||||
|
||||
/**
|
||||
* Free a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block to
|
||||
* free.
|
||||
*/
|
||||
void free(void *Address);
|
||||
|
||||
/**
|
||||
* Allocate a new memory block
|
||||
*
|
||||
* @param NumberOfBlocks Number of blocks
|
||||
* to allocate.
|
||||
* @param Size Size of the block to allocate.
|
||||
* @return void* Pointer to the allocated
|
||||
* block.
|
||||
*/
|
||||
void *calloc(Xsize_t NumberOfBlocks,
|
||||
Xsize_t Size);
|
||||
|
||||
/**
|
||||
* Reallocate a previously allocated block
|
||||
*
|
||||
* @param Address Address of the block
|
||||
* to reallocate.
|
||||
* @param Size New size of the block.
|
||||
* @return void* Pointer to the reallocated
|
||||
* block.
|
||||
*/
|
||||
void *realloc(void *Address, Xsize_t Size);
|
||||
|
||||
/**
|
||||
* Construct a new Allocator object
|
||||
*
|
||||
* @param VirtualBase Virtual address
|
||||
* to map the pages.
|
||||
*/
|
||||
V2(void *VirtualBase);
|
||||
|
||||
/**
|
||||
* Destroy the Allocator object
|
||||
*/
|
||||
~V2();
|
||||
|
||||
friend class Block;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_Xalloc_H__
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "Xalloc.hpp"
|
||||
|
||||
Xalloc_def;
|
||||
XallocV1_def;
|
||||
|
||||
#define XALLOC_CONCAT(x, y) x##y
|
||||
#define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
@@ -30,261 +30,261 @@ extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, X
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress);
|
||||
|
||||
// TODO: Change memcpy with an optimized version
|
||||
void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length)
|
||||
void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xsize_t Length)
|
||||
{
|
||||
unsigned char *dst = (unsigned char *)Destination;
|
||||
const unsigned char *src = (const unsigned char *)Source;
|
||||
for (Xuint64_t i = 0; i < Length; i++)
|
||||
dst[i] = src[i];
|
||||
return Destination;
|
||||
unsigned char *dst = (unsigned char *)Destination;
|
||||
const unsigned char *src = (const unsigned char *)Source;
|
||||
for (Xsize_t i = 0; i < Length; i++)
|
||||
dst[i] = src[i];
|
||||
return Destination;
|
||||
}
|
||||
|
||||
// TODO: Change memset with an optimized version
|
||||
void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length)
|
||||
void *Xmemset(void *__restrict__ Destination, int Data, Xsize_t Length)
|
||||
{
|
||||
unsigned char *Buffer = (unsigned char *)Destination;
|
||||
for (Xuint64_t i = 0; i < Length; i++)
|
||||
Buffer[i] = (unsigned char)Data;
|
||||
return Destination;
|
||||
unsigned char *Buffer = (unsigned char *)Destination;
|
||||
for (Xsize_t i = 0; i < Length; i++)
|
||||
Buffer[i] = (unsigned char)Data;
|
||||
return Destination;
|
||||
}
|
||||
|
||||
namespace Xalloc
|
||||
{
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
void *Address = nullptr;
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
void *Address = nullptr;
|
||||
|
||||
int Sanity = Xalloc_BlockSanityKey;
|
||||
Xsize_t Size = 0;
|
||||
Block *Next = nullptr;
|
||||
Block *Last = nullptr;
|
||||
bool IsFree = true;
|
||||
int Sanity = Xalloc_BlockSanityKey;
|
||||
Xsize_t Size = 0;
|
||||
Block *Next = nullptr;
|
||||
Block *Last = nullptr;
|
||||
bool IsFree = true;
|
||||
|
||||
bool Check()
|
||||
{
|
||||
if (this->Sanity != Xalloc_BlockSanityKey)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
bool Check()
|
||||
{
|
||||
if (this->Sanity != Xalloc_BlockSanityKey)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Block(Xsize_t Size)
|
||||
{
|
||||
this->Address = Xalloc_REQUEST_PAGES(XStoP(Size + 1));
|
||||
this->Size = Size;
|
||||
Xmemset(this->Address, 0, Size);
|
||||
}
|
||||
Block(Xsize_t Size)
|
||||
{
|
||||
this->Address = Xalloc_REQUEST_PAGES(XStoP(Size + 1));
|
||||
this->Size = Size;
|
||||
Xmemset(this->Address, 0, Size);
|
||||
}
|
||||
|
||||
~Block()
|
||||
{
|
||||
Xalloc_FREE_PAGES(this->Address, XStoP(this->Size + 1));
|
||||
}
|
||||
~Block()
|
||||
{
|
||||
Xalloc_FREE_PAGES(this->Address, XStoP(this->Size + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overload new operator to allocate memory from the heap
|
||||
* @param Size Unused
|
||||
* @return void* Pointer to the allocated memory
|
||||
*/
|
||||
void *operator new(Xsize_t Size)
|
||||
{
|
||||
void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block)));
|
||||
return ptr;
|
||||
(void)(Size);
|
||||
}
|
||||
/**
|
||||
* @brief Overload new operator to allocate memory from the heap
|
||||
* @param Size Unused
|
||||
* @return void* Pointer to the allocated memory
|
||||
*/
|
||||
void *operator new(Xsize_t Size)
|
||||
{
|
||||
void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block)));
|
||||
return ptr;
|
||||
(void)(Size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Overload delete operator to free memory from the heap
|
||||
* @param Address Pointer to the memory to free
|
||||
*/
|
||||
void operator delete(void *Address)
|
||||
{
|
||||
Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block)));
|
||||
}
|
||||
} __attribute__((packed, aligned((16))));
|
||||
/**
|
||||
* @brief Overload delete operator to free memory from the heap
|
||||
* @param Address Pointer to the memory to free
|
||||
*/
|
||||
void operator delete(void *Address)
|
||||
{
|
||||
Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block)));
|
||||
}
|
||||
} __attribute__((packed, aligned((16))));
|
||||
|
||||
class SmartSMAPClass
|
||||
{
|
||||
private:
|
||||
V1 *allocator = nullptr;
|
||||
class SmartSMAPClass
|
||||
{
|
||||
private:
|
||||
V1 *allocator = nullptr;
|
||||
|
||||
public:
|
||||
SmartSMAPClass(V1 *allocator)
|
||||
{
|
||||
this->allocator = allocator;
|
||||
this->allocator->Xstac();
|
||||
}
|
||||
~SmartSMAPClass() { this->allocator->Xclac(); }
|
||||
};
|
||||
public:
|
||||
SmartSMAPClass(V1 *allocator)
|
||||
{
|
||||
this->allocator = allocator;
|
||||
this->allocator->Xstac();
|
||||
}
|
||||
~SmartSMAPClass() { this->allocator->Xclac(); }
|
||||
};
|
||||
#define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this)
|
||||
|
||||
void V1::Xstac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
void V1::Xstac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
#if defined(a86)
|
||||
asm volatile("stac" ::
|
||||
: "cc");
|
||||
asm volatile("stac" ::
|
||||
: "cc");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V1::Xclac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
void V1::Xclac()
|
||||
{
|
||||
if (this->SMAPUsed)
|
||||
{
|
||||
#if defined(a86)
|
||||
asm volatile("clac" ::
|
||||
: "cc");
|
||||
asm volatile("clac" ::
|
||||
: "cc");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void V1::Arrange()
|
||||
{
|
||||
Xalloc_err("Arrange() is not implemented yet!");
|
||||
}
|
||||
void V1::Arrange()
|
||||
{
|
||||
Xalloc_err("Arrange() is not implemented yet!");
|
||||
}
|
||||
|
||||
void *V1::malloc(Xsize_t Size)
|
||||
{
|
||||
if (Size == 0)
|
||||
{
|
||||
Xalloc_warn("Attempted to allocate 0 bytes!");
|
||||
return nullptr;
|
||||
}
|
||||
void *V1::malloc(Xsize_t Size)
|
||||
{
|
||||
if (Size == 0)
|
||||
{
|
||||
Xalloc_warn("Attempted to allocate 0 bytes!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
|
||||
if (this->FirstBlock == nullptr)
|
||||
{
|
||||
this->FirstBlock = new Block(Size);
|
||||
((Block *)this->FirstBlock)->IsFree = false;
|
||||
Xalloc_unlock;
|
||||
return ((Block *)this->FirstBlock)->Address;
|
||||
}
|
||||
if (this->FirstBlock == nullptr)
|
||||
{
|
||||
this->FirstBlock = new Block(Size);
|
||||
((Block *)this->FirstBlock)->IsFree = false;
|
||||
XallocV1_unlock;
|
||||
return ((Block *)this->FirstBlock)->Address;
|
||||
}
|
||||
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size)
|
||||
{
|
||||
CurrentBlock->IsFree = false;
|
||||
Xmemset(CurrentBlock->Address, 0, Size);
|
||||
Xalloc_unlock;
|
||||
return CurrentBlock->Address;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size)
|
||||
{
|
||||
CurrentBlock->IsFree = false;
|
||||
Xmemset(CurrentBlock->Address, 0, Size);
|
||||
XallocV1_unlock;
|
||||
return CurrentBlock->Address;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
|
||||
CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock->Next != nullptr)
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock->Next != nullptr)
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
|
||||
CurrentBlock->Next = new Block(Size);
|
||||
((Block *)CurrentBlock->Next)->Last = CurrentBlock;
|
||||
((Block *)CurrentBlock->Next)->IsFree = false;
|
||||
Xalloc_unlock;
|
||||
return ((Block *)CurrentBlock->Next)->Address;
|
||||
}
|
||||
CurrentBlock->Next = new Block(Size);
|
||||
((Block *)CurrentBlock->Next)->Last = CurrentBlock;
|
||||
((Block *)CurrentBlock->Next)->IsFree = false;
|
||||
XallocV1_unlock;
|
||||
return ((Block *)CurrentBlock->Next)->Address;
|
||||
}
|
||||
|
||||
void V1::free(void *Address)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
{
|
||||
Xalloc_warn("Attempted to free a null pointer!");
|
||||
return;
|
||||
}
|
||||
void V1::free(void *Address)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
{
|
||||
Xalloc_warn("Attempted to free a null pointer!");
|
||||
return;
|
||||
}
|
||||
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->Address == Address)
|
||||
{
|
||||
if (CurrentBlock->IsFree)
|
||||
{
|
||||
Xalloc_warn("Attempted to free an already freed pointer!");
|
||||
Xalloc_unlock;
|
||||
return;
|
||||
}
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
if (!CurrentBlock->Check())
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
(Xsize_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
else if (CurrentBlock->Address == Address)
|
||||
{
|
||||
if (CurrentBlock->IsFree)
|
||||
{
|
||||
Xalloc_warn("Attempted to free an already freed pointer!");
|
||||
XallocV1_unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentBlock->IsFree = true;
|
||||
Xalloc_unlock;
|
||||
return;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
CurrentBlock->IsFree = true;
|
||||
XallocV1_unlock;
|
||||
return;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
|
||||
Xalloc_err("Invalid address %#lx.", Address);
|
||||
Xalloc_unlock;
|
||||
}
|
||||
Xalloc_err("Invalid address %#lx.", Address);
|
||||
XallocV1_unlock;
|
||||
}
|
||||
|
||||
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
|
||||
{
|
||||
if (NumberOfBlocks == 0 || Size == 0)
|
||||
{
|
||||
Xalloc_warn("The %s%s%s is 0!",
|
||||
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
|
||||
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
|
||||
Size == 0 ? "Size" : "");
|
||||
return nullptr;
|
||||
}
|
||||
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
|
||||
{
|
||||
if (NumberOfBlocks == 0 || Size == 0)
|
||||
{
|
||||
Xalloc_warn("The %s%s%s is 0!",
|
||||
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
|
||||
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
|
||||
Size == 0 ? "Size" : "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->malloc(NumberOfBlocks * Size);
|
||||
}
|
||||
return this->malloc(NumberOfBlocks * Size);
|
||||
}
|
||||
|
||||
void *V1::realloc(void *Address, Xsize_t Size)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
return this->malloc(Size);
|
||||
void *V1::realloc(void *Address, Xsize_t Size)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
return this->malloc(Size);
|
||||
|
||||
if (Size == 0)
|
||||
{
|
||||
this->free(Address);
|
||||
return nullptr;
|
||||
}
|
||||
if (Size == 0)
|
||||
{
|
||||
this->free(Address);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// SmartSMAP;
|
||||
// Xalloc_lock;
|
||||
// ...
|
||||
// Xalloc_unlock;
|
||||
// SmartSMAP;
|
||||
// XallocV1_lock;
|
||||
// ...
|
||||
// XallocV1_unlock;
|
||||
|
||||
// TODO: Implement realloc
|
||||
this->free(Address);
|
||||
return this->malloc(Size);
|
||||
}
|
||||
// TODO: Implement realloc
|
||||
this->free(Address);
|
||||
return this->malloc(Size);
|
||||
}
|
||||
|
||||
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
|
||||
{
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
this->SMAPUsed = SMAPEnabled;
|
||||
this->UserMapping = UserMode;
|
||||
this->BaseVirtualAddress = BaseVirtualAddress;
|
||||
Xalloc_unlock;
|
||||
}
|
||||
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
|
||||
{
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
this->SMAPUsed = SMAPEnabled;
|
||||
this->UserMapping = UserMode;
|
||||
this->BaseVirtualAddress = BaseVirtualAddress;
|
||||
XallocV1_unlock;
|
||||
}
|
||||
|
||||
V1::~V1()
|
||||
{
|
||||
SmartSMAP;
|
||||
Xalloc_lock;
|
||||
Xalloc_trace("Destructor not implemented yet.");
|
||||
Xalloc_unlock;
|
||||
}
|
||||
V1::~V1()
|
||||
{
|
||||
SmartSMAP;
|
||||
XallocV1_lock;
|
||||
Xalloc_trace("Destructor not implemented yet.");
|
||||
XallocV1_unlock;
|
||||
}
|
||||
}
|
||||
|
281
Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp
Normal file
281
Core/Memory/HeapAllocators/Xalloc/XallocV2.cpp
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Xalloc.hpp"
|
||||
|
||||
XallocV2_def;
|
||||
|
||||
#define XALLOC_CONCAT(x, y) x##y
|
||||
#define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
#define XPtoS(d) ((d)*PAGE_SIZE)
|
||||
|
||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages);
|
||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages);
|
||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress,
|
||||
void *PhysicalAddress,
|
||||
Xsize_t Flags);
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress);
|
||||
|
||||
#define Xalloc_BlockSanityKey 0xA110C
|
||||
|
||||
/*
|
||||
[ IN DEVELOPMENT ]
|
||||
*/
|
||||
|
||||
namespace Xalloc
|
||||
{
|
||||
void V2::Block::Check()
|
||||
{
|
||||
if (unlikely(this->Sanity != Xalloc_BlockSanityKey))
|
||||
{
|
||||
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
|
||||
this, this->Sanity, Xalloc_BlockSanityKey);
|
||||
|
||||
while (Xalloc_StopOnFail)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
V2::Block::Block(Xsize_t Size, V2 *ctx)
|
||||
{
|
||||
this->ctx = ctx;
|
||||
this->Data = ctx->AllocateHeap(Size);
|
||||
this->DataSize = Size;
|
||||
}
|
||||
|
||||
V2::Block::~Block()
|
||||
{
|
||||
}
|
||||
|
||||
void *V2::Block::operator new(Xsize_t)
|
||||
{
|
||||
constexpr Xsize_t bPgs = XStoP(sizeof(Block));
|
||||
void *ptr = Xalloc_REQUEST_PAGES(bPgs);
|
||||
/* TODO: Do something with the rest of
|
||||
the allocated memory */
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void V2::Block::operator delete(void *Address)
|
||||
{
|
||||
constexpr Xsize_t bPgs = XStoP(sizeof(Block));
|
||||
Xalloc_FREE_PAGES(Address, bPgs);
|
||||
}
|
||||
|
||||
/* ========================================= */
|
||||
|
||||
Xuint8_t *V2::AllocateHeap(Xsize_t Size)
|
||||
{
|
||||
Size = this->Align(Size);
|
||||
Xsize_t Pages = XStoP(Size);
|
||||
|
||||
Xuint8_t *FinalAddress = 0x0;
|
||||
if (this->HeapUsed + Size >= this->HeapSize)
|
||||
{
|
||||
void *Address = Xalloc_REQUEST_PAGES(Pages);
|
||||
void *VirtualAddress = (void *)(this->BaseVirtualAddress + this->HeapSize);
|
||||
if (Xalloc_MapPages)
|
||||
{
|
||||
for (Xsize_t i = 0; i < Pages; i++)
|
||||
{
|
||||
Xuintptr_t Page = i * Xalloc_PAGE_SIZE;
|
||||
void *vAddress = (void *)((Xuintptr_t)VirtualAddress + Page);
|
||||
Xalloc_MAP_MEMORY(vAddress, (void *)((Xuintptr_t)Address + Page), 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
this->HeapSize += XPtoS(Pages);
|
||||
FinalAddress = (Xuint8_t *)VirtualAddress;
|
||||
}
|
||||
else
|
||||
FinalAddress = (Xuint8_t *)(this->BaseVirtualAddress + this->HeapUsed);
|
||||
|
||||
this->HeapUsed += Size;
|
||||
return (uint8_t *)FinalAddress;
|
||||
}
|
||||
|
||||
void V2::FreeHeap(Xuint8_t *At, Xsize_t Size)
|
||||
{
|
||||
Xsize_t Pages = XStoP(Size);
|
||||
|
||||
if (Xalloc_MapPages)
|
||||
{
|
||||
for (Xsize_t i = 0; i < Pages; i++)
|
||||
{
|
||||
Xuintptr_t Page = i * Xalloc_PAGE_SIZE;
|
||||
void *VirtualAddress = (void *)((Xuintptr_t)At + Page);
|
||||
Xalloc_UNMAP_MEMORY(VirtualAddress);
|
||||
}
|
||||
}
|
||||
|
||||
Xalloc_FREE_PAGES(At, Pages);
|
||||
this->HeapUsed -= Size;
|
||||
}
|
||||
|
||||
Xsize_t V2::Align(Xsize_t Size)
|
||||
{
|
||||
return (Size + 0xF) & ~0xF;
|
||||
}
|
||||
|
||||
void *V2::FindFreeBlock(Xsize_t Size, Block *&CurrentBlock)
|
||||
{
|
||||
if (this->FirstBlock == nullptr)
|
||||
{
|
||||
this->FirstBlock = new Block(Size, this);
|
||||
this->FirstBlock->IsFree = false;
|
||||
return this->FirstBlock->Data;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
CurrentBlock->Check();
|
||||
|
||||
/* FIXME: This will waste a lot of space
|
||||
need better algorithm */
|
||||
if (CurrentBlock->IsFree &&
|
||||
CurrentBlock->DataSize >= Size)
|
||||
{
|
||||
CurrentBlock->IsFree = false;
|
||||
return CurrentBlock->Data;
|
||||
}
|
||||
|
||||
if (CurrentBlock->Next == nullptr)
|
||||
break;
|
||||
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void V2::Arrange()
|
||||
{
|
||||
Xalloc_err("Arrange() is not implemented yet!");
|
||||
}
|
||||
|
||||
void *V2::malloc(Xsize_t Size)
|
||||
{
|
||||
if (Size == 0)
|
||||
{
|
||||
Xalloc_warn("Attempted to allocate 0 bytes!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
XallocV2_lock;
|
||||
Block *CurrentBlock = this->FirstBlock;
|
||||
void *ret = this->FindFreeBlock(Size, CurrentBlock);
|
||||
if (ret)
|
||||
{
|
||||
XallocV2_unlock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CurrentBlock->Next = new Block(Size, this);
|
||||
CurrentBlock->Next->IsFree = false;
|
||||
XallocV2_unlock;
|
||||
return CurrentBlock->Next->Data;
|
||||
}
|
||||
|
||||
void V2::free(void *Address)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
{
|
||||
Xalloc_warn("Attempted to free a null pointer!");
|
||||
return;
|
||||
}
|
||||
|
||||
XallocV2_lock;
|
||||
|
||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
||||
while (CurrentBlock != nullptr)
|
||||
{
|
||||
CurrentBlock->Check();
|
||||
|
||||
if (CurrentBlock->Data == Address)
|
||||
{
|
||||
if (CurrentBlock->IsFree)
|
||||
Xalloc_warn("Attempted to free an already freed block! %#lx", Address);
|
||||
|
||||
CurrentBlock->IsFree = true;
|
||||
XallocV2_unlock;
|
||||
return;
|
||||
}
|
||||
CurrentBlock = CurrentBlock->Next;
|
||||
}
|
||||
|
||||
Xalloc_err("Invalid address %#lx.", Address);
|
||||
XallocV2_unlock;
|
||||
}
|
||||
|
||||
void *V2::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
|
||||
{
|
||||
if (NumberOfBlocks == 0 || Size == 0)
|
||||
{
|
||||
Xalloc_warn("The %s%s%s is 0!",
|
||||
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
|
||||
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
|
||||
Size == 0 ? "Size" : "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return this->malloc(NumberOfBlocks * Size);
|
||||
}
|
||||
|
||||
void *V2::realloc(void *Address, Xsize_t Size)
|
||||
{
|
||||
if (Address == nullptr && Size != 0)
|
||||
return this->malloc(Size);
|
||||
|
||||
if (Size == 0)
|
||||
{
|
||||
this->free(Address);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// XallocV2_lock;
|
||||
// ...
|
||||
// XallocV2_unlock;
|
||||
|
||||
// TODO: Implement realloc
|
||||
static int once = 0;
|
||||
if (!once++)
|
||||
Xalloc_trace("realloc is stub!");
|
||||
this->free(Address);
|
||||
return this->malloc(Size);
|
||||
}
|
||||
|
||||
V2::V2(void *VirtualBase)
|
||||
{
|
||||
if (VirtualBase == 0x0 && Xalloc_MapPages)
|
||||
{
|
||||
Xalloc_err("VirtualBase is 0x0 and Xalloc_MapPages is true!");
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
|
||||
XallocV2_lock;
|
||||
this->BaseVirtualAddress = Xuintptr_t(VirtualBase);
|
||||
XallocV2_unlock;
|
||||
}
|
||||
|
||||
V2::~V2()
|
||||
{
|
||||
XallocV2_lock;
|
||||
Xalloc_trace("Destructor not implemented yet.");
|
||||
XallocV2_unlock;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user