wip: frame_allocator working pretty good (?)
core: remove physical allocatory
This commit is contained in:
parent
e8fd6c55eb
commit
3315d85e0c
@ -21,9 +21,25 @@
|
|||||||
#define GET_PAGE_ADDR(pd_index, pt_index) \
|
#define GET_PAGE_ADDR(pd_index, pt_index) \
|
||||||
((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * 4096)
|
((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * 4096)
|
||||||
|
|
||||||
|
#define GET_FRAME(frame_table, i) (frame_table[i / 8] & (1 << (i % 8)))
|
||||||
|
#define SET_FRAME(frame_table, i, used) \
|
||||||
|
do { \
|
||||||
|
if (used) \
|
||||||
|
frame_table[i / 8] |= (1 << (i % 8)); \
|
||||||
|
else \
|
||||||
|
frame_table[i / 8] &= ~(1 << (i % 8)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* len is the total size of the zone (ratio starnakin)
|
||||||
|
* size is the remaining usable size after allocating
|
||||||
|
* the struct for the linked list
|
||||||
|
*/
|
||||||
struct frame_zone {
|
struct frame_zone {
|
||||||
void *addr;
|
void *addr;
|
||||||
|
uint32_t first_free_frame;
|
||||||
uint32_t *frame_table;
|
uint32_t *frame_table;
|
||||||
|
uint32_t len;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t remaining_frames;
|
uint32_t remaining_frames;
|
||||||
struct frame_zone *next;
|
struct frame_zone *next;
|
||||||
@ -40,8 +56,8 @@ extern struct frame_zone *head;
|
|||||||
|
|
||||||
uint32_t *virt_to_phys(uint32_t *virt_addr);
|
uint32_t *virt_to_phys(uint32_t *virt_addr);
|
||||||
void init_memory(multiboot_info_t *mbd, uint32_t magic);
|
void init_memory(multiboot_info_t *mbd, uint32_t magic);
|
||||||
void *alloc_frames(size_t size);
|
void *alloc_frame(void);
|
||||||
int free_frames(void *frame_ptr, size_t size);
|
int free_frame(void *frame_ptr);
|
||||||
void *alloc_pages(size_t size);
|
void *alloc_pages(size_t size);
|
||||||
int free_pages(void *page_ptr, size_t size);
|
int free_pages(void *page_ptr, size_t size);
|
||||||
void init_page_table(uint32_t page_table[1024], uint16_t start);
|
void init_page_table(uint32_t page_table[1024], uint16_t start);
|
||||||
|
@ -66,9 +66,9 @@ void kernel_main(multiboot_info_t *mbd, uint32_t magic)
|
|||||||
"I see no way to confuse an array of 256 seg:off pairs with a "
|
"I see no way to confuse an array of 256 seg:off pairs with a "
|
||||||
"complex 8*unknown quantity -byte descriptor table. -- Troy "
|
"complex 8*unknown quantity -byte descriptor table. -- Troy "
|
||||||
"Martin 03:50, 22 March 2009 (UTC)\n");
|
"Martin 03:50, 22 March 2009 (UTC)\n");
|
||||||
alloc_frames(1);
|
/* alloc_frame(); */
|
||||||
/* vmalloc(10); */
|
/* vmalloc(10); */
|
||||||
/* while (vmalloc(10)) */
|
while (vmalloc(10))
|
||||||
/* ; */
|
;
|
||||||
shell_init();
|
shell_init();
|
||||||
}
|
}
|
||||||
|
@ -8,28 +8,36 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
void *alloc_frames(size_t size)
|
void *alloc_frame(void)
|
||||||
{
|
{
|
||||||
const uint32_t nb_frames = CEIL(size, PAGE_SIZE);
|
struct frame_zone *it = head;
|
||||||
for (uint32_t i = 0; i < mmap_length; i++) {
|
while (it && !it->remaining_frames)
|
||||||
multiboot_memory_map_t *mmmt =
|
it = it->next;
|
||||||
(multiboot_memory_map_t *)mmap_addr + i;
|
if (it->remaining_frames == 0) {
|
||||||
if (mmmt->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
kprintf(KERN_CRIT "No memory zone available (ratio)\n");
|
||||||
kprintf("type: %d, addr: %p, len: %u, size: %u, \n",
|
|
||||||
mmmt->type, mmmt->addr, mmmt->len, mmmt->size);
|
|
||||||
}
|
|
||||||
PRINT_PTR(mmmt);
|
|
||||||
}
|
|
||||||
PRINT_PTR(head);
|
|
||||||
PRINT_PTR(head->addr);
|
|
||||||
PRINT_PTR(head->frame_table);
|
|
||||||
PRINT_UINT(head->size);
|
|
||||||
PRINT_UINT(head->remaining_frames);
|
|
||||||
PRINT_PTR(head->next);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int free_frames(void *frame_ptr, size_t size)
|
size_t i = it->first_free_frame;
|
||||||
|
for (; GET_FRAME(it->frame_table, i); i++)
|
||||||
|
;
|
||||||
|
it->first_free_frame++;
|
||||||
|
it->remaining_frames--;
|
||||||
|
SET_FRAME(it->frame_table, i, 1);
|
||||||
|
return it->addr + i * PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int free_frame(void *frame_ptr)
|
||||||
{
|
{
|
||||||
|
struct frame_zone *it = head;
|
||||||
|
while (it && (frame_ptr < it->addr || frame_ptr >= it->addr + it->len))
|
||||||
|
it = it->next;
|
||||||
|
|
||||||
|
uint32_t index =
|
||||||
|
(frame_ptr + (it->len - it->size) - it->addr) / PAGE_SIZE;
|
||||||
|
SET_FRAME(it->frame_table, index, 0);
|
||||||
|
if (it->first_free_frame > index)
|
||||||
|
it->first_free_frame = index;
|
||||||
|
it->remaining_frames++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,11 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
|
|||||||
init_page_table(frame_zones_page_table, 0);
|
init_page_table(frame_zones_page_table, 0);
|
||||||
page_directory[1022] =
|
page_directory[1022] =
|
||||||
((uint32_t)frame_zones_page_table - HEAP_END) | 0x03;
|
((uint32_t)frame_zones_page_table - HEAP_END) | 0x03;
|
||||||
frame_zones_page_table[index++] =
|
frame_zones_page_table[index] =
|
||||||
((uint32_t)zone & PAGE_MASK) | INIT_FLAGS;
|
((uint32_t)zone & PAGE_MASK) | INIT_FLAGS;
|
||||||
|
|
||||||
struct frame_zone *current =
|
struct frame_zone *current =
|
||||||
(struct frame_zone *)GET_PAGE_ADDR(1022, 0);
|
(struct frame_zone *)GET_PAGE_ADDR(1022, index++);
|
||||||
memset(current, 0, sizeof(struct frame_zone));
|
memset(current, 0, sizeof(struct frame_zone));
|
||||||
current->addr = (void *)mmmt->addr;
|
current->addr = (void *)mmmt->addr;
|
||||||
current->frame_table = (uint32_t *)current + sizeof(struct frame_zone);
|
current->frame_table = (uint32_t *)current + sizeof(struct frame_zone);
|
||||||
@ -68,16 +69,18 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
|
|||||||
frame_zones_page_table[index] =
|
frame_zones_page_table[index] =
|
||||||
((uint32_t)zone + PAGE_SIZE & PAGE_MASK) | INIT_FLAGS;
|
((uint32_t)zone + PAGE_SIZE & PAGE_MASK) | INIT_FLAGS;
|
||||||
// glhf reading this bozo
|
// glhf reading this bozo
|
||||||
|
current->len = mmmt->len;
|
||||||
current->size = (mmmt->len - (sizeof(struct frame_zone) +
|
current->size = (mmmt->len - (sizeof(struct frame_zone) +
|
||||||
(mmmt->len / PAGE_SIZE) / 32));
|
(mmmt->len / PAGE_SIZE) / 32));
|
||||||
current->remaining_frames = current->size / PAGE_SIZE;
|
current->remaining_frames = current->size / PAGE_SIZE;
|
||||||
|
current->first_free_frame = 0;
|
||||||
current->next = NULL;
|
current->next = NULL;
|
||||||
|
|
||||||
struct frame_zone *it = head;
|
if (!head) {
|
||||||
if (!it) {
|
|
||||||
head = current;
|
head = current;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
struct frame_zone *it = head;
|
||||||
while (it->next)
|
while (it->next)
|
||||||
it = it->next;
|
it = it->next;
|
||||||
it->next = current;
|
it->next = current;
|
||||||
|
@ -46,11 +46,10 @@ void *alloc_pages(size_t size)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (size_t i = index; i - (size_t)index < nb_pages; i++) {
|
for (size_t i = index; i - (size_t)index < nb_pages; i++) {
|
||||||
void *frame = alloc_frames(PAGE_SIZE);
|
void *frame = alloc_frame();
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
for (size_t j = index; j < i; j++)
|
for (size_t j = index; j < i; j++)
|
||||||
free_frames((void *)(page_table[j] >> 12),
|
free_frame((void *)(page_table[j] >> 12));
|
||||||
PAGE_SIZE);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
|
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
|
||||||
@ -83,7 +82,7 @@ int free_pages(void *page_ptr, size_t size)
|
|||||||
kprintf(KERN_WARNING "Page already free\n");
|
kprintf(KERN_WARNING "Page already free\n");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
free_frames((void *)(page_table[i] & PAGE_MASK), PAGE_SIZE);
|
free_frame((void *)(page_table[i] & PAGE_MASK));
|
||||||
page_table[i] = i << 12;
|
page_table[i] = i << 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ void init_page_table(uint32_t page_table[1024], uint16_t start)
|
|||||||
|
|
||||||
int16_t add_page_table(uint16_t pd_index)
|
int16_t add_page_table(uint16_t pd_index)
|
||||||
{
|
{
|
||||||
void *frame = alloc_frames(PAGE_SIZE);
|
void *frame = alloc_frame();
|
||||||
if (!frame)
|
if (!frame)
|
||||||
return -1;
|
return -1;
|
||||||
page_table_default[PT_START + pd_index] =
|
page_table_default[PT_START + pd_index] =
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
#include "alloc.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
Zone *kzones[3];
|
|
||||||
|
|
||||||
static void add_zone(Zone *zone, block_type_t type)
|
|
||||||
{
|
|
||||||
// We put the zone at the beginning of the list
|
|
||||||
if (kzones[type]) {
|
|
||||||
zone->next = kzones[type];
|
|
||||||
kzones[type]->prev = zone;
|
|
||||||
}
|
|
||||||
kzones[type] = zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void new_block(Zone *zone, uint32_t zone_size)
|
|
||||||
{
|
|
||||||
Block *new_block = (Block *)align_mem((uint32_t)zone + sizeof(Zone));
|
|
||||||
|
|
||||||
// Metadata
|
|
||||||
new_block->in_use = false;
|
|
||||||
new_block->size = zone_size - sizeof(Zone) - sizeof(Block);
|
|
||||||
new_block->sub_size = new_block->size;
|
|
||||||
new_block->ptr = (Block *)((uint32_t)new_block + sizeof(Block));
|
|
||||||
new_block->zone = zone;
|
|
||||||
|
|
||||||
// Init future linked lists
|
|
||||||
new_block->prev = NULL;
|
|
||||||
new_block->prev_free = NULL;
|
|
||||||
new_block->prev_used = NULL;
|
|
||||||
new_block->next = NULL;
|
|
||||||
new_block->next_free = NULL;
|
|
||||||
new_block->next_used = NULL;
|
|
||||||
|
|
||||||
if (zone->free) {
|
|
||||||
zone->free->prev = new_block;
|
|
||||||
zone->free->prev_free = new_block;
|
|
||||||
new_block->next = zone->free;
|
|
||||||
new_block->next_free = zone->free;
|
|
||||||
}
|
|
||||||
zone->free = new_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
int new_kzone(block_type_t type, uint32_t size)
|
|
||||||
{
|
|
||||||
void *heap = alloc_frames(size);
|
|
||||||
if (heap == NULL) {
|
|
||||||
kprintf(KERN_ERR "error: alloc_frames failed\n");
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Zone *zone = (Zone *)heap;
|
|
||||||
zone->type = type;
|
|
||||||
zone->size = size;
|
|
||||||
zone->used = NULL;
|
|
||||||
zone->next = NULL;
|
|
||||||
zone->prev = NULL;
|
|
||||||
|
|
||||||
new_block(zone, size);
|
|
||||||
add_zone(heap, type);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
#include "alloc.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// FULL_INFO is to display (or not) both used and unused blocks
|
|
||||||
#define FULL_INFO 1
|
|
||||||
|
|
||||||
void show_kalloc_mem(void)
|
|
||||||
{
|
|
||||||
char *const kzones_name[3] = {"TINY", "SMALL", "LARGE"};
|
|
||||||
uint32_t total_size = 0;
|
|
||||||
|
|
||||||
for (block_type_t type = 0; type < 3; ++type) {
|
|
||||||
int count = 0;
|
|
||||||
for (Zone *zone_it = kzones[type]; zone_it != NULL;
|
|
||||||
zone_it = zone_it->next) {
|
|
||||||
#if FULL_INFO
|
|
||||||
if (zone_it->free)
|
|
||||||
kprintf("---------- AVAILABLE %s [n°%d - %p] "
|
|
||||||
"----------\n",
|
|
||||||
kzones_name[type], count, zone_it);
|
|
||||||
for (Block *block_it = zone_it->free; block_it != NULL;
|
|
||||||
block_it = block_it->next_free) {
|
|
||||||
kprintf("%p - %p : %u bytes\n", block_it->ptr,
|
|
||||||
(uint32_t)block_it->ptr +
|
|
||||||
block_it->sub_size + sizeof(Block),
|
|
||||||
block_it->sub_size);
|
|
||||||
}
|
|
||||||
if (zone_it->free)
|
|
||||||
kprintf("\n");
|
|
||||||
#endif
|
|
||||||
if (zone_it->used)
|
|
||||||
kprintf("---------- IN_USE %s [n°%d - %p] "
|
|
||||||
"----------\n",
|
|
||||||
kzones_name[type], count, zone_it);
|
|
||||||
for (Block *block_it = zone_it->used; block_it != NULL;
|
|
||||||
block_it = block_it->next_used) {
|
|
||||||
kprintf("%p - %p : %u bytes\n", block_it->ptr,
|
|
||||||
(uint32_t)block_it->ptr +
|
|
||||||
block_it->sub_size + sizeof(Block),
|
|
||||||
block_it->sub_size);
|
|
||||||
total_size += block_it->sub_size;
|
|
||||||
}
|
|
||||||
if (zone_it->used)
|
|
||||||
kprintf("\n");
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kprintf("Total: %u\n", total_size);
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
#include "alloc.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
static void remove_used(Block *to_free)
|
|
||||||
{
|
|
||||||
Block *left = to_free->prev_used;
|
|
||||||
Block *right = to_free->next_used;
|
|
||||||
|
|
||||||
to_free->next_used = NULL;
|
|
||||||
to_free->prev_used = NULL;
|
|
||||||
|
|
||||||
if (!left && !right) {
|
|
||||||
to_free->zone->used = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!left)
|
|
||||||
to_free->zone->used = right;
|
|
||||||
else
|
|
||||||
left->next_used = right;
|
|
||||||
if (right)
|
|
||||||
right->prev_used = left;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If all the blocks of the zone have been kfreed,
|
|
||||||
* we can unmap the zone and delete it from the list of kzones
|
|
||||||
*/
|
|
||||||
static int unmap_zone(Zone *zone)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
block_type_t type = zone->type;
|
|
||||||
Zone *left = zone->prev;
|
|
||||||
Zone *right = zone->next;
|
|
||||||
zone->prev = NULL;
|
|
||||||
zone->next = NULL;
|
|
||||||
|
|
||||||
if (!left && !right) {
|
|
||||||
kzones[type] = NULL;
|
|
||||||
goto unmap;
|
|
||||||
}
|
|
||||||
if (!left)
|
|
||||||
kzones[type] = right;
|
|
||||||
else
|
|
||||||
left->next = right;
|
|
||||||
if (right)
|
|
||||||
right->prev = left;
|
|
||||||
unmap:
|
|
||||||
err = free_frames((void *)zone, zone->size);
|
|
||||||
if (err)
|
|
||||||
kprintf(KERN_ERR "error: munmap failed\n");
|
|
||||||
return (err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the newly kfreed block is next to another previously
|
|
||||||
* kfreed block, merge both of these and update the size
|
|
||||||
*/
|
|
||||||
static Block *merge_blocks(Block *left, Block *right)
|
|
||||||
{
|
|
||||||
if (right->next)
|
|
||||||
right->next->prev = left;
|
|
||||||
if (right->next_free) {
|
|
||||||
right->next_free->prev_free = left;
|
|
||||||
left->next_free = right->next_free;
|
|
||||||
}
|
|
||||||
left->next = right->next;
|
|
||||||
left->size += right->size + sizeof(Block);
|
|
||||||
return (left);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simply add the new block to the list of available blocks
|
|
||||||
static int add_available(Block *available, Block *merged)
|
|
||||||
{
|
|
||||||
Zone *zone = available->zone;
|
|
||||||
if (merged != zone->free && available != zone->free)
|
|
||||||
available->next_free = zone->free;
|
|
||||||
if (zone->free)
|
|
||||||
zone->free->prev_free = available;
|
|
||||||
zone->free = available;
|
|
||||||
if (zone->type == LARGE)
|
|
||||||
return (unmap_zone(zone));
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ptr: pointer to kfree, if the pointer is invalid the kfree()
|
|
||||||
* function will have an undefined behavior (most likely segfault)
|
|
||||||
*
|
|
||||||
* First, we remove the block from the list of in_use blocks
|
|
||||||
* Then, we check if the block needs to be merged with another
|
|
||||||
* neighboring block, if so we replace the previous block by the
|
|
||||||
* newly merged block
|
|
||||||
* Finally, we add the block to the list of available blocks
|
|
||||||
*/
|
|
||||||
void kfree(void *ptr)
|
|
||||||
{
|
|
||||||
if (ptr == NULL)
|
|
||||||
return;
|
|
||||||
Block *to_free = (Block *)((uint32_t)ptr - sizeof(Block));
|
|
||||||
Block *to_merge = NULL;
|
|
||||||
to_free->in_use = false;
|
|
||||||
remove_used(to_free);
|
|
||||||
if (to_free->prev && !to_free->prev->in_use) {
|
|
||||||
to_merge = to_free;
|
|
||||||
to_free = merge_blocks(to_free->prev, to_free);
|
|
||||||
}
|
|
||||||
if (to_free->next && !to_free->next->in_use) {
|
|
||||||
to_merge = to_free->next;
|
|
||||||
to_free = merge_blocks(to_free, to_free->next);
|
|
||||||
}
|
|
||||||
int err = add_available(to_free, to_merge);
|
|
||||||
if (err)
|
|
||||||
kprintf(KERN_ERR "kfree: fatal error\n");
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
#include "alloc.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "kprintf.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find first available (not in_use) block
|
|
||||||
* in a zone matching the size we need
|
|
||||||
*/
|
|
||||||
static Block *find_block(Zone *head, uint32_t size)
|
|
||||||
{
|
|
||||||
for (Zone *zone_it = head; zone_it != NULL; zone_it = zone_it->next) {
|
|
||||||
for (Block *block_it = zone_it->free; block_it != NULL;
|
|
||||||
block_it = block_it->next_free) {
|
|
||||||
assert(!block_it->in_use);
|
|
||||||
if (size <= block_it->size) {
|
|
||||||
assert(block_it->zone == zone_it);
|
|
||||||
return (block_it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PARTIALLY DEPRECATED
|
|
||||||
/*
|
|
||||||
* This will split the newly allocated block to use
|
|
||||||
* the remaining bytes for a new block
|
|
||||||
* This is our linked list of blocks
|
|
||||||
* ... -> [5] -> [6] -> ...
|
|
||||||
* After the allocation, this will become
|
|
||||||
* ... -> [5] -> [new] -> [6] -> ...
|
|
||||||
*
|
|
||||||
* For an example of [5].size = 32 and requiring a kmalloc of 10
|
|
||||||
* Let's say the metadata takes a size of 2:
|
|
||||||
* ... -> [metadata][data][remaining size] -> [6]
|
|
||||||
* ^ ^ ^
|
|
||||||
* 2 10 20
|
|
||||||
*
|
|
||||||
* So now our block [new] will become:
|
|
||||||
* [5] -> [metadata][available data] -> [6]
|
|
||||||
* ^ ^
|
|
||||||
* 2 18
|
|
||||||
* We can see that it now has its own metadata and available
|
|
||||||
* data and it points towards [6]
|
|
||||||
*/
|
|
||||||
static void frag_block(Zone *zone, Block *old_block, uint32_t size)
|
|
||||||
{
|
|
||||||
Block *new_block = (Block *)align_mem((uint32_t)old_block + size);
|
|
||||||
assert(!(new_block >=
|
|
||||||
(Block *)((uint32_t)zone + get_zone_size(zone->type))));
|
|
||||||
|
|
||||||
// Newly created block metadata
|
|
||||||
new_block->size = old_block->size - size;
|
|
||||||
new_block->sub_size = new_block->size;
|
|
||||||
new_block->in_use = false;
|
|
||||||
new_block->ptr = (void *)((uint32_t)new_block + sizeof(Block));
|
|
||||||
new_block->zone = zone;
|
|
||||||
|
|
||||||
new_block->prev = old_block;
|
|
||||||
new_block->next = old_block->next;
|
|
||||||
old_block->next = new_block;
|
|
||||||
|
|
||||||
new_block->prev_used = NULL;
|
|
||||||
new_block->next_used = NULL;
|
|
||||||
|
|
||||||
new_block->prev_free = old_block->prev_free;
|
|
||||||
new_block->next_free = old_block->next_free;
|
|
||||||
|
|
||||||
if (zone->free == old_block)
|
|
||||||
zone->free = new_block;
|
|
||||||
|
|
||||||
old_block->next_free = NULL;
|
|
||||||
old_block->prev_free = NULL;
|
|
||||||
|
|
||||||
// Newly in_use block metadata
|
|
||||||
old_block->in_use = true;
|
|
||||||
old_block->size = size - sizeof(Block);
|
|
||||||
old_block->sub_size = old_block->size;
|
|
||||||
|
|
||||||
if (zone->used == NULL) {
|
|
||||||
zone->used = old_block;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
old_block->prev_used = NULL;
|
|
||||||
old_block->next_used = zone->used;
|
|
||||||
zone->used->prev_used = old_block;
|
|
||||||
zone->used = old_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the block to use and unset free
|
|
||||||
static void save_block(Zone *head, Block *block, Zone *zone)
|
|
||||||
{
|
|
||||||
zone->free = NULL;
|
|
||||||
block->in_use = true;
|
|
||||||
if (head->used) {
|
|
||||||
head->used->prev_used = block;
|
|
||||||
head->used->prev = block;
|
|
||||||
block->next = head->used;
|
|
||||||
block->next_used = head->used;
|
|
||||||
}
|
|
||||||
head->used = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* size: size needed by the user to get allocated
|
|
||||||
*
|
|
||||||
* First, we init the allocator if it's the first time
|
|
||||||
* Then we search if there is an available block in all
|
|
||||||
* the kzones currently mapped
|
|
||||||
* If no block has been found (NULL), we create 1 new zone of
|
|
||||||
* the corresponding type
|
|
||||||
* We then search again for an available block (should not be NULL)
|
|
||||||
* Finally, if type == LARGE, we just have to change the block to used
|
|
||||||
* else, we frag the block to use just what's needed
|
|
||||||
*
|
|
||||||
* ptr: returns the aligned pointer of the block (after the metadata)
|
|
||||||
*/
|
|
||||||
void *kmalloc(uint32_t size)
|
|
||||||
{
|
|
||||||
void *ptr = NULL;
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
kprintf(KERN_WARNING "kmalloc: can't kmalloc(0)\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the zone we need to search
|
|
||||||
block_type_t type = get_type(size);
|
|
||||||
Zone *head = kzones[type];
|
|
||||||
|
|
||||||
// Find an available block in a zone of type "type"
|
|
||||||
Block *available = find_block(head, size);
|
|
||||||
if (available == NULL) {
|
|
||||||
uint32_t full_size;
|
|
||||||
if (type == LARGE)
|
|
||||||
full_size = size + sizeof(Block) + sizeof(Zone);
|
|
||||||
else
|
|
||||||
full_size = get_zone_size(type);
|
|
||||||
if (new_kzone(type, full_size) == -1)
|
|
||||||
return NULL;
|
|
||||||
head = kzones[type];
|
|
||||||
available = find_block(head, size);
|
|
||||||
}
|
|
||||||
assert(available != NULL);
|
|
||||||
if (type == LARGE)
|
|
||||||
save_block(head, available, available->zone);
|
|
||||||
else
|
|
||||||
frag_block(available->zone, available, size + sizeof(Block));
|
|
||||||
ptr = available->ptr;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
#include "alloc.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// Prototype for kfree and kmalloc
|
|
||||||
void kfree(void *ptr);
|
|
||||||
void *kmalloc(uint32_t size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ptr: block to resize (undefined behavior if invalid)
|
|
||||||
* size: size needed by the user to get kreallocated
|
|
||||||
*
|
|
||||||
* If we have a size <= to the previous size, we don't have
|
|
||||||
* to do anything, we just change sub_size for info purposes
|
|
||||||
* and return the same pointer
|
|
||||||
* Else, we allocate a new block and copy the content of
|
|
||||||
* the previous block in the new one and kfree the old block
|
|
||||||
*
|
|
||||||
* ptr: returns the aligned pointer of the kreallocated block
|
|
||||||
*/
|
|
||||||
void *krealloc(void *ptr, uint32_t size)
|
|
||||||
{
|
|
||||||
void *new_ptr = NULL;
|
|
||||||
if (ptr == NULL)
|
|
||||||
return NULL;
|
|
||||||
Block *block = (Block *)((uint32_t)ptr - sizeof(Block));
|
|
||||||
if (block->size >= size) {
|
|
||||||
block->sub_size = size;
|
|
||||||
return (ptr);
|
|
||||||
}
|
|
||||||
new_ptr = kmalloc(size);
|
|
||||||
if (new_ptr == NULL)
|
|
||||||
return NULL;
|
|
||||||
memmove(new_ptr, ptr, block->size);
|
|
||||||
kfree(ptr);
|
|
||||||
return (new_ptr);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#include "alloc.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
uint32_t ksize(void *ptr)
|
|
||||||
{
|
|
||||||
Block *meta_data = (Block *)((uint32_t)ptr - sizeof(Block));
|
|
||||||
|
|
||||||
return meta_data->sub_size;
|
|
||||||
}
|
|
@ -32,6 +32,6 @@ void *vrealloc(void *ptr, uint32_t size)
|
|||||||
if (new_ptr == NULL)
|
if (new_ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
memmove(new_ptr, ptr, block->size);
|
memmove(new_ptr, ptr, block->size);
|
||||||
kfree(ptr);
|
vfree(ptr);
|
||||||
return (new_ptr);
|
return (new_ptr);
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,6 @@
|
|||||||
|
|
||||||
void heap_cmd(char *arg)
|
void heap_cmd(char *arg)
|
||||||
{
|
{
|
||||||
if (!arg)
|
(void)arg;
|
||||||
kprintf(KERN_INFO "You must specify an argument (phys/virt)\n");
|
|
||||||
else if (!strcmp(arg, "phys"))
|
|
||||||
show_kalloc_mem();
|
|
||||||
else if (!strcmp(arg, "virt"))
|
|
||||||
show_valloc_mem();
|
show_valloc_mem();
|
||||||
else
|
|
||||||
kprintf(KERN_INFO "%s: invalid argument to heap (phys/virt)\n",
|
|
||||||
arg);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user