diff --git a/src/kernel/vm_space.cpp b/src/kernel/vm_space.cpp index f1052d0..1e8e2a2 100644 --- a/src/kernel/vm_space.cpp +++ b/src/kernel/vm_space.cpp @@ -7,7 +7,8 @@ #include "vm_space.h" // The initial memory for the array of areas for the kernel space -static uint64_t kernel_areas[16]; +constexpr size_t num_kernel_areas = 8; +static uint64_t kernel_areas[num_kernel_areas * 2]; int vm_space::area::compare(const vm_space::area &o) const @@ -28,7 +29,7 @@ vm_space::area::operator==(const vm_space::area &o) const vm_space::vm_space(page_table *p) : m_kernel {true}, m_pml4 {p}, - m_areas {reinterpret_cast(kernel_areas), 0, 8} + m_areas {reinterpret_cast(kernel_areas), 0, num_kernel_areas} {} vm_space::vm_space() : diff --git a/src/libraries/kutil/heap_allocator.cpp b/src/libraries/kutil/heap_allocator.cpp index cdafd24..7dd66d2 100644 --- a/src/libraries/kutil/heap_allocator.cpp +++ b/src/libraries/kutil/heap_allocator.cpp @@ -62,10 +62,13 @@ private: }; -heap_allocator::heap_allocator() : m_next(0), m_size(0) {} +heap_allocator::heap_allocator() : m_start {0}, m_end {0} {} heap_allocator::heap_allocator(uintptr_t start, size_t size) : - m_next(start), m_size(size), m_allocated_size(0) + m_start {start}, + m_end {start+size}, + m_blocks {0}, + m_allocated_size {0} { kutil::memset(m_free, 0, sizeof(m_free)); } @@ -97,6 +100,11 @@ heap_allocator::free(void *p) { if (!p) return; + static constexpr uintptr_t bad_mask = (1 << min_order) - 1; + uintptr_t addr = reinterpret_cast(p); + kassert(addr >= m_start && addr < m_end && !(addr & bad_mask), + "Attempt to free non-heap pointer"); + mem_header *header = reinterpret_cast(p); header -= 1; // p points after the header header->set_used(false); @@ -133,12 +141,12 @@ heap_allocator::ensure_block(unsigned order) if (order == max_order) { size_t bytes = (1 << max_order); - if (bytes <= m_size) { - mem_header *next = reinterpret_cast(m_next); - new (next) mem_header(nullptr, nullptr, order); - get_free(order) = next; - m_next += bytes; - m_size -= bytes; + uintptr_t next = m_start + m_blocks * bytes; + if (next + bytes <= m_end) { + mem_header *nextp = reinterpret_cast(next); + new (nextp) mem_header(nullptr, nullptr, order); + get_free(order) = nextp; + ++m_blocks; } } else { mem_header *orig = pop_free(order + 1); diff --git a/src/libraries/kutil/include/kutil/heap_allocator.h b/src/libraries/kutil/include/kutil/heap_allocator.h index 3c125f8..43b2dab 100644 --- a/src/libraries/kutil/include/kutil/heap_allocator.h +++ b/src/libraries/kutil/include/kutil/heap_allocator.h @@ -23,11 +23,11 @@ public: /// \arg length The amount of memory to allocate, in bytes /// \returns A pointer to the allocated memory, or nullptr if /// allocation failed. - virtual void * allocate(size_t length); + void * allocate(size_t length); /// Free a previous allocation. /// \arg p A pointer previously retuned by allocate() - virtual void free(void *p); + void free(void *p); /// Minimum block size is (2^min_order). Must be at least 6. static const unsigned min_order = 6; @@ -52,8 +52,8 @@ protected: /// \returns A detached block of the given order mem_header * pop_free(unsigned order); - uintptr_t m_next; - size_t m_size; + uintptr_t m_start, m_end; + size_t m_blocks; mem_header *m_free[max_order - min_order + 1]; size_t m_allocated_size; diff --git a/src/libraries/kutil/include/kutil/vector.h b/src/libraries/kutil/include/kutil/vector.h index 9a45d9b..18408cf 100644 --- a/src/libraries/kutil/include/kutil/vector.h +++ b/src/libraries/kutil/include/kutil/vector.h @@ -15,6 +15,7 @@ class vector { using count_t = S; static constexpr count_t min_capacity = 4; + static constexpr count_t cap_mask = static_cast(-1) >> 1; public: /// Default constructor. Creates an empty vector with no capacity. @@ -60,7 +61,7 @@ public: /// static storage. vector(T *data, count_t size, count_t capacity) : m_size(size), - m_capacity(capacity), + m_capacity(capacity | ~cap_mask), m_elements(&data[0]) { } @@ -69,13 +70,19 @@ public: ~vector() { while (m_size) remove(); - kfree(m_elements); + + bool was_static = m_capacity & ~cap_mask; + if (!was_static) + kfree(m_elements); } /// Get the size of the array. - /// \returns The number of elements in the array inline count_t count() const { return m_size; } + /// Get the capacity of the array. This is the amount of space + /// actually allocated. + inline count_t capacity() const { return m_capacity & cap_mask; } + /// Access an element in the array. inline T & operator[] (count_t i) { return m_elements[i]; } @@ -83,19 +90,15 @@ public: inline const T & operator[] (count_t i) const { return m_elements[i]; } /// Get a pointer to the beginning for iteration. - /// \returns A pointer to the beginning of the array T * begin() { return m_elements; } /// Get a pointer to the beginning for iteration. - /// \returns A pointer to the beginning of the array const T * begin() const { return m_elements; } /// Get a pointer to the end for iteration. - /// \returns A pointer to the end of the array T * end() { return m_elements + m_size; } /// Get a pointer to the end for iteration. - /// \returns A pointer to the end of the array const T * end() const { return m_elements + m_size; } /// Add an item onto the array by copying it. @@ -255,7 +258,7 @@ public: /// \arg size Size of the array void ensure_capacity(count_t size) { - if (m_capacity >= size) return; + if (capacity() >= size) return; count_t capacity = (1 << log2(size)); if (capacity < min_capacity) capacity = min_capacity; @@ -267,6 +270,7 @@ public: /// \arg capacity Number of elements to allocate void set_capacity(count_t capacity) { + bool was_static = m_capacity & ~cap_mask; T *new_array = reinterpret_cast(kalloc(capacity * sizeof(T))); count_t size = capacity > m_size ? m_size : capacity; @@ -276,7 +280,8 @@ public: m_size = size; m_capacity = capacity; - kfree(m_elements); + if (!was_static) + kfree(m_elements); m_elements = new_array; }