Multiple page allocation
This commit is contained in:
parent
ba9e0f1bff
commit
9815cc062f
|
@ -1,5 +1,6 @@
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
#include "klibc.h"
|
#include "klibc.h"
|
||||||
|
#include "kthread.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
#define STR_HELPER(x) #x
|
#define STR_HELPER(x) #x
|
||||||
#define STR(x) STR_HELPER(x)
|
#define STR(x) STR_HELPER(x)
|
||||||
|
@ -61,6 +62,8 @@ __attribute__((interrupt)) void pagefault_handler(struct interrupt_frame *frame,
|
||||||
uint32_t faulting_address;
|
uint32_t faulting_address;
|
||||||
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
|
asm volatile("mov %%cr2, %0" : "=r"(faulting_address));
|
||||||
|
|
||||||
|
struct kthread *current = getCurrentThread();
|
||||||
|
printf("page fault while in thread %s\n", current->name);
|
||||||
printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1);
|
printStringDetails("PAGE FAULT", RED, BLACK, 0, VGA_HEIGHT - 1);
|
||||||
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
|
printIntDetails(error_code, RED, BLACK, 11, VGA_HEIGHT - 1);
|
||||||
(void)faulting_address;
|
(void)faulting_address;
|
||||||
|
|
|
@ -76,7 +76,7 @@ int pagingSetup(paddr_t upperKernelAddr)
|
||||||
struct pdbr cr3;
|
struct pdbr cr3;
|
||||||
|
|
||||||
// x86 got 1024 of pde for 4Byte each: 4ko !
|
// x86 got 1024 of pde for 4Byte each: 4ko !
|
||||||
struct pde *pd = (struct pde *)allocPhyPage();
|
struct pde *pd = (struct pde *)allocPhyPage(1);
|
||||||
|
|
||||||
memset(pd, 0, PAGE_SIZE);
|
memset(pd, 0, PAGE_SIZE);
|
||||||
memset(&cr3, 0x0, sizeof(struct pdbr));
|
memset(&cr3, 0x0, sizeof(struct pdbr));
|
||||||
|
@ -93,7 +93,7 @@ int pagingSetup(paddr_t upperKernelAddr)
|
||||||
pt = (struct pte *)(pd[pdEntry].pt_addr << PT_SHIFT);
|
pt = (struct pte *)(pd[pdEntry].pt_addr << PT_SHIFT);
|
||||||
refPhyPage((paddr_t)pt);
|
refPhyPage((paddr_t)pt);
|
||||||
} else {
|
} else {
|
||||||
pt = (struct pte *)allocPhyPage();
|
pt = (struct pte *)allocPhyPage(1);
|
||||||
|
|
||||||
memset(pt, 0, PAGE_SIZE);
|
memset(pt, 0, PAGE_SIZE);
|
||||||
pd[pdEntry].present = 1;
|
pd[pdEntry].present = 1;
|
||||||
|
@ -137,7 +137,7 @@ int pageMap(vaddr_t vaddr, paddr_t paddr, int flags)
|
||||||
struct pte *pt = (struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
|
struct pte *pt = (struct pte *)((PD_MIRROR_PAGE_IDX << PD_SHIFT) + (pdEntry << PT_SHIFT));
|
||||||
|
|
||||||
if (!pd[pdEntry].present) {
|
if (!pd[pdEntry].present) {
|
||||||
paddr_t ptPhy = allocPhyPage();
|
paddr_t ptPhy = allocPhyPage(1);
|
||||||
if (ptPhy == (vaddr_t)NULL)
|
if (ptPhy == (vaddr_t)NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
142
core/alloc.c
142
core/alloc.c
|
@ -3,35 +3,49 @@
|
||||||
#include "alloc.h"
|
#include "alloc.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
|
#include "kernel.h"
|
||||||
#include "klibc.h"
|
#include "klibc.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
#include "paging.h"
|
||||||
|
|
||||||
#define IS_SELF_CONTAINED(desc) ((vaddr_t)((desc)->page) == (vaddr_t)(desc))
|
#define IS_SELF_CONTAINED(desc) ((vaddr_t)((desc)->page) == (vaddr_t)(desc))
|
||||||
// Slab will contains object from sizeof(void *) to PAGE_SIZE/2 by pow2
|
// Slab will contains object from sizeof(void *) to PAGE_SIZE/2 by pow2
|
||||||
#define SLUB_SIZE (PAGE_SHIFT)
|
|
||||||
static struct slabDesc *slub;
|
static struct slabDesc *slub;
|
||||||
|
|
||||||
int allocSlab(struct slabDesc **desc, size_t size, int self_containing);
|
int allocSlab(struct slabDesc **desc, size_t sizeEl, size_t sizeSlab, int self_containing);
|
||||||
int allocSlabEntry(struct slabEntry **desc, size_t size, int selfContained);
|
int allocSlabEntry(struct slabEntry **desc, size_t sizeEl, size_t sizeSlab, int selfContained);
|
||||||
static int formatPage(struct slabEntry *desc, size_t size, int selfContained);
|
static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained);
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
size_t elementSize;
|
||||||
|
size_t slabSize;
|
||||||
|
unsigned char isSelf;
|
||||||
|
} initSlab[] = {{sizeof(struct slabDesc), PAGE_SIZE, 1},
|
||||||
|
{sizeof(struct slabEntry), PAGE_SIZE, 1},
|
||||||
|
{4, PAGE_SIZE, 0},
|
||||||
|
{8, PAGE_SIZE, 0},
|
||||||
|
{16, PAGE_SIZE, 0},
|
||||||
|
{32, PAGE_SIZE, 0},
|
||||||
|
{64, PAGE_SIZE, 0},
|
||||||
|
{128, PAGE_SIZE, 0},
|
||||||
|
{256, 2 * PAGE_SIZE, 0},
|
||||||
|
{1024, 2 * PAGE_SIZE, 0},
|
||||||
|
{2048, 3 * PAGE_SIZE, 0},
|
||||||
|
{4096, 4 * PAGE_SIZE, 0},
|
||||||
|
{8192, 8 * PAGE_SIZE, 0},
|
||||||
|
{16384, 12 * PAGE_SIZE, 0},
|
||||||
|
{0, 0, 0}};
|
||||||
|
|
||||||
int allocSetup(void)
|
int allocSetup(void)
|
||||||
{
|
{
|
||||||
uint start = log2(sizeof(void *));
|
|
||||||
list_init(slub);
|
list_init(slub);
|
||||||
int ret;
|
|
||||||
if ((ret = allocBookSlab(sizeof(struct slabDesc), 1))) {
|
for (uint i = 0; initSlab[i].elementSize != 0; i++) {
|
||||||
pr_devel("Fail to allocBookSlab %d for slabDesc :( \n", ret);
|
int ret;
|
||||||
return ret;
|
if ((ret = allocBookSlab(initSlab[i].elementSize, initSlab[i].slabSize,
|
||||||
}
|
initSlab[i].isSelf))) {
|
||||||
if ((ret = allocBookSlab(sizeof(struct slabEntry), 1))) {
|
|
||||||
pr_devel("Fail to allocBookSlab %d for slabEntry :( \n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
for (uint i = start; i <= SLUB_SIZE; i++) {
|
|
||||||
if ((ret = allocBookSlab(1U << i, 0))) {
|
|
||||||
if (ret == -EEXIST)
|
if (ret == -EEXIST)
|
||||||
continue;
|
continue;
|
||||||
pr_devel("Fail to allocBookSlab %d for %d \n", ret, (1U << i));
|
pr_devel("Fail to allocBookSlab %d for %d \n", ret, (1U << i));
|
||||||
|
@ -41,10 +55,11 @@ int allocSetup(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int allocBookSlab(size_t size, int selfContained)
|
int allocBookSlab(size_t sizeEl, size_t sizeSlab, int selfContained)
|
||||||
{
|
{
|
||||||
pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
|
pr_devel("%s for element of size %d is self %d\n", __func__, sizeEl, selfContained);
|
||||||
struct slabDesc *slab = NULL;
|
struct slabDesc *slab = NULL;
|
||||||
|
struct slabDesc *newSlab = NULL;
|
||||||
int slabIdx;
|
int slabIdx;
|
||||||
int ret;
|
int ret;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -52,38 +67,49 @@ int allocBookSlab(size_t size, int selfContained)
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
list_foreach(slub, slab, slabIdx)
|
list_foreach(slub, slab, slabIdx)
|
||||||
{
|
{
|
||||||
if (slab->size == size) {
|
if (slab->size == sizeEl) {
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
if (slab->size > size) {
|
if (slab->size > sizeEl) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct slabDesc *newSlab;
|
|
||||||
if ((ret = allocSlab(&newSlab, size, selfContained))) {
|
if ((ret = allocSlab(&newSlab, sizeEl, sizeSlab, selfContained))) {
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list_foreach_early_break(slub, slab, slabIdx)) {
|
if (list_foreach_early_break(slub, slab, slabIdx)) {
|
||||||
list_insert_before(slub, slab, newSlab);
|
list_insert_before(slub, slab, newSlab);
|
||||||
} else {
|
} else {
|
||||||
list_add_tail(slub, newSlab);
|
list_add_tail(slub, newSlab);
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int allocSlab(struct slabDesc **desc, size_t size, int selfContained)
|
int allocSlab(struct slabDesc **desc, size_t size, size_t sizeSlab, int selfContained)
|
||||||
{
|
{
|
||||||
// pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
|
uint nbPage, i;
|
||||||
if (size > PAGE_SIZE)
|
|
||||||
|
pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
|
||||||
|
sizeSlab = MAX(sizeSlab, PAGE_SIZE);
|
||||||
|
if (size > sizeSlab) {
|
||||||
|
pr_devel("%s size of element %d are bigger than slab size %d\n", size, sizeSlab);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
paddr_t alloc = allocPhyPage();
|
}
|
||||||
|
|
||||||
|
nbPage = DIV_ROUND_UP(sizeSlab, PAGE_SIZE);
|
||||||
|
paddr_t alloc = allocPhyPage(nbPage);
|
||||||
if (alloc == (paddr_t)NULL)
|
if (alloc == (paddr_t)NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
if (pageMap((vaddr_t)alloc, alloc, PAGING_MEM_WRITE))
|
for (i = 0; i < nbPage; i++) {
|
||||||
return -ENOMEM;
|
if (pageMap((vaddr_t)alloc + i * PAGE_SIZE, alloc + i * PAGE_SIZE, PAGING_MEM_WRITE))
|
||||||
|
goto free_page;
|
||||||
|
}
|
||||||
|
|
||||||
if (selfContained) {
|
if (selfContained) {
|
||||||
*desc = (struct slabDesc *)alloc;
|
*desc = (struct slabDesc *)alloc;
|
||||||
|
@ -96,21 +122,37 @@ int allocSlab(struct slabDesc **desc, size_t size, int selfContained)
|
||||||
list_singleton(slab, slab);
|
list_singleton(slab, slab);
|
||||||
slab->page = (vaddr_t)alloc;
|
slab->page = (vaddr_t)alloc;
|
||||||
slab->full = 0;
|
slab->full = 0;
|
||||||
|
slab->size = sizeSlab;
|
||||||
(*desc)->size = size;
|
(*desc)->size = size;
|
||||||
// pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->slab.freeEl);
|
// pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->slab.freeEl);
|
||||||
return formatPage(&(*desc)->slab, size, selfContained);
|
return formatPage(&(*desc)->slab, size, sizeSlab, selfContained);
|
||||||
|
|
||||||
|
free_page:
|
||||||
|
for (uint j = 0; j < i; j++) {
|
||||||
|
pageUnmap((vaddr_t)alloc + i * PAGE_SIZE);
|
||||||
|
}
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
int allocSlabEntry(struct slabEntry **desc, size_t size, int selfContained)
|
int allocSlabEntry(struct slabEntry **desc, size_t size, size_t sizeSlab, int selfContained)
|
||||||
{
|
{
|
||||||
|
uint nbPage, i;
|
||||||
|
|
||||||
pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
|
pr_devel("%s for size %d is self %d\n", __func__, size, selfContained);
|
||||||
if (size > PAGE_SIZE)
|
sizeSlab = MAX(sizeSlab, PAGE_SIZE);
|
||||||
|
if (size > sizeSlab) {
|
||||||
|
pr_devel("%s size of element %d are bigger than slab size %d\n", size, sizeSlab);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
paddr_t alloc = allocPhyPage();
|
}
|
||||||
|
|
||||||
|
nbPage = DIV_ROUND_UP(sizeSlab, PAGE_SIZE);
|
||||||
|
paddr_t alloc = allocPhyPage(nbPage);
|
||||||
if (alloc == (paddr_t)NULL)
|
if (alloc == (paddr_t)NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
if (pageMap((vaddr_t)alloc, alloc, PAGING_MEM_WRITE))
|
for (i = 0; i < nbPage; i++) {
|
||||||
return -ENOMEM;
|
if (pageMap((vaddr_t)alloc + i * PAGE_SIZE, alloc + i * PAGE_SIZE, PAGING_MEM_WRITE))
|
||||||
|
goto free_page;
|
||||||
|
}
|
||||||
|
|
||||||
if (selfContained) {
|
if (selfContained) {
|
||||||
*desc = (struct slabEntry *)alloc;
|
*desc = (struct slabEntry *)alloc;
|
||||||
|
@ -122,16 +164,23 @@ int allocSlabEntry(struct slabEntry **desc, size_t size, int selfContained)
|
||||||
list_singleton(*desc, *desc);
|
list_singleton(*desc, *desc);
|
||||||
(*desc)->page = (vaddr_t)alloc;
|
(*desc)->page = (vaddr_t)alloc;
|
||||||
(*desc)->full = 0;
|
(*desc)->full = 0;
|
||||||
|
(*desc)->size = sizeSlab;
|
||||||
// pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->freeEl);
|
// pr_devel("got page %d for size %d first %d", alloc, size, (*desc)->freeEl);
|
||||||
return formatPage((*desc), size, selfContained);
|
return formatPage((*desc), size, sizeSlab, selfContained);
|
||||||
|
|
||||||
|
free_page:
|
||||||
|
for (uint j = 0; j < i; j++) {
|
||||||
|
pageUnmap((vaddr_t)alloc + i * PAGE_SIZE);
|
||||||
|
}
|
||||||
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int formatPage(struct slabEntry *desc, size_t size, int selfContained)
|
static int formatPage(struct slabEntry *desc, size_t size, size_t sizeSlab, int selfContained)
|
||||||
{
|
{
|
||||||
char *cur = desc->freeEl;
|
char *cur = desc->freeEl;
|
||||||
ulong nbEl = PAGE_SIZE / size - 1;
|
ulong nbEl = sizeSlab / size - 1;
|
||||||
if (selfContained)
|
if (selfContained)
|
||||||
nbEl = (PAGE_SIZE - sizeof(struct slabDesc)) / size - 1;
|
nbEl = (sizeSlab - sizeof(struct slabDesc)) / size - 1;
|
||||||
ulong i;
|
ulong i;
|
||||||
for (i = 0; i < nbEl; i++) {
|
for (i = 0; i < nbEl; i++) {
|
||||||
*((vaddr_t *)cur) = (vaddr_t)cur + size;
|
*((vaddr_t *)cur) = (vaddr_t)cur + size;
|
||||||
|
@ -157,16 +206,12 @@ static void *allocFromSlab(struct slabEntry *slab)
|
||||||
void *malloc(size_t size)
|
void *malloc(size_t size)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
void *ret;
|
|
||||||
|
|
||||||
if (size > (1U << SLUB_SIZE)) {
|
|
||||||
printf("implement malloc for big size\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
struct slabDesc *slab;
|
struct slabDesc *slab;
|
||||||
uint slubIdx;
|
uint slubIdx;
|
||||||
|
void *ret;
|
||||||
|
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
|
|
||||||
list_foreach(slub, slab, slubIdx)
|
list_foreach(slub, slab, slubIdx)
|
||||||
{
|
{
|
||||||
if (size <= slab->size)
|
if (size <= slab->size)
|
||||||
|
@ -188,9 +233,10 @@ void *malloc(size_t size)
|
||||||
// No room found
|
// No room found
|
||||||
struct slabEntry *newSlabEntry;
|
struct slabEntry *newSlabEntry;
|
||||||
struct slabEntry *slabList = &slab->slab;
|
struct slabEntry *slabList = &slab->slab;
|
||||||
|
size_t slabSize = MAX(PAGE_SIZE, size);
|
||||||
int retSlab;
|
int retSlab;
|
||||||
if ((retSlab =
|
if ((retSlab = allocSlabEntry(&newSlabEntry, slab->size, slabSize,
|
||||||
allocSlabEntry(&newSlabEntry, slab->size, IS_SELF_CONTAINED(&slab->slab)))) {
|
IS_SELF_CONTAINED(&slab->slab)))) {
|
||||||
pr_devel("Fail to allocSlabEntry %d\n", retSlab);
|
pr_devel("Fail to allocSlabEntry %d\n", retSlab);
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -209,7 +255,7 @@ int freeFromSlab(void *ptr, struct slabEntry *slab)
|
||||||
list_foreach(slab, slabEntry, slabIdx)
|
list_foreach(slab, slabEntry, slabIdx)
|
||||||
{
|
{
|
||||||
if ((slabEntry->page <= (vaddr_t)ptr) &&
|
if ((slabEntry->page <= (vaddr_t)ptr) &&
|
||||||
((vaddr_t)ptr < (slabEntry->page + PAGE_SIZE))) {
|
((vaddr_t)ptr < (slabEntry->page + slabEntry->size))) {
|
||||||
// pr_devel("free place! was %d is now %d\n", slabEntry->freeEl, ptr);
|
// pr_devel("free place! was %d is now %d\n", slabEntry->freeEl, ptr);
|
||||||
if (slabEntry->full) {
|
if (slabEntry->full) {
|
||||||
*((vaddr_t *)ptr) = (vaddr_t)NULL;
|
*((vaddr_t *)ptr) = (vaddr_t)NULL;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
struct slabEntry {
|
struct slabEntry {
|
||||||
vaddr_t page;
|
vaddr_t page;
|
||||||
|
size_t size;
|
||||||
void *freeEl;
|
void *freeEl;
|
||||||
char full;
|
char full;
|
||||||
struct slabEntry *next;
|
struct slabEntry *next;
|
||||||
|
@ -17,7 +18,7 @@ struct slabDesc {
|
||||||
struct slabDesc *prev;
|
struct slabDesc *prev;
|
||||||
};
|
};
|
||||||
int allocSetup(void);
|
int allocSetup(void);
|
||||||
int allocBookSlab(size_t size, int selfContained);
|
int allocBookSlab(size_t size, size_t sizeSlab, int selfContained);
|
||||||
|
|
||||||
void *malloc(size_t size);
|
void *malloc(size_t size);
|
||||||
void free(void *ptr);
|
void free(void *ptr);
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
|
||||||
|
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a)-1)
|
||||||
|
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||||
|
|
||||||
|
/* @a is a power of 2 value */
|
||||||
|
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
|
||||||
|
#define ALIGN_DOWN(x, a) __ALIGN_KERNEL((x) - ((a)-1), (a))
|
||||||
|
#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
|
||||||
|
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
|
||||||
|
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a)-1)) == 0)
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This looks more complex than it should be. But we need to
|
||||||
|
* get the type for the ~ right in round_down (it needs to be
|
||||||
|
* as wide as the result!), and we want to evaluate the macro
|
||||||
|
* arguments just once each.
|
||||||
|
*/
|
||||||
|
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
|
||||||
|
/**
|
||||||
|
* round_up - round up to next specified power of 2
|
||||||
|
* @x: the value to round
|
||||||
|
* @y: multiple to round up to (must be a power of 2)
|
||||||
|
*
|
||||||
|
* Rounds @x up to next multiple of @y (which must be a power of 2).
|
||||||
|
* To perform arbitrary rounding up, use roundup() below.
|
||||||
|
*/
|
||||||
|
#define round_up(x, y) ((((x)-1) | __round_mask(x, y)) + 1)
|
||||||
|
/**
|
||||||
|
* round_down - round down to next specified power of 2
|
||||||
|
* @x: the value to round
|
||||||
|
* @y: multiple to round down to (must be a power of 2)
|
||||||
|
*
|
||||||
|
* Rounds @x down to next multiple of @y (which must be a power of 2).
|
||||||
|
* To perform arbitrary rounding down, use rounddown() below.
|
||||||
|
*/
|
||||||
|
#define round_down(x, y) ((x) & ~__round_mask(x, y))
|
||||||
|
|
||||||
|
#define typeof_member(T, m) typeof(((T *)0)->m)
|
||||||
|
|
||||||
|
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
|
||||||
|
/**
|
||||||
|
* roundup - round up to the next specified multiple
|
||||||
|
* @x: the value to up
|
||||||
|
* @y: multiple to round up to
|
||||||
|
*
|
||||||
|
* Rounds @x up to next multiple of @y. If @y will always be a power
|
||||||
|
* of 2, consider using the faster round_up().
|
||||||
|
*/
|
||||||
|
#define roundup(x, y) \
|
||||||
|
({ \
|
||||||
|
typeof(y) __y = y; \
|
||||||
|
(((x) + (__y - 1)) / __y) * __y; \
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* rounddown - round down to next specified multiple
|
||||||
|
* @x: the value to round
|
||||||
|
* @y: multiple to round down to
|
||||||
|
*
|
||||||
|
* Rounds @x down to next multiple of @y. If @y will always be a power
|
||||||
|
* of 2, consider using the faster round_down().
|
||||||
|
*/
|
||||||
|
#define rounddown(x, y) \
|
||||||
|
({ \
|
||||||
|
typeof(x) __x = (x); \
|
||||||
|
__x - (__x % (y)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
@ -35,6 +35,10 @@ void printf(const char *format, ...);
|
||||||
0; \
|
0; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#ifndef pr_fmt
|
||||||
|
#define pr_fmt(fmt) fmt
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define pr_devel(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
|
#define pr_devel(fmt, ...) printf(pr_fmt(fmt), ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -50,7 +50,7 @@ struct kthread *kthreadCreate(const char *name, cpu_kstate_function_arg1_t func,
|
||||||
|
|
||||||
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
|
thread->stackAddr = (vaddr_t)malloc(KTHREAD_DEFAULT_STACK_SIZE);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("Alloc stask at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
|
printf("Alloc stack at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
|
||||||
#endif
|
#endif
|
||||||
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
|
thread->stackSize = KTHREAD_DEFAULT_STACK_SIZE;
|
||||||
|
|
||||||
|
@ -85,6 +85,9 @@ void kthreadDelete(struct kthread *thread)
|
||||||
disable_IRQs(flags);
|
disable_IRQs(flags);
|
||||||
list_delete(currentThread, thread);
|
list_delete(currentThread, thread);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("Free stack at 0x%x struct at 0x%x\n", thread->stackAddr, thread);
|
||||||
|
#endif
|
||||||
free((void *)thread->stackAddr);
|
free((void *)thread->stackAddr);
|
||||||
free((void *)thread);
|
free((void *)thread);
|
||||||
restore_IRQs(flags);
|
restore_IRQs(flags);
|
||||||
|
|
58
core/mem.c
58
core/mem.c
|
@ -1,4 +1,5 @@
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
#include "kernel.h"
|
||||||
#include "klibc.h"
|
#include "klibc.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -50,16 +51,59 @@ struct mem_desc *addr2memDesc(paddr_t addr)
|
||||||
return page_desc + idx;
|
return page_desc + idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
paddr_t allocPhyPage(void)
|
struct mem_desc *memFindConsecutiveFreePage(uint nbPage)
|
||||||
{
|
{
|
||||||
|
struct mem_desc *mem, *head;
|
||||||
|
uint memIdx, count;
|
||||||
|
|
||||||
if (list_is_empty(free_page)) {
|
if (list_is_empty(free_page)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
count = 1;
|
||||||
|
memIdx = 0;
|
||||||
|
head = free_page;
|
||||||
|
mem = free_page;
|
||||||
|
|
||||||
|
while (count < nbPage && (!memIdx || mem != free_page)) {
|
||||||
|
memIdx++;
|
||||||
|
mem = mem->next;
|
||||||
|
if (mem->phy_addr == head->phy_addr + count * PAGE_SIZE) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
count = 1;
|
||||||
|
head = mem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < nbPage) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
paddr_t allocPhyPage(uint nbPage)
|
||||||
|
{
|
||||||
|
struct mem_desc *mem, *head, *next;
|
||||||
|
uint count;
|
||||||
|
|
||||||
|
head = memFindConsecutiveFreePage(nbPage);
|
||||||
|
|
||||||
|
if (head == NULL) {
|
||||||
|
pr_devel("Cannot find %d consecutive page\n", nbPage);
|
||||||
return (unsigned long)NULL;
|
return (unsigned long)NULL;
|
||||||
}
|
}
|
||||||
struct mem_desc *mem = list_pop_head(free_page);
|
|
||||||
mem->ref = 1;
|
mem = head;
|
||||||
list_add_tail(used_page, mem);
|
next = head->next;
|
||||||
allocatedPage++;
|
for (count = 0; count < nbPage; count++) {
|
||||||
return mem->phy_addr;
|
list_delete(free_page, mem);
|
||||||
|
mem->ref = 1;
|
||||||
|
list_add_tail(used_page, mem);
|
||||||
|
mem = next;
|
||||||
|
next = mem->next;
|
||||||
|
}
|
||||||
|
allocatedPage += nbPage;
|
||||||
|
return head->phy_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unrefPhyPage(paddr_t addr)
|
int unrefPhyPage(paddr_t addr)
|
||||||
|
@ -72,7 +116,7 @@ int unrefPhyPage(paddr_t addr)
|
||||||
if (mem->ref == 0) {
|
if (mem->ref == 0) {
|
||||||
allocatedPage--;
|
allocatedPage--;
|
||||||
list_delete(used_page, mem);
|
list_delete(used_page, mem);
|
||||||
list_add_tail(free_page, mem);
|
list_add_tail(free_page, mem); // TODO find the right place to keep free_page sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mem->ref;
|
return mem->ref;
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct mem_desc {
|
||||||
};
|
};
|
||||||
|
|
||||||
int memSetup(paddr_t upperMem, paddr_t *lastUsed);
|
int memSetup(paddr_t upperMem, paddr_t *lastUsed);
|
||||||
paddr_t allocPhyPage(void);
|
paddr_t allocPhyPage(uint nbPage);
|
||||||
int unrefPhyPage(paddr_t addr);
|
int unrefPhyPage(paddr_t addr);
|
||||||
int refPhyPage(paddr_t addr);
|
int refPhyPage(paddr_t addr);
|
||||||
unsigned long getNbAllocatedPage(void);
|
unsigned long getNbAllocatedPage(void);
|
||||||
|
|
12
core/types.h
12
core/types.h
|
@ -28,18 +28,6 @@
|
||||||
#define S64_MAX ((s64)(U64_MAX >> 1))
|
#define S64_MAX ((s64)(U64_MAX >> 1))
|
||||||
#define S64_MIN ((s64)(-S64_MAX - 1))
|
#define S64_MIN ((s64)(-S64_MAX - 1))
|
||||||
|
|
||||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a)-1)
|
|
||||||
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
|
||||||
|
|
||||||
/* @a is a power of 2 value */
|
|
||||||
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
|
|
||||||
#define ALIGN_DOWN(x, a) __ALIGN_KERNEL((x) - ((a)-1), (a))
|
|
||||||
#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
|
|
||||||
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
|
|
||||||
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a)-1)) == 0)
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
|
|
||||||
|
|
||||||
// Virtual address
|
// Virtual address
|
||||||
typedef unsigned long vaddr_t;
|
typedef unsigned long vaddr_t;
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
#define VGA_WIDTH 80
|
#define VGA_WIDTH 80
|
||||||
#define VGA_HEIGHT 25
|
#define VGA_HEIGHT 25
|
||||||
|
|
||||||
#ifndef pr_fmt
|
|
||||||
#define pr_fmt(fmt) fmt
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int VGASetup(uint bgColor, uint color);
|
int VGASetup(uint bgColor, uint color);
|
||||||
void VGAputc(const char str);
|
void VGAputc(const char str);
|
||||||
void clearScreen(uint bgColor);
|
void clearScreen(uint bgColor);
|
||||||
|
|
|
@ -21,7 +21,7 @@ void testPhymem(void)
|
||||||
int allocCount = 0;
|
int allocCount = 0;
|
||||||
int freeCount = 0;
|
int freeCount = 0;
|
||||||
|
|
||||||
while ((page = (struct mem_desc *)allocPhyPage()) != NULL) {
|
while ((page = (struct mem_desc *)allocPhyPage(1)) != NULL) {
|
||||||
page->phy_addr = allocCount;
|
page->phy_addr = allocCount;
|
||||||
allocCount++;
|
allocCount++;
|
||||||
list_add_tail(allocated_page_list, page);
|
list_add_tail(allocated_page_list, page);
|
||||||
|
@ -35,7 +35,7 @@ void testPhymem(void)
|
||||||
}
|
}
|
||||||
printf("%d pages freed\n", freeCount);
|
printf("%d pages freed\n", freeCount);
|
||||||
|
|
||||||
assertmsg((page = (struct mem_desc *)allocPhyPage()) != NULL, "Cannot allocate memory\n");
|
assertmsg((page = (struct mem_desc *)allocPhyPage(1)) != NULL, "Cannot allocate memory\n");
|
||||||
unrefPhyPage((ulong)page);
|
unrefPhyPage((ulong)page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ static void testPaging(void)
|
||||||
int allocCount = 0;
|
int allocCount = 0;
|
||||||
int freeCount = 0;
|
int freeCount = 0;
|
||||||
|
|
||||||
while ((page = (struct mem_desc *)allocPhyPage()) != NULL) {
|
while ((page = (struct mem_desc *)allocPhyPage(1)) != NULL) {
|
||||||
assertmsg(pageMap((vaddr_t)page, (paddr_t)page, PAGING_MEM_WRITE) == 0,
|
assertmsg(pageMap((vaddr_t)page, (paddr_t)page, PAGING_MEM_WRITE) == 0,
|
||||||
"Fail to map page %d\n", allocCount);
|
"Fail to map page %d\n", allocCount);
|
||||||
memset(page, allocCount, PAGE_SIZE);
|
memset(page, allocCount, PAGE_SIZE);
|
||||||
|
@ -121,7 +121,7 @@ static void testPaging(void)
|
||||||
}
|
}
|
||||||
printf("%d pages freed\n", freeCount);
|
printf("%d pages freed\n", freeCount);
|
||||||
|
|
||||||
assertmsg((page = (struct mem_desc *)allocPhyPage()) != NULL, "Cannot allocate memory\n");
|
assertmsg((page = (struct mem_desc *)allocPhyPage(1)) != NULL, "Cannot allocate memory\n");
|
||||||
unrefPhyPage((ulong)page);
|
unrefPhyPage((ulong)page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue