Compare commits
3 Commits
40b21d9c75
...
d6ba336b83
Author | SHA1 | Date |
---|---|---|
Drew Galbraith | d6ba336b83 | |
Drew Galbraith | dcc05f2741 | |
Drew Galbraith | eb04242a59 |
|
@ -1 +1,3 @@
|
|||
add_subdirectory(libc)
|
||||
add_subdirectory(libcxx)
|
||||
add_subdirectory(mammoth)
|
||||
|
|
|
@ -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")
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t size_t;
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
void* malloc(size_t size);
|
|
@ -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);
|
||||
}
|
|
@ -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")
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/* vim: syntax=cpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
|
@ -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;
|
|
@ -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); }
|
|
@ -20,6 +20,7 @@ add_executable(test2
|
|||
test2.cpp)
|
||||
|
||||
target_link_libraries(test2
|
||||
libcxx
|
||||
mammoth_lib)
|
||||
|
||||
set_target_properties(test2
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue