This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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