Skip to content
Snippets Groups Projects
Commit 018c8357 authored by Recolic Keghart's avatar Recolic Keghart
Browse files

allocator

parent 9ad8f548
No related branches found
No related tags found
No related merge requests found
Pipeline #837 failed with stage
...@@ -15,7 +15,7 @@ head: ...@@ -15,7 +15,7 @@ head:
nasm -f elf$(BITS) -DTARGET_BITS=$(BITS) image_head.asm -o image_head.o nasm -f elf$(BITS) -DTARGET_BITS=$(BITS) image_head.asm -o image_head.o
kernel: kernel:
g++ -ffreestanding -fpie -c kernel.cc -o kernel.o -m$(BITS) -std=c++17 g++ -ffreestanding -fpie -fno-exceptions -c kernel.cc -o kernel.o -m$(BITS) -std=c++17
clean: clean:
rm -f *.o *.img rm -f *.o *.img
......
...@@ -9,18 +9,19 @@ namespace impl { ...@@ -9,18 +9,19 @@ namespace impl {
constexpr uint64_t kalloc_end_addr = 0x200000; constexpr uint64_t kalloc_end_addr = 0x200000;
// Currently 1MB, must be paged. // Currently 1MB, must be paged.
struct __attribute__((packed)) free_slot_head_t { struct __attribute__((packed)) free_slot_header_t {
uint32_t size; uint32_t size;
uint64_t next; // 0x0 means tail. uint64_t next; // 0x0 means tail.
}; };
static_assert(sizeof(free_slot_head_t) == sizeof(uint32_t) + sizeof(uint64_t)); static_assert(sizeof(free_slot_header_t) == sizeof(uint32_t) + sizeof(uint64_t));
using allocated_slot_head_t = uint32_t; // contains size EXCEPT the head! using allocated_slot_header_t = uint32_t; // contains size EXCEPT the head!
inline void kalloc_init_pool() { inline void kalloc_init_pool() {
// Just create a single huge slot, which contains the whole pool.
struct __attribute__((packed)) _kalloc_head { struct __attribute__((packed)) _kalloc_head {
uint32_t magic = 0x12230823; uint32_t magic = 0x12230823;
free_slot_head_t free_slot_head {kalloc_end_addr - kalloc_begin_addr - sizeof(_kalloc_head), 0x0}; free_slot_header_t free_slot_head {kalloc_end_addr - kalloc_begin_addr - sizeof(_kalloc_head), 0x0};
} kalloc_head; } kalloc_head;
static_assert(sizeof(kalloc_head) == sizeof(uint32_t)*2 + sizeof(uint64_t)); static_assert(sizeof(kalloc_head) == sizeof(uint32_t)*2 + sizeof(uint64_t));
...@@ -28,57 +29,84 @@ namespace impl { ...@@ -28,57 +29,84 @@ namespace impl {
} }
} }
// naive kalloc // naive kalloc. We keep a list of free slot.
// The return value is NULL on failure, and is a valid pointer `p` on success.
// ((allocated_slot_header_t *)p)[-1] contains the header, which records the allocated size.
// and ((char *)p)[0:requested_size] is available for use.
inline void *kalloc_impl(const uint32_t requested_size) { inline void *kalloc_impl(const uint32_t requested_size) {
const auto req_size_with_head = requested_size + sizeof(impl::allocated_slot_head_t); const auto req_size_with_head = requested_size + sizeof(impl::allocated_slot_header_t);
uint64_t prev_slot_addr = 0x0; uint64_t prev_slot_addr = 0x0;
auto curr_slot_addr = impl::kalloc_begin_addr + sizeof(impl::free_slot_head_t::size); // Locate first free slot.
auto curr_slot_addr = impl::kalloc_begin_addr + sizeof(impl::free_slot_header_t::size);
while(true) { while(true) {
auto curr_slot = (impl::free_slot_head_t *)curr_slot_addr; // Iterate all free slots. It's slow, but good enough for a toy.
if(curr_slot->size >= req_size_with_head) { auto curr_freeslot_header_ptr = (impl::free_slot_header_t *)curr_slot_addr;
if(curr_slot->size < 32 + req_size_with_head) { if(curr_freeslot_header_ptr->size >= req_size_with_head) {
// Give the whole slot // Good. We can do the allocate now!
decltype(impl::free_slot_header_t::size) actually_assigned_size;
decltype(curr_slot_addr) allocated_slot_addr;
if(curr_freeslot_header_ptr->size < 32 + req_size_with_head) {
// Give the current slot.
if(prev_slot_addr == 0x0) { if(prev_slot_addr == 0x0) {
// No previous slot. I am the first one. // The first slot must be a valid free_slot_head. It's required
// Never give the WHOLE first slot. Try again. // to locate the next free_slot.
goto _kalloc_failed_try_again; curr_freeslot_header_ptr->size = 0;
// Is this case, the space of free_slot_head is not available.
actually_assigned_size = curr_freeslot_header_ptr->size;
allocated_slot_addr = curr_slot_addr + sizeof(impl::free_slot_header_t);
} }
// Do the alloc
else { else {
curr_slot->size -= req_size_with_head; // Eliminate the current free_slot_head.
auto prev_slot = (impl::free_slot_head_t *)prev_slot_addr; curr_freeslot_header_ptr->size -= req_size_with_head;
prev_slot->next = curr_slot->next; auto prev_slot = (impl::free_slot_header_t *)prev_slot_addr;
prev_slot->next = curr_freeslot_header_ptr->next;
// Is this case, the space of free_slot_head is available.
actually_assigned_size = curr_freeslot_header_ptr->size + sizeof(impl::free_slot_header_t);
allocated_slot_addr = curr_slot_addr;
} }
const auto actually_assigned_size = sizeof(impl::free_slot_head_t) + curr_slot->size;
*(impl::allocated_slot_head_t *)curr_slot_addr = actually_assigned_size;
return (char *)curr_slot_addr + sizeof(impl::allocated_slot_head_t);
} }
else { else {
// Shrink the slot. // The slot is too large. Shrink the free_slot, and give the tail space as result.
// Do the alloc curr_freeslot_header_ptr->size -= req_size_with_head;
// TODO actually_assigned_size = req_size_with_head;
curr_slot->size -= req_size_with_head; allocated_slot_addr = curr_slot_addr + sizeof(impl::free_slot_header_t) + curr_freeslot_header_ptr->size;
return (char *)curr_slot_addr + curr_slot->size;
} }
// Create the allocated_slot_head structure.
*(impl::allocated_slot_header_t *)allocated_slot_addr = actually_assigned_size - sizeof(impl::allocated_slot_header_t);
return (char *)allocated_slot_addr + sizeof(impl::allocated_slot_header_t);
} }
else if (curr_slot->next != 0x0){ else if (curr_freeslot_header_ptr->next != 0x0){
// Failed. Next. // Failed. Try next slot.
_kalloc_failed_try_again:
prev_slot_addr = curr_slot_addr; prev_slot_addr = curr_slot_addr;
curr_slot_addr = curr_slot->next; curr_slot_addr = curr_freeslot_header_ptr->next;
continue; continue;
} }
else { else {
// No memory // We're already at the end. Return NO_MEMORY.
return 0x0; return NULL;
} }
} }
} }
inline void kfree(void *memory) { inline void kfree(void *memory) {
} }
template <typename T>
struct kallocator {
using value_type = T;
kallocator() noexcept {}
template <typename AnyType> kallocator (const kallocator &) noexcept {}
template <typename AnyType> kallocator (kallocator &&) noexcept {}
T *allocate(uint32_t count) {
return (T*)kalloc_impl(sizeof(T) * count);
}
void deallocate (T* p, uint32_t) {
kfree(p);
}
};
#endif #endif
#include <stdint.h>
#define ROS_KERN_STDINT_HPP
#ifndef ROS_KERN_STDINT_HPP #ifndef ROS_KERN_STDINT_HPP
#define ROS_KERN_STDINT_HPP #define ROS_KERN_STDINT_HPP
......
...@@ -3,14 +3,18 @@ ...@@ -3,14 +3,18 @@
#include "stdint.hpp" #include "stdint.hpp"
#ifndef NULL
#define NULL 0
#endif
template <typename T> template <typename T>
inline void memcpy(T *dst, const T *src, size_t count) { inline void memcpy(T *dst, const T *src, uint32_t count) {
for(auto i = 0; i < count; ++i) { for(auto i = 0; i < count; ++i) {
dst[i] = src[i]; dst[i] = src[i];
} }
} }
template <typename T> template <typename T>
inline void memset(T *dst, const T &data_to_set, size_t count) { inline void memset(T *dst, const T &data_to_set, uint32_t count) {
char *cdst = reinterpret_cast<char *>(dst); char *cdst = reinterpret_cast<char *>(dst);
for(auto i = 0; i < count; ++i) { for(auto i = 0; i < count; ++i) {
...@@ -19,4 +23,5 @@ inline void memset(T *dst, const T &data_to_set, size_t count) { ...@@ -19,4 +23,5 @@ inline void memset(T *dst, const T &data_to_set, size_t count) {
} }
#endif #endif
...@@ -24,7 +24,7 @@ inline void set_char(uint16_t x, uint16_t y, char c, char color) { ...@@ -24,7 +24,7 @@ inline void set_char(uint16_t x, uint16_t y, char c, char color) {
VGA_BEGIN_ADDR[y*VGA_WIDTH + x] = VGA_MAKE_CHAR(c, color); VGA_BEGIN_ADDR[y*VGA_WIDTH + x] = VGA_MAKE_CHAR(c, color);
} }
inline void put_char(char c, uint8_t color) { inline void print_char(char c, uint8_t color = default_color) {
static uint16_t pos = 0; static uint16_t pos = 0;
if(pos >= VGA_WIDTH * VGA_HEIGHT) if(pos >= VGA_WIDTH * VGA_HEIGHT)
trigger_scroll(&pos); trigger_scroll(&pos);
...@@ -43,7 +43,7 @@ inline void put_char(char c, uint8_t color) { ...@@ -43,7 +43,7 @@ inline void put_char(char c, uint8_t color) {
inline void print(const char *cstr, uint8_t color = default_color) { inline void print(const char *cstr, uint8_t color = default_color) {
while(*cstr != '\0') { while(*cstr != '\0') {
put_char(*(cstr++), color); print_char(*(cstr++), color);
} }
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "include/bus_io.hpp" #include "include/bus_io.hpp"
#include "include/kutils.hpp" #include "include/kutils.hpp"
#include <string>
void test_dummy_function() { void test_dummy_function() {
auto tmp = read_byte_from_bus(0x3f2); auto tmp = read_byte_from_bus(0x3f2);
tmp |= 0x08; tmp |= 0x08;
...@@ -15,11 +17,23 @@ void kernel_init() { ...@@ -15,11 +17,23 @@ void kernel_init() {
} }
void main() { void main() {
kernel_init();
clear_screen(); clear_screen();
print("Hello world!\n"); print("Hello world!\n");
print("Hello world!\n", 0xb1); print("Hello world!\n", 0xb1);
print("Hello world!\n", 0xae); print("Hello world!\n", 0xae);
print("Hello world!\n", 0x5c); print("Hello world!\n", 0x5c);
print("Hello world! This is recolic's test message, \n"); print("Hello world! This is recolic's test message, \n");
// std::array<uint32_t, 32> test_buf;
// uint32_t * test_buf = (uint32_t *)kalloc_impl(sizeof(uint32_t) * 32);
// for(auto i = 0; i < 32; ++i) {
// test_buf[i] = i == 0 ? 1 : test_buf[i-1]*2+1;
// print_char('0' + test_buf[i], default_color);
// }
// std::string s = "cxxhello world";
std::basic_string<char, std::char_traits<char>, kallocator<char>> s = "cxx hello world";
print(s.c_str());
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment