Compare commits

...

3 Commits

16 changed files with 262 additions and 1 deletions

View File

@ -1 +1,3 @@
add_subdirectory(libc)
add_subdirectory(libcxx)
add_subdirectory(mammoth)

15
lib/libc/CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
add_library(libc STATIC
src/malloc.cpp
)
target_include_directories(libc
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(libc
zion_lib
)
set_target_properties(libc PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -mgeneral-regs-only")

View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
typedef uint64_t size_t;

View File

@ -0,0 +1,5 @@
#pragma once
#include "stddef.h"
void* malloc(size_t size);

44
lib/libc/src/malloc.cpp Normal file
View File

@ -0,0 +1,44 @@
#include <zcall.h>
#include "stdlib.h"
namespace {
class NaiveAllocator {
public:
constexpr static uint64_t kSize = 0x4000;
NaiveAllocator() {}
bool is_init() { return next_addr_ != 0; }
void Init() {
uint64_t vmmo_cap;
uint64_t err = ZMemoryObjectCreate(kSize, &vmmo_cap);
if (err != 0) {
ZProcessExit(err);
}
err = ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, vmmo_cap, &next_addr_);
max_addr_ = next_addr_ + kSize;
}
void* Allocate(size_t size) {
uint64_t addr = next_addr_;
next_addr_ += size;
if (next_addr_ >= max_addr_) {
return 0;
}
return reinterpret_cast<void*>(addr);
}
private:
uint64_t next_addr_ = 0;
uint64_t max_addr_ = 0;
};
NaiveAllocator gAlloc;
} // namespace
void* malloc(size_t size) {
if (!gAlloc.is_init()) {
gAlloc.Init();
}
return gAlloc.Allocate(size);
}

15
lib/libcxx/CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
add_library(libcxx STATIC
src/new.cpp
)
target_include_directories(libcxx
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(libcxx
libc
zion_lib
)
set_target_properties(libcxx PROPERTIES
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -mgeneral-regs-only")

View File

@ -0,0 +1,34 @@
/* vim: syntax=cpp */
#pragma once
#include "cstdint"
namespace std {
using ptrdiff_t = uint64_t;
using size_t = uint64_t;
// FIXME: I don't understand what this does.
using max_align_t = uint64_t;
using nullptr_t = decltype(nullptr);
enum class byte : unsigned char {};
// byte type operations
template<class IntType>
constexpr byte& operator<<=(byte& b, IntType shift) noexcept;
template<class IntType>
constexpr byte operator<<(byte b, IntType shift) noexcept;
template<class IntType>
constexpr byte& operator>>=(byte& b, IntType shift) noexcept;
template<class IntType>
constexpr byte operator>>(byte b, IntType shift) noexcept;
constexpr byte& operator|=(byte& l, byte r) noexcept;
constexpr byte operator|(byte l, byte r) noexcept;
constexpr byte& operator&=(byte& l, byte r) noexcept;
constexpr byte operator&(byte l, byte r) noexcept;
constexpr byte& operator^=(byte& l, byte r) noexcept;
constexpr byte operator^(byte l, byte r) noexcept;
constexpr byte operator~(byte b) noexcept;
template<class IntType>
constexpr IntType to_integer(byte b) noexcept;
}

View File

@ -0,0 +1,5 @@
/* vim: syntax=cpp */
#pragma once
#include <stdint.h>

69
lib/libcxx/include/new Normal file
View File

@ -0,0 +1,69 @@
/* vim: syntax=cpp */
#pragma once
#include "cstddef"
namespace std {
// storage allocation errors
class bad_alloc;
class bad_array_new_length;
struct destroying_delete_t {
explicit destroying_delete_t() = default;
};
inline constexpr destroying_delete_t destroying_delete{};
// global operator new control
enum class align_val_t : size_t {};
struct nothrow_t { explicit nothrow_t() = default; };
extern const nothrow_t nothrow;
using new_handler = void (*)();
new_handler get_new_handler() noexcept;
new_handler set_new_handler(new_handler new_p) noexcept;
// pointer optimization barrier
template<class T> [[nodiscard]] constexpr T* launder(T* p) noexcept;
// hardware interference size
// inline constexpr size_t hardware_destructive_interference_size =
// /* implementation-defined */;
// inline constexpr size_t hardware_constructive_interference_size =
// /* implementation-defined */;
}
// storage allocation and deallocation
[[nodiscard]] void* operator new(std::size_t size);
[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment);
[[nodiscard]] void* operator new(std::size_t size, const std::nothrow_t&) noexcept;
[[nodiscard]] void* operator new(std::size_t size, std::align_val_t alignment,
const std::nothrow_t&) noexcept;
void operator delete(void* ptr) noexcept;
void operator delete(void* ptr, std::size_t size) noexcept;
void operator delete(void* ptr, std::align_val_t alignment) noexcept;
void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept;
void operator delete(void* ptr, const std::nothrow_t&) noexcept;
void operator delete(void* ptr, std::align_val_t alignment,
const std::nothrow_t&) noexcept;
[[nodiscard]] void* operator new[](std::size_t size);
[[nodiscard]] void* operator new[](std::size_t size, std::align_val_t alignment);
[[nodiscard]] void* operator new[](std::size_t size, const std::nothrow_t&) noexcept;
[[nodiscard]] void* operator new[](std::size_t size, std::align_val_t alignment,
const std::nothrow_t&) noexcept;
void operator delete[](void* ptr) noexcept;
void operator delete[](void* ptr, std::size_t size) noexcept;
void operator delete[](void* ptr, std::align_val_t alignment) noexcept;
void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept;
void operator delete[](void* ptr, const std::nothrow_t&) noexcept;
void operator delete[](void* ptr, std::align_val_t alignment,
const std::nothrow_t&) noexcept;
[[nodiscard]] void* operator new (std::size_t size, void* ptr) noexcept;
[[nodiscard]] void* operator new[](std::size_t size, void* ptr) noexcept;
void operator delete (void* ptr, void*) noexcept;
void operator delete[](void* ptr, void*) noexcept;

6
lib/libcxx/src/new.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "include/new"
#include "stdlib.h"
[[nodiscard]] void* operator new(std::size_t size) { return malloc(size); }
[[nodiscard]] void* operator new[](std::size_t size) { return malloc(size); }

View File

@ -20,6 +20,7 @@ add_executable(test2
test2.cpp)
target_link_libraries(test2
libcxx
mammoth_lib)
set_target_properties(test2

View File

@ -1,6 +1,7 @@
#include <mammoth/channel.h>
#include <mammoth/debug.h>
#include <mammoth/thread.h>
#include <stdlib.h>
void thread_entry(void* a) {
dbgln("In thread");
@ -18,7 +19,7 @@ int main(uint64_t bootstrap_cap) {
Thread t2(thread_entry, b);
uint64_t size = 10;
char buff[10];
char* buff = new char[size];
Channel c1;
c1.adopt_cap(bootstrap_cap);
check(c1.ReadStr(buff, &size));

View File

@ -4,6 +4,7 @@
#include "common/port.h"
#include "debug/debug.h"
#include "memory/kernel_heap.h"
#include "scheduler/scheduler.h"
#define IDT_INTERRUPT_GATE 0x8E
@ -132,6 +133,9 @@ extern "C" void isr_timer();
extern "C" void interrupt_timer(InterruptFrame*) {
cnt++;
if (cnt % 20 == 0) {
if (cnt == 20) {
KernelHeap::DumpDistribution();
}
dbgln("timer: %us", cnt * 50 / 1000);
}
outb(PIC1_COMMAND, PIC_EOI);

View File

@ -3,6 +3,8 @@
#include "debug/debug.h"
#include "memory/paging_util.h"
#define K_HEAP_DEBUG 0
namespace {
static KernelHeap* gKernelHeap = nullptr;
@ -24,12 +26,43 @@ void* KernelHeap::Allocate(uint64_t size) {
if (next_addr_ + size >= upper_bound_) {
panic("Kernel Heap Overrun");
}
#if K_HEAP_DEBUG
RecordSize(size);
#endif
EnsureResident(next_addr_, size);
uint64_t address = next_addr_;
next_addr_ += size;
return reinterpret_cast<void*>(address);
}
void KernelHeap::DumpDistribution() {
#if K_HEAP_DEBUG
uint64_t* distributions = gKernelHeap->distributions;
dbgln("<=4B: %u", distributions[0]);
dbgln("<=8B: %u", distributions[1]);
dbgln("<=16B: %u", distributions[2]);
dbgln("<=32B: %u", distributions[3]);
dbgln("<=64B: %u", distributions[4]);
dbgln("<=128B: %u", distributions[5]);
dbgln("<=256B: %u", distributions[6]);
dbgln("<=512B: %u", distributions[7]);
dbgln("<=1KiB: %u", distributions[8]);
dbgln("<=2KiB: %u", distributions[9]);
dbgln("<=4KiB: %u", distributions[10]);
dbgln("> 4KiB: %u", distributions[11]);
#endif
}
void KernelHeap::RecordSize(uint64_t size) {
size >>= 3;
uint64_t index = 0;
while (size && index < 11) {
size >>= 1;
index++;
}
distributions[index]++;
}
void* operator new(uint64_t size) { return GetKernelHeap().Allocate(size); }
void* operator new[](uint64_t size) { return GetKernelHeap().Allocate(size); }

View File

@ -8,7 +8,26 @@ class KernelHeap {
void* Allocate(uint64_t size);
static void DumpDistribution();
private:
uint64_t next_addr_;
uint64_t upper_bound_;
// Distribution collection for the purpose of investigating a slab allocator.
// 0: 0-4B
// 1: 4B-8B
// 2: 8B-16B
// 3: 16B-32B
// 4: 32B-64B
// 5: 64B-128B
// 6: 128B-256B
// 7: 256B-512B
// 8: 512B-1KiB
// 9: 1KiB-2KiB
// 10: 2KiB-4KiB
// 11: 4KiB+
uint64_t distributions[12];
void RecordSize(uint64_t size);
};

View File

@ -40,6 +40,9 @@ extern "C" void zion() {
dbgln("[boot] Loading sys init program.");
LoadInitProgram();
dbgln("[boot] Allocs during boot:");
heap.DumpDistribution();
dbgln("[boot] Init finished, yielding.");
gScheduler->Enable();
gScheduler->Yield();