metal-cos/sys/kern/palloc.c
2014-07-06 14:30:09 -07:00

81 lines
1.5 KiB
C

/*
* Copyright (c) 2013-2014 Stanford University
* All rights reserved.
*/
#include <stdarg.h>
#include <stdint.h>
#include <cdefs.h>
#include <kassert.h>
#include <kmem.h>
#include <queue.h>
#include "../amd64/amd64.h"
/* 'FREEPAGE' */
#define FREEPAGE_MAGIC_FREE 0x4652454550414745ULL
/* 'ALLOCATE' */
#define FREEPAGE_MAGIC_INUSE 0x414c4c4f43415445ULL
typedef struct FreePage
{
uint64_t magic;
LIST_ENTRY(FreePage) entries;
} FreePage;
LIST_HEAD(FreeListHead, FreePage) freeList;
void
PAlloc_Init()
{
LIST_INIT(&freeList);
}
void
PAlloc_AddRegion(uintptr_t start, uintptr_t len)
{
uintptr_t i;
FreePage *pg;
if ((start % PGSIZE) != 0)
Panic("Region start is not page aligned!");
if ((len % PGSIZE) != 0)
Panic("Region length is not page aligned!");
for (i = 0; i < len; i += PGSIZE)
{
pg = (void *)(start + i);
pg->magic = FREEPAGE_MAGIC_FREE;
LIST_INSERT_HEAD(&freeList, pg, entries);
}
}
void *
PAlloc_AllocPage()
{
FreePage *pg = LIST_FIRST(&freeList);
LIST_REMOVE(pg, entries);
ASSERT(pg->magic == FREEPAGE_MAGIC_FREE);
pg->magic = FREEPAGE_MAGIC_INUSE;
//kprintf("PAlloc_AllocPage: %08llx\n", pg);
return (void *)pg;
}
void
PAlloc_FreePage(void *region)
{
FreePage *pg = (FreePage *)region;
LIST_INSERT_HEAD(&freeList, pg, entries);
#ifndef NDEBUG
// Application can write this magic, but for
// debug builds we can use this as a double free check.
ASSERT(pg->magic != FREEPAGE_MAGIC_FREE);
#endif
pg->magic = FREEPAGE_MAGIC_FREE;
}