stos: pool: Add actual allocation groundwork
Still lots to do Signed-off-by: Chloe M. <chloe@mensia.org>
This commit is contained in:
+129
-1
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <ex/pool.h>
|
#include <ex/pool.h>
|
||||||
#include <ex/trace.h>
|
#include <ex/trace.h>
|
||||||
|
#include <hal/kpcr.h>
|
||||||
#include <mm/vmm.h>
|
#include <mm/vmm.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -17,6 +18,11 @@
|
|||||||
/* Globals */
|
/* Globals */
|
||||||
static USIZE PoolCount = 0;
|
static USIZE PoolCount = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize a pool block
|
||||||
|
*
|
||||||
|
* @Block: Pool block to initialize
|
||||||
|
*/
|
||||||
static ST_STATUS
|
static ST_STATUS
|
||||||
PoolInitBlock(MEMORY_BLOCK *Block)
|
PoolInitBlock(MEMORY_BLOCK *Block)
|
||||||
{
|
{
|
||||||
@@ -35,6 +41,126 @@ PoolInitBlock(MEMORY_BLOCK *Block)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internally used by AllocatePoolWithTag()
|
||||||
|
*
|
||||||
|
* TODO: Handle running out of pages
|
||||||
|
*/
|
||||||
|
static VOID *
|
||||||
|
AllocateFromBlock(UCHAR BlockIndex, MEMORY_BLOCK *Block, USIZE Count)
|
||||||
|
{
|
||||||
|
USIZE Gran, Idx;
|
||||||
|
USIZE BitsNeeded, BitsFound = 0;
|
||||||
|
SSIZE BitBase = -1;
|
||||||
|
MEMORY_PAGE *Page;
|
||||||
|
|
||||||
|
if (Block == NULL || Count == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gran = LEVEL_GRAN(BlockIndex);
|
||||||
|
BitsNeeded = Count / Gran;
|
||||||
|
Page = Block->FirstPage; /* TODO: Handle many */
|
||||||
|
|
||||||
|
for (Idx = 0; Idx < sizeof(Page->Bitmap) * 8; ++Idx) {
|
||||||
|
if (!TESTBIT(&Page->Bitmap, Idx) && BitsFound < BitsNeeded) {
|
||||||
|
if (BitBase < 0)
|
||||||
|
BitBase = Idx;
|
||||||
|
|
||||||
|
++BitsFound;
|
||||||
|
} else if (TESTBIT(&Page->Bitmap, Idx)) {
|
||||||
|
BitBase = -1;
|
||||||
|
BitsFound = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BitsFound >= BitsNeeded) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Idx = BitBase; Idx < BitBase + BitsNeeded; ++Idx) {
|
||||||
|
SETBIT(&Page->Bitmap, Idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (BitsFound >= BitsNeeded)
|
||||||
|
? PTR_OFFSET(Page, sizeof(MEMORY_PAGE) + (BitBase * Gran))
|
||||||
|
: NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internally used by ExAllocatePoolWithTag()
|
||||||
|
*/
|
||||||
|
static VOID *
|
||||||
|
AllocatePoolWithTag(MEMORY_POOL *Pool, POOL_TYPE Type, USIZE ByteCount, ULONG Tag)
|
||||||
|
{
|
||||||
|
USIZE TmpCount;
|
||||||
|
UCHAR BlockIndex = 0;
|
||||||
|
MEMORY_BLOCK *Block;
|
||||||
|
|
||||||
|
if (Pool == NULL || ByteCount == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtain the block index with the formula:
|
||||||
|
*
|
||||||
|
* i = (log2(count) - POOL_MIN_LOG2) - 1
|
||||||
|
*/
|
||||||
|
ByteCount = ALIGN_UP(ByteCount, LEVEL_GRAN(0));
|
||||||
|
TmpCount = ByteCount;
|
||||||
|
while (TmpCount != 0) {
|
||||||
|
++BlockIndex;
|
||||||
|
TmpCount >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockIndex -= (POOL_MIN_LOG2 + 1);
|
||||||
|
BlockIndex %= LEVEL_COUNT;
|
||||||
|
Block = &Pool->BlockLevels[BlockIndex];
|
||||||
|
return AllocateFromBlock(BlockIndex, Block, ByteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Handle tag assignment and prepend a pool header
|
||||||
|
*/
|
||||||
|
VOID *
|
||||||
|
ExAllocatePoolWithTag(POOL_TYPE Type, USIZE ByteCount, ULONG Tag)
|
||||||
|
{
|
||||||
|
KPCR *ThisCore;
|
||||||
|
MEMORY_POOL *AllocPool;
|
||||||
|
|
||||||
|
if (ByteCount == 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that the pool type is valid */
|
||||||
|
switch (Type) {
|
||||||
|
case POOL_NON_PAGED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DTRACE("got bad pool type in allocation\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThisCore = HalKpcrCurrent();
|
||||||
|
AllocPool = &ThisCore->AllocPool;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the byte count is aligned by the minimum granularity
|
||||||
|
* that we can allocate. Furthermore, ensure that it does not exceed
|
||||||
|
* the size of a single page.
|
||||||
|
*/
|
||||||
|
ByteCount = ALIGN_UP(ByteCount, LEVEL_GRAN(0));
|
||||||
|
if (ByteCount >= PAGESIZE) {
|
||||||
|
DTRACE(
|
||||||
|
"allocation in pool #%d exceeds page size\n",
|
||||||
|
AllocPool->Id
|
||||||
|
);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AllocatePoolWithTag(AllocPool, Type, ByteCount, Tag);
|
||||||
|
}
|
||||||
|
|
||||||
ST_STATUS
|
ST_STATUS
|
||||||
ExPoolInit(MEMORY_POOL *Pool)
|
ExPoolInit(MEMORY_POOL *Pool)
|
||||||
{
|
{
|
||||||
@@ -46,8 +172,10 @@ ExPoolInit(MEMORY_POOL *Pool)
|
|||||||
return STATUS_INVALID_PARAM;
|
return STATUS_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pool->Id = PoolCount;
|
||||||
|
DTRACE("bringing up pool #%d\n", Pool->Id);
|
||||||
|
|
||||||
/* Initialize the pools */
|
/* Initialize the pools */
|
||||||
DTRACE("bringing up pool #%d\n", PoolCount);
|
|
||||||
for (LevelIdx = 0; LevelIdx < LEVEL_COUNT; ++LevelIdx) {
|
for (LevelIdx = 0; LevelIdx < LEVEL_COUNT; ++LevelIdx) {
|
||||||
Block = &Pool->BlockLevels[LevelIdx];
|
Block = &Pool->BlockLevels[LevelIdx];
|
||||||
Status = PoolInitBlock(Block);
|
Status = PoolInitBlock(Block);
|
||||||
|
|||||||
+30
-1
@@ -13,9 +13,12 @@
|
|||||||
#include <stapi/status.h>
|
#include <stapi/status.h>
|
||||||
#include <stdef.h>
|
#include <stdef.h>
|
||||||
|
|
||||||
|
/* Minimum log2 allocation size */
|
||||||
|
#define POOL_MIN_LOG2 3
|
||||||
|
|
||||||
/* Compute the granularity of a specific level */
|
/* Compute the granularity of a specific level */
|
||||||
#define LEVEL_GRAN(LEVEL) \
|
#define LEVEL_GRAN(LEVEL) \
|
||||||
(1 << (3 + (LEVEL)))
|
(1 << (POOL_MIN_LOG2 + (LEVEL)))
|
||||||
|
|
||||||
/* Maximum levels per pool */
|
/* Maximum levels per pool */
|
||||||
#define LEVEL_COUNT 8
|
#define LEVEL_COUNT 8
|
||||||
@@ -28,6 +31,15 @@
|
|||||||
#define POOL_REAL_PAGESZ \
|
#define POOL_REAL_PAGESZ \
|
||||||
(PAGESIZE - sizeof(MEMORY_PAGE))
|
(PAGESIZE - sizeof(MEMORY_PAGE))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Valid pool types
|
||||||
|
*
|
||||||
|
* @POOL_NON_PAGED: Not pagable to disk
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
POOL_NON_PAGED
|
||||||
|
} POOL_TYPE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Page data structure used internally to link together page
|
* Page data structure used internally to link together page
|
||||||
* lists
|
* lists
|
||||||
@@ -58,9 +70,11 @@ typedef struct {
|
|||||||
* A memory pool holds blocks of varying granularities
|
* A memory pool holds blocks of varying granularities
|
||||||
*
|
*
|
||||||
* @BlockLevels: Block levels [granularity : GRAN(level)]
|
* @BlockLevels: Block levels [granularity : GRAN(level)]
|
||||||
|
* @Id: Pool ID
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MEMORY_BLOCK BlockLevels[LEVEL_COUNT];
|
MEMORY_BLOCK BlockLevels[LEVEL_COUNT];
|
||||||
|
USIZE Id;
|
||||||
} MEMORY_POOL;
|
} MEMORY_POOL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -70,4 +84,19 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
ST_STATUS ExPoolInit(MEMORY_POOL *Pool);
|
ST_STATUS ExPoolInit(MEMORY_POOL *Pool);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a tagged pool
|
||||||
|
*
|
||||||
|
* @Type: Pool type
|
||||||
|
* @ByteCount: Number of bytes to allocate
|
||||||
|
* @Tag: Tag to assign to pool
|
||||||
|
*
|
||||||
|
* Returns the memory base on success, otherwise
|
||||||
|
* NULL on failure.
|
||||||
|
*/
|
||||||
|
VOID *ExAllocatePoolWithTag(
|
||||||
|
POOL_TYPE Type, USIZE ByteCount,
|
||||||
|
ULONG Tag
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* !_EX_POOL_H_ */
|
#endif /* !_EX_POOL_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user