Skip to content

Instantly share code, notes, and snippets.

@mopp
Last active December 30, 2015 09:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mopp/7807666 to your computer and use it in GitHub Desktop.
Save mopp/7807666 to your computer and use it in GitHub Desktop.
enum memory_manager_constants {
MAX_MEM_NODE_NUM = 4096,
MEM_INFO_STATE_LOST = -1,
MEM_INFO_STATE_FREE,
MEM_INFO_STATE_ALLOC,
};
/* 管理対象のメモリ情報 */
struct memory_info {
uint32_t base_addr, size;
uint8_t state;
};
typedef struct memory_info Memory_info;
/* メモリ管理を行うオブジェクト */
struct memory_manager {
uint32_t exist_info_num, lost_size, lost_times;
Dlinked_list_node mem_lst;
};
typedef struct memory_manager Memory_manager;
/* grubから渡されるデータ */
struct multiboot_mmap {
uint32_t size;
uint64_t addr;
uint64_t len;
uint32_t type;
};
typedef struct multiboot_mmap Multiboot_memory_map;
static inline void init_memory_list(void) {
dlst_nodes = (struct dlinked_list_node*)(get_kernel_end_addr() + sizeof(Memory_manager));
mem_info = (Memory_info*)(dlst_nodes + sizeof(struct dlinked_list_node) * MAX_MEM_NODE_NUM);
for (int i = 0; i < MAX_MEM_NODE_NUM; ++i) {
// 各ノードにメモリ情報を付加
// この時点でメモリの先頭と末尾は何も指していない
init(&dlst_nodes[i], mem_info + i);
memset(mem_info + i, 0, sizeof(Memory_info));
}
}
static inline void set_meminfo(Multiboot_memory_map* mmap, Memory_info* mi) {
mi->base_addr = mmap->addr;
mi->size = mmap->len;
mi->state = (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) ? MEM_INFO_STATE_FREE : MEM_INFO_STATE_ALLOC;
}
void init_memory(Multiboot_memory_map* mmap, size_t mmap_len) {
Multiboot_memory_map* limit = (Multiboot_memory_map*)((uint32_t)mmap + mmap_len);
init_memory_list();
// マネージャにカーネル領域末尾を使用
mem_manager = (Memory_manager*)get_kernel_end_addr();
mem_manager->mem_lst = &dlst_nodes[0];
mem_manager->exist_info_num = 1;
mem_manager->lost_times = 0;
mem_manager->lost_size = 0;
set_meminfo(mmap, mem_manager->mem_lst->data);
Dlinked_list_node tdl = mem_manager->mem_lst;
while (mmap < limit) {
// 次の要素へ
mmap = (Multiboot_memory_map*)((uint32_t)mmap + sizeof(mmap->size) + mmap->size);
Dlinked_list_node dl = get_new_memory_list_node();
Memory_info* mi = dl->data;
set_meminfo(mmap, mi);
tdl = insert_tail(tdl, dl);
}
// allocate kernel area
Dlinked_list_node ka_node = mem_manager->mem_lst;
Memory_info* ka_mi = ka_node->data;
const uint32_t ka_start_addr = get_kernel_start_addr();
const uint32_t ka_end_addr = get_kernel_end_addr() + (uint32_t)mem_info + sizeof(Memory_info) * MAX_MEM_NODE_NUM;
const uint32_t ka_size = ka_end_addr - ka_start_addr;
while (ka_node->tail != DUMMY) {
if (ka_mi->base_addr <= ka_start_addr && ka_end_addr <= (ka_mi->base_addr + ka_mi->size)) {
break;
}
ka_node = ka_node->tail;
ka_mi = ka_node->data;
}
if (ka_mi->base_addr == ka_start_addr && (ka_mi->base_addr + ka_mi->size) == ka_end_addr) {
ka_mi->state = MEM_INFO_STATE_ALLOC;
return;
}
if (ka_mi->base_addr == ka_start_addr) {
ka_mi->size = ka_size;
ka_mi->state = MEM_INFO_STATE_ALLOC;
Dlinked_list_node ka_new_node = get_new_memory_list_node();
Memory_info* ka_new_mi = ka_new_node->data;
ka_new_mi->base_addr = ka_mi->base_addr + ka_size;
ka_new_mi->size = ka_mi->size - ka_size;
ka_new_mi->state = MEM_INFO_STATE_FREE;
insert_tail(ka_node, ka_new_node);
} else {
// TODO
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment