Actually buddy allocator is good....
This commit is contained in:
parent
0b6b0a46b4
commit
8ef4b18684
|
@ -0,0 +1,67 @@
|
|||
/* Copyright 2016 secXsQuared
|
||||
* Distributed under GPL license
|
||||
* See COPYING under root for details
|
||||
*/
|
||||
|
||||
#include "balloc.h"
|
||||
#include "std_lib.h"
|
||||
#include "bit_ops.h"
|
||||
|
||||
int32_t balloc_init(balloc_desc_t *desc,
|
||||
uint64_t base,
|
||||
uint64_t end,
|
||||
uint64_t page_size,
|
||||
balloc_alloc_func alloc,
|
||||
balloc_free_func free,
|
||||
balloc_lock_func lock,
|
||||
balloc_unlock_func unlock)
|
||||
{
|
||||
if(desc == NULL || base >= end || page_size == 0 || alloc == 0
|
||||
|| free == 0 || lock == 0 || unlock == 0)
|
||||
return BALLOC_STATUS_INVALID_ARGUMENTS;
|
||||
|
||||
if(((end - base) % page_size) != 0)
|
||||
return BALLOC_STATUS_INVALID_ALIGNMENT;
|
||||
|
||||
desc->alloc = alloc;
|
||||
desc->free = free;
|
||||
desc->lock = lock;
|
||||
desc->unlock = unlock;
|
||||
|
||||
desc->base = base;
|
||||
desc->page_size = page_size;
|
||||
uint64_t quot = (end-base) / page_size;
|
||||
uint32_t order = log_base_2(quot);
|
||||
if(quot & bit_mask_64(order) != 0)
|
||||
{
|
||||
order++;
|
||||
}
|
||||
desc->order = order;
|
||||
|
||||
// allocate linked lists and bit maps
|
||||
desc->free_lists = (linked_list_t*)desc->alloc((order + 1) * sizeof(linked_list_t));
|
||||
if(desc->free_lists == NULL || desc->bit_map == NULL)
|
||||
return BALLOC_STATUS_CANT_ALLOC_MEM;
|
||||
|
||||
return BALLOC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t balloc_alloc(balloc_desc_t* desc, uint32_t page_num, uint64_t* out)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int32_t balloc_free(balloc_desc_t* desc, uint64_t addr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int32_t balloc_mark_used(balloc_desc_t* desc, uint64_t start, uint64_t end)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int32_t balloc_mark_free(balloc_desc_t* desc, uint64_t start, uint64_t end)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef _BALLOC_H_
|
||||
#define _BALLOC_H_
|
||||
|
||||
#include "linked_list.h"
|
||||
#include "avl_tree.h"
|
||||
|
||||
/*
|
||||
* A tree allocator for page-size allocation
|
||||
* All
|
||||
*/
|
||||
|
||||
#define BALLOC_STATUS_SUCCESS 0
|
||||
#define BALLOC_STATUS_INVALID_ARGUMENTS 1
|
||||
#define BALLOC_STATUS_NO_AVAILABLE_MEM 2
|
||||
#define BALLOC_STATUS_CANT_ALLOC_MEM 3
|
||||
#define BALLOC_STATUS_INVALID_ALIGNMENT 4
|
||||
|
||||
typedef void *(*balloc_alloc_func)(uint64_t size);
|
||||
|
||||
typedef void (*balloc_free_func)(void *ptr);
|
||||
|
||||
typedef void (*balloc_lock_func)(void);
|
||||
|
||||
typedef void (*balloc_unlock_func)(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t base;
|
||||
uint64_t order;
|
||||
uint64_t page_size;
|
||||
|
||||
linked_list_t *free_lists;
|
||||
uint8_t *bit_map;
|
||||
|
||||
balloc_alloc_func alloc;
|
||||
balloc_free_func free;
|
||||
balloc_lock_func lock;
|
||||
balloc_unlock_func unlock;
|
||||
} balloc_desc_t;
|
||||
|
||||
|
||||
int32_t balloc_init(balloc_desc_t *desc,
|
||||
uint64_t base,
|
||||
uint64_t end,
|
||||
uint64_t page_size,
|
||||
balloc_alloc_func alloc,
|
||||
balloc_free_func free,
|
||||
balloc_lock_func lock,
|
||||
balloc_unlock_func unlock);
|
||||
|
||||
int32_t balloc_alloc(balloc_desc_t* desc, uint32_t page_num, uint64_t* out);
|
||||
|
||||
int32_t balloc_free(balloc_desc_t* desc, uint64_t addr);
|
||||
|
||||
int32_t balloc_mark_used(balloc_desc_t* desc, uint64_t start, uint64_t end);
|
||||
|
||||
int32_t balloc_mark_free(balloc_desc_t* desc, uint64_t start, uint64_t end);
|
||||
|
||||
#endif
|
|
@ -32,7 +32,8 @@ static inline uint64_t KAPI align_down(uint64_t val, uint64_t alignment)
|
|||
|
||||
static inline uint64_t KAPI align_up(uint64_t val, uint64_t alignment)
|
||||
{
|
||||
return ((((val) % (alignment)) == 0) ? (((val) / (alignment)) * (alignment)) : ((((val) / (alignment)) * (alignment)) + 1));
|
||||
return ((((val) % (alignment)) == 0) ? (((val) / (alignment)) * (alignment)) : (
|
||||
(((val) / (alignment)) * (alignment)) + 1));
|
||||
}
|
||||
|
||||
static inline uint64_t KAPI is_overlap(uint64_t x1, uint64_t x2, uint64_t y1, uint64_t y2)
|
||||
|
@ -40,6 +41,7 @@ static inline uint64_t KAPI is_overlap(uint64_t x1, uint64_t x2, uint64_t y1, ui
|
|||
return ((x1 <= y2) && (y1 <= x2)) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int64_t KAPI max_64(int64_t a, int64_t b)
|
||||
{
|
||||
return (a) > (b) ? a : b;
|
||||
|
@ -60,6 +62,31 @@ static inline int32_t KAPI min_32(int32_t a, int32_t b)
|
|||
return (a) < (b) ? a : b;
|
||||
}
|
||||
|
||||
#define OBTAIN_STRUCT_ADDR(member_addr, member_name, struct_name) ((struct_name*)((void*)(member_addr)-(void*)(&(((struct_name*)0)->member_name))))
|
||||
static inline uint64_t KAPI round_up_power_of_2(uint64_t num)
|
||||
{
|
||||
num--;
|
||||
num |= num >> 1;
|
||||
num |= num >> 2;
|
||||
num |= num >> 4;
|
||||
num |= num >> 8;
|
||||
num |= num >> 16;
|
||||
num |= num >> 32;
|
||||
num++;
|
||||
return (uint64_t)num;
|
||||
}
|
||||
|
||||
static inline uint32_t KAPI log_base_2(uint64_t num)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
while (num >>= 1)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((void*)(member_addr)-(void*)(&(((struct_name*)0)->member_name))))
|
||||
|
||||
#endif
|
|
@ -1,64 +0,0 @@
|
|||
#ifndef _TALLOC_H_
|
||||
#define _TALLOC_H_
|
||||
|
||||
#include "avl_tree.h"
|
||||
|
||||
/*
|
||||
* A tree allocator for page-size allocation
|
||||
* All
|
||||
*/
|
||||
|
||||
#define TALLOC_STATUS_SUCCESS 0
|
||||
#define TALLOC_STATUS_INVALID_ARGUMENTS 1
|
||||
#define TALLOC_STATUS_NOT_ENOUGH_MEM 2
|
||||
#define TALLOC_STATUS_CANT_ALLOC_NODE 3
|
||||
#define TALLOC_STATUS_INVALID_REIGON 4
|
||||
|
||||
typedef void *(*talloc_alloc_func)(uint64_t size);
|
||||
typedef void (*talloc_free_func)(void* ptr);
|
||||
typedef void (*talloc_lock_func)(void);
|
||||
typedef void (*talloc_unlock_func)(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
avl_tree_t used_base_tree;
|
||||
avl_tree_t free_size_tree;
|
||||
avl_tree_t free_start_tree;
|
||||
avl_tree_t free_end_tree;
|
||||
|
||||
uint64_t page_size;
|
||||
|
||||
talloc_alloc_func alloc;
|
||||
talloc_free_func free;
|
||||
talloc_lock_func lock;
|
||||
talloc_unlock_func unlock;
|
||||
} talloc_desc_t;
|
||||
|
||||
|
||||
int32_t talloc(talloc_desc_t* desc,
|
||||
uint64_t size,
|
||||
uint64_t alignment,
|
||||
void** out);
|
||||
|
||||
|
||||
int32_t talloc_init(talloc_desc_t *desc,
|
||||
void *base,
|
||||
uint64_t size,
|
||||
uint64_t page_size,
|
||||
talloc_alloc_func alloc,
|
||||
talloc_free_func free,
|
||||
talloc_lock_func lock,
|
||||
talloc_unlock_func unlock);
|
||||
|
||||
int32_t talloc_mark_used(talloc_desc_t *desc,
|
||||
void *base,
|
||||
uint64_t size);
|
||||
|
||||
int32_t talloc_mark_free(talloc_desc_t* desc,
|
||||
void *base,
|
||||
uint64_t size);
|
||||
|
||||
int32_t tfree(talloc_desc_t *desc,
|
||||
void *base);
|
||||
|
||||
#endif
|
|
@ -1,192 +0,0 @@
|
|||
/* Copyright 2016 secXsQuared
|
||||
* Distributed under GPL license
|
||||
* See COPYING under root for details
|
||||
*/
|
||||
|
||||
#include "linked_list.h"
|
||||
#include "talloc.h"
|
||||
#include "std_lib.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
avl_tree_node_t tree_node;
|
||||
uint64_t size;
|
||||
linked_list_t free_size_list;
|
||||
} lalloc_free_list_node_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
avl_tree_node_t used_base_tree_node;
|
||||
linked_list_node_t free_size_list_node;
|
||||
avl_tree_node_t free_start_tree_node;
|
||||
avl_tree_node_t free_end_tree_node;
|
||||
void *base;
|
||||
uint64_t size;
|
||||
void *end;
|
||||
} lalloc_desc_node_t;
|
||||
|
||||
static int32_t _lalloc_desc_node_size_compare(avl_tree_node_t *others, avl_tree_node_t *yours)
|
||||
{
|
||||
uint64_t osize = OBTAIN_STRUCT_ADDR(others, free_size_tree_node, lalloc_desc_node_t)->size;
|
||||
uint64_t ysize = OBTAIN_STRUCT_ADDR(yours, free_size_tree_node, lalloc_desc_node_t)->size;
|
||||
if (osize == ysize)
|
||||
return 0;
|
||||
else if (osize > ysize)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t _lalloc_desc_node_start_compare(avl_tree_node_t *others, avl_tree_node_t *yours)
|
||||
{
|
||||
uint64_t osize = (uint64_t) (OBTAIN_STRUCT_ADDR(others, free_size_tree_node, lalloc_desc_node_t)->base);
|
||||
uint64_t ysize = (uint64_t) (OBTAIN_STRUCT_ADDR(yours, free_size_tree_node, lalloc_desc_node_t)->base);
|
||||
if (osize == ysize)
|
||||
return 0;
|
||||
else if (osize > ysize)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t _lalloc_desc_node_end_compare(avl_tree_node_t *others, avl_tree_node_t *yours)
|
||||
{
|
||||
uint64_t osize = (uint64_t) (OBTAIN_STRUCT_ADDR(others, free_size_tree_node, lalloc_desc_node_t)->end);
|
||||
uint64_t ysize = (uint64_t) (OBTAIN_STRUCT_ADDR(yours, free_size_tree_node, lalloc_desc_node_t)->end);
|
||||
if (osize == ysize)
|
||||
return 0;
|
||||
else if (osize > ysize)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _lalloc_merge_nodes(lalloc_desc_node_t *node)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int32_t _lalloc_node_alloc(talloc_desc_t *desc, lalloc_desc_node_t *node, uint64_t size, uint64_t alignment,
|
||||
void **out)
|
||||
{
|
||||
if (desc == NULL || node == NULL || size == 0 || alignment == 0 || out == NULL)
|
||||
{
|
||||
return LALLOC_STATUS_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
int32_t result = LALLOC_STATUS_NOT_ENOUGH_MEM;
|
||||
|
||||
uint64_t real_base = align_up((uint64_t) node->base, alignment);
|
||||
uint64_t real_size = node->size - ((uint64_t) real_base - (uint64_t) node->base);
|
||||
|
||||
if (real_size >= size)
|
||||
{
|
||||
// we've got a hit
|
||||
uint64_t prev_size = real_base - (uint64_t) node->base;
|
||||
uint64_t next_size = (uint64_t) node->base + node->size - real_base;
|
||||
|
||||
if (prev_size == 0 && next_size == 0)
|
||||
{
|
||||
// if the block is just enough
|
||||
// detach the block and
|
||||
linked_list_remove_ref(&desc->free_list, &each_desc_node->list_node);
|
||||
desc->free();
|
||||
}
|
||||
|
||||
result = LALLOC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline _Bool _lalloc_is_desc_valid(talloc_desc_t *desc)
|
||||
{
|
||||
return desc != NULL && desc->unlock != NULL && desc->lock != NULL && desc->alloc != NULL && desc->free != NULL;
|
||||
}
|
||||
|
||||
int32_t lalloc(talloc_desc_t *desc,
|
||||
uint64_t size,
|
||||
uint64_t alignment,
|
||||
void **out)
|
||||
{
|
||||
if (!_lalloc_is_desc_valid(desc) || size == 0 || alignment == 0 || out == NULL)
|
||||
return LALLOC_STATUS_INVALID_ARGUMENTS;
|
||||
|
||||
int32_t result = LALLOC_STATUS_NOT_ENOUGH_MEM;
|
||||
|
||||
|
||||
desc->lock();
|
||||
|
||||
|
||||
linked_list_node_t *each_list_node = linked_list_first(&desc->free_list);
|
||||
while (each_list_node != NULL)
|
||||
{
|
||||
// calculate real base/size w.r.t. alignment
|
||||
lalloc_desc_node_t *each_desc_node = OBTAIN_STRUCT_ADDR(each_list_node, list_node, lalloc_desc_node_t);
|
||||
|
||||
if (_lalloc_node_alloc(desc, each_desc_node, size, alignment, out) == LALLOC_STATUS_SUCCESS)
|
||||
{
|
||||
result = LALLOC_STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
each_list_node = linked_list_next(each_list_node);
|
||||
}
|
||||
|
||||
|
||||
desc->unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t talloc_init(talloc_desc_t *desc,
|
||||
void *base,
|
||||
uint64_t size,
|
||||
uint64_t page_size,
|
||||
talloc_alloc_func alloc,
|
||||
talloc_free_func free,
|
||||
talloc_lock_func lock,
|
||||
talloc_unlock_func unlock)
|
||||
{
|
||||
if (desc == NULL || alloc == NULL || free == NULL ||
|
||||
size == 0 || page_size == 0 || base == NULL ||
|
||||
lock == NULL || unlock == NULL || (uint64_t) base % page_size != 0)
|
||||
return TALLOC_STATUS_INVALID_ARGUMENTS;
|
||||
|
||||
avl_tree_init(&desc->used_base_tree);
|
||||
avl_tree_init(&desc->free_size_tree);
|
||||
avl_tree_init(&desc->free_start_tree);
|
||||
avl_tree_init(&desc->free_end_tree,);
|
||||
avl_tree_init(&desc->used_tree, _lalloc_desc_node_size_compare);
|
||||
|
||||
desc->alloc = alloc;
|
||||
desc->free = free;
|
||||
desc->lock = lock;
|
||||
desc->unlock = unlock;
|
||||
desc->page_size = page_size;
|
||||
|
||||
lalloc_desc_node_t *node = desc->alloc(sizeof(lalloc_desc_node_t));
|
||||
|
||||
if (node == NULL)
|
||||
return LALLOC_STATUS_CANT_ALLOC_NODE;
|
||||
|
||||
node->size = size;
|
||||
node->base = base;
|
||||
linked_list_push_back(&desc->free_list, &node->list_node);
|
||||
|
||||
return LALLOC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t lalloc_mark_used(talloc_desc_t *desc,
|
||||
void *base,
|
||||
uint64_t size)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int32_t lalloc_mark_free(talloc_desc_t *desc,
|
||||
void *base,
|
||||
uint64_t size);
|
||||
|
||||
int32_t lfree(talloc_desc_t *desc,
|
||||
void *base);
|
|
@ -16,8 +16,8 @@ static int_tree_node *create_tree_node(int val)
|
|||
|
||||
static int compare(avl_tree_node_t *root, avl_tree_node_t *node)
|
||||
{
|
||||
int_tree_node *rooti = OBTAIN_STRUCT_ADDR(root, tree_entry, int_tree_node);
|
||||
int_tree_node *nodei = OBTAIN_STRUCT_ADDR(node, tree_entry, int_tree_node);
|
||||
int_tree_node *rooti = OBTAIN_STRUCT_ADDR(root, int_tree_node, tree_entry);
|
||||
int_tree_node *nodei = OBTAIN_STRUCT_ADDR(node, int_tree_node, tree_entry);
|
||||
return rooti->val - nodei->val;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ static bool _pre_order_assert(avl_tree_node_t *node, int order[], int size)
|
|||
return false;
|
||||
|
||||
bool result = true;
|
||||
int_tree_node *my_node = OBTAIN_STRUCT_ADDR(node, tree_entry, int_tree_node);
|
||||
int_tree_node *my_node = OBTAIN_STRUCT_ADDR(node, int_tree_node, tree_entry);
|
||||
if (order[counter] != my_node->val)
|
||||
{
|
||||
result = false;
|
||||
|
@ -831,7 +831,7 @@ static bool test_apocalypse()
|
|||
avl_tree_node_t* entry = avl_tree_smallest(&tree);
|
||||
uint32_t size = 0;
|
||||
int32_t prev = -1;
|
||||
int32_t cur = OBTAIN_STRUCT_ADDR(entry, tree_entry,int_tree_node)->val;
|
||||
int32_t cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
while(entry != NULL)
|
||||
{
|
||||
if(cur < prev)
|
||||
|
@ -844,7 +844,7 @@ static bool test_apocalypse()
|
|||
prev = cur;
|
||||
if(entry != NULL)
|
||||
{
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, tree_entry, int_tree_node)->val;
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -853,7 +853,7 @@ static bool test_apocalypse()
|
|||
// larger test
|
||||
entry = avl_tree_largest(&tree);
|
||||
size = 0;
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, tree_entry,int_tree_node)->val;
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
prev = cur;
|
||||
while(entry != NULL)
|
||||
{
|
||||
|
@ -867,7 +867,7 @@ static bool test_apocalypse()
|
|||
prev = cur;
|
||||
if(entry != NULL)
|
||||
{
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, tree_entry, int_tree_node)->val;
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ static bool assert_list(linked_list_t *list, int val[], int size)
|
|||
|
||||
while (node != NULL && i < size)
|
||||
{
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, lnode, my_list_node);
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, my_list_node, lnode);
|
||||
if (enode->val != val[i])
|
||||
{
|
||||
return false;
|
||||
|
@ -62,7 +62,7 @@ static bool assert_list(linked_list_t *list, int val[], int size)
|
|||
node = linked_list_last(list);
|
||||
while (node != NULL && i >= 0)
|
||||
{
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, lnode, my_list_node);
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, my_list_node, lnode);
|
||||
if (enode->val != val[i - 1])
|
||||
{
|
||||
return false;
|
||||
|
@ -400,7 +400,7 @@ static bool push_pop_back_test()
|
|||
|
||||
static bool equals(linked_list_node_t *a, linked_list_node_t *b)
|
||||
{
|
||||
return (int64_t) a == OBTAIN_STRUCT_ADDR(b, lnode, my_list_node)->val;
|
||||
return (int64_t) a == OBTAIN_STRUCT_ADDR(b, my_list_node, lnode)->val;
|
||||
}
|
||||
|
||||
static bool search_test()
|
||||
|
|
Loading…
Reference in New Issue