aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2025-02-27 09:21:43 +0100
committerFabian Imhof <fabian.imhof@ost.ch>2025-02-27 09:21:43 +0100
commit3fb836101a2032e93f7b82c924ce208d7377a5ea (patch)
tree52f9aa1f5316b9938e74f43637c0641803fda01a /arch/x86_64
parentcd42c21f2460751428b3e1b4ae07ea0b924967bc (diff)
parent2f1f0fa8b0dc1893219be68ab8bf653b5d6349fb (diff)
downloadteachos-3fb836101a2032e93f7b82c924ce208d7377a5ea.tar.xz
teachos-3fb836101a2032e93f7b82c924ce208d7377a5ea.zip
Merge branch 'feat_new_delete_override' into 'develop_ba'
new delete override See merge request teachos/kernel!4
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/CMakeLists.txt8
-rw-r--r--arch/x86_64/include/arch/memory/heap/bump_allocator.hpp21
-rw-r--r--arch/x86_64/include/arch/memory/heap/concept.hpp22
-rw-r--r--arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp82
-rw-r--r--arch/x86_64/include/arch/memory/heap/heap_allocator.hpp43
-rw-r--r--arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp26
-rw-r--r--arch/x86_64/include/arch/memory/heap/memory_block.hpp1
-rw-r--r--arch/x86_64/include/arch/memory/paging/page_entry.hpp3
-rw-r--r--arch/x86_64/include/arch/stl/shared_pointer.hpp120
-rw-r--r--arch/x86_64/include/arch/stl/unique_pointer.hpp68
-rw-r--r--arch/x86_64/include/arch/stl/vector.hpp193
-rw-r--r--arch/x86_64/src/boot/boot.s2
-rw-r--r--arch/x86_64/src/kernel/main.cpp30
-rw-r--r--arch/x86_64/src/memory/cpu/control_register.cpp8
-rw-r--r--arch/x86_64/src/memory/heap/bump_allocator.cpp4
-rw-r--r--arch/x86_64/src/memory/heap/global_heap_allocator.cpp78
-rw-r--r--arch/x86_64/src/memory/heap/linked_list_allocator.cpp41
-rw-r--r--arch/x86_64/src/memory/main.cpp2
18 files changed, 653 insertions, 99 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index c5624d8..e9f8d5f 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -59,6 +59,14 @@ target_sources("_memory" PRIVATE
"src/memory/heap/bump_allocator.cpp"
"src/memory/heap/memory_block.cpp"
"src/memory/heap/linked_list_allocator.cpp"
+ "src/memory/heap/global_heap_allocator.cpp"
+)
+
+#[============================================================================[
+# The Shared Library
+#]============================================================================]
+
+target_sources("_shared" PRIVATE
"src/shared/mutex.cpp"
)
diff --git a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp
index 545b72f..011f45c 100644
--- a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp
+++ b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp
@@ -1,6 +1,8 @@
#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP
#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_BUMP_ALLOCATOR_HPP
+#include "arch/memory/heap/heap_allocator.hpp"
+
#include <atomic>
#include <cstdint>
@@ -10,7 +12,7 @@ namespace teachos::arch::memory::heap
* @brief Simple heap allocator, which allocates linearly and leaks all allocated memory, because it does not really
* deallocate anything.
*/
- struct bump_allocator
+ struct bump_allocator : heap_allocator
{
/**
* @brief Constructor.
@@ -26,23 +28,14 @@ namespace teachos::arch::memory::heap
// Nothing to do
}
- /**
- * @brief Allocates the specified amount of memory in the heap.
- *
- * @param size Amount of memory to allocate.
- * @return Address of the first byte to the allocated area
- */
- auto allocate(std::size_t size) -> void *;
+ auto allocate(std::size_t size) -> void * override;
/**
- * @brief Deallocates heap memory at the specified location.
- *
- * @note Simply does nothing, because this allocator leaks all memory.
+ * @copybrief heap_allocator::deallocate
*
- * @param pointer Pointer to the location which should be deallocated.
- * @param size Size of the underlying memory area we want to deallocate.
+ * @note Simply does nothing, because this allocator leaks all memory
*/
- auto deallocate(void * pointer, std::size_t size) -> void;
+ auto deallocate(void * pointer) noexcept -> void override;
private:
std::size_t heap_start; ///< Start of the allocatable heap area
diff --git a/arch/x86_64/include/arch/memory/heap/concept.hpp b/arch/x86_64/include/arch/memory/heap/concept.hpp
deleted file mode 100644
index e22e35f..0000000
--- a/arch/x86_64/include/arch/memory/heap/concept.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP
-
-#include <concepts>
-
-namespace teachos::arch::memory::heap
-{
- std::size_t constexpr HEAP_START = 0x100000000;
- std::size_t constexpr HEAP_SIZE = 100 * 1024;
-
- /**
- * @brief Heap allocator concept required for allocating and managing free space on the heap.
- */
- template<typename T>
- concept HeapAllocator = requires(T t, uint8_t * pointer, std::size_t size) {
- { t.allocate(size) } -> std::same_as<uint8_t *>;
- { t.deallocate(pointer, size) } -> std::same_as<void>;
- };
-
-} // namespace teachos::arch::memory::heap
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_CONCEPT_HPP
diff --git a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp
new file mode 100644
index 0000000..dff837e
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp
@@ -0,0 +1,82 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP
+
+#include "arch/memory/heap/heap_allocator.hpp"
+
+namespace teachos::arch::memory::heap
+{
+ /**
+ * @brief Possible types that should be constructed by the register_heap_allocator factory method.
+ * Creates the underlying heap allocator instance that is then used by all global allocations using new and delete
+ */
+ enum class heap_allocator_type : uint8_t
+ {
+ NONE, ///< Don't use any heap allocation implementation, this will result in all calls of new and delte halting
+ ///< further execution of the kernel
+ BUMP, ///< Use the bump allocator as the heap allocation implementation, be aware that using this allocator leaks
+ ///< memory, because there is no delete implementation
+ LINKED_LIST ///< Use the linked list allocator as the heap implementation, recommended because it does not leak
+ ///< memory and
+ };
+
+ /**
+ * @brief Global instance of a heap allocator implementation created by the factory method pattern @see
+ * https://refactoring.guru/design-patterns/factory-method for more information.
+ *
+ * @note Can only be registered once and only once the kernel and the heap part of the kernel has been remapped
+ * successfully. If the instance is created before than the device will abort, because it acceses unmapped memory
+ * areas.
+ */
+ struct global_heap_allocator
+ {
+ /**
+ * @brief Registers the heap allocation implementation that should be used by the global heap allocator.
+ * Meaning all future calls to the global new or delete will be forwarded to the allocate and deallocate calls of
+ * the underlying heap allocation implementation
+ *
+ * @param new_type Type of the heap allocation implementation we want to instantiate
+ */
+ static auto register_heap_allocator(heap_allocator_type new_type) -> void;
+
+ /**
+ * @brief Allocates the given amount of memory and returns the pointer to the start of the allocatable memory area.
+ * Simply forwards the call to the allocate method of the registered heap_allocation implementation
+ *
+ * @param size Amount of bytes that should be allocated
+ * @return void* Pointer to the start of the allocatable memory area
+ */
+ static auto allocate(std::size_t size) -> void *;
+
+ /**
+ * @brief Deallocated all memory associated with the memory area starting from the given pointer address.
+ * Simply forwards the call to the deallocate method of the registered heap_allocation implementation
+ *
+ * @param pointer Previously allocated memory area, that should now be freed
+ */
+ static auto deallocate(void * pointer) noexcept -> void;
+
+ private:
+ static heap_allocator * allocator_instance; ///< Instance used to actually allocate and deallocate
+
+ /**
+ * @brief Either returns the previously registered heap allocated or halts furthere execution
+ *
+ * @return Reference to the registered heap allocation
+ */
+ static auto get() -> heap_allocator &;
+ };
+} // namespace teachos::arch::memory::heap
+
+auto operator new(std::size_t size) -> void *;
+
+auto operator delete(void * pointer) noexcept -> void;
+
+auto operator delete(void * pointer, std::size_t size) noexcept -> void;
+
+auto operator new[](std::size_t size) -> void *;
+
+auto operator delete[](void * pointer) noexcept -> void;
+
+auto operator delete[](void * pointer, std::size_t size) noexcept -> void;
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_GLOBAL_HEAP_ALLOCATOR_HPP
diff --git a/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp
new file mode 100644
index 0000000..6aed3d8
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp
@@ -0,0 +1,43 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_HEAP_ALLOCATOR_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_HEAP_ALLOCATOR_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::memory::heap
+{
+ std::size_t constexpr HEAP_START = 0x100000000;
+ std::size_t constexpr HEAP_SIZE = 100 * 1024;
+
+ /**
+ * @brief Heap allocator interface containing methods required to allocate and deallocate heap memory areas
+ */
+ struct heap_allocator
+ {
+ /**
+ * @brief Virtual default destructor, created to ensure that if a pointer to this class is used and deleted, we will
+ * also call the derived base class destructor. Deleting a base class destructor that does not have a virtual
+ * destructor is undefined behaviour, because the derived class destructor originally instantiated with new is never
+ * called. This can cause potential memory leaks, because derived classes can not clean up their internal members as
+ * expected and instead simply leak them
+ */
+ virtual ~heap_allocator() {}
+
+ /**
+ * @brief Allocates the given amount of memory and returns the pointer to the start of the allocatable memory area
+ *
+ * @param size Amount of bytes that should be allocated
+ * @return void* Pointer to the start of the allocatable memory area
+ */
+ virtual auto allocate(std::size_t size) -> void * = 0;
+
+ /**
+ * @brief Deallocates all memory associated with the given pointer address.
+ * Simply deallocates the amount of memory created with the corresponding call to allocate
+ *
+ * @param pointer Previously allocated memory area, that should now be freed
+ */
+ virtual auto deallocate(void * pointer) noexcept -> void = 0;
+ };
+} // namespace teachos::arch::memory::heap
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_HEAP_ALLOCATOR_HPP
diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp
index 06b21bb..df9e370 100644
--- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp
+++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp
@@ -1,6 +1,7 @@
#ifndef TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP
#define TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP
+#include "arch/memory/heap/heap_allocator.hpp"
#include "arch/memory/heap/memory_block.hpp"
#include "arch/shared/mutex.hpp"
@@ -10,7 +11,7 @@ namespace teachos::arch::memory::heap
* @brief Sorted by address list of memory holes (free memory). Uses free holes itself to save the information,
* containing the size and pointer to the next hole. Resulting in a singly linked list.
*/
- struct linked_list_allocator
+ struct linked_list_allocator : heap_allocator
{
/**
* @brief Constructor.
@@ -21,7 +22,7 @@ namespace teachos::arch::memory::heap
linked_list_allocator(std::size_t heap_start, std::size_t heap_end);
/**
- * @brief Allocates the specified amount of memory in the heap.
+ * @copybrief heap_allocator::allocate
*
* @note The specified size is used to find a free memory block with the exact same size, meaning we can remove that
* free memory block from the free list and simply return its address. Or it has to be big enough to hold the size
@@ -31,21 +32,10 @@ namespace teachos::arch::memory::heap
* they received more memory than wanted. Therefore the memory would simply be unused and because it is neither
* allocated nor deallocated would never be indexed by the free memory list. We would therefore permanently loose
* that memory, to prevent that allocation into free memory blocks like that are impossible.
- *
- * @param size Amount of memory to allocate.
- * @return Address of the first byte to the allocated area
*/
- auto allocate(std::size_t size) -> void *;
+ auto allocate(std::size_t size) -> void * override;
- /**
- * @brief Deallocates heap memory at the specified location.
- *
- * @note Simply does nothing, because this allocator leaks all memory.
- *
- * @param pointer Pointer to the location which should be deallocated.
- * @param size Size of the underlying memory area we want to deallocate.
- */
- auto deallocate(void * pointer, std::size_t size) -> void;
+ auto deallocate(void * pointer) noexcept -> void override;
private:
/**
@@ -78,8 +68,8 @@ namespace teachos::arch::memory::heap
*
* @return Previous start address of the memory block we just split, because it can now be used for the allocation.
*/
- auto split_free_memory_block(memory_block * previous_block, memory_block * current_block,
- std::size_t size) -> void *;
+ auto split_free_memory_block(memory_block * previous_block, memory_block * current_block, std::size_t size)
+ -> void *;
/**
* @brief Removes a free memory block from the free list and returns its address so the caller can allocate into it.
@@ -127,6 +117,8 @@ namespace teachos::arch::memory::heap
shared::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once.
};
+ extern linked_list_allocator kernel_heap;
+
} // namespace teachos::arch::memory::heap
#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_LINKED_LIST_ALLOCATOR_HPP
diff --git a/arch/x86_64/include/arch/memory/heap/memory_block.hpp b/arch/x86_64/include/arch/memory/heap/memory_block.hpp
index b9a2254..e1cd288 100644
--- a/arch/x86_64/include/arch/memory/heap/memory_block.hpp
+++ b/arch/x86_64/include/arch/memory/heap/memory_block.hpp
@@ -32,7 +32,6 @@ namespace teachos::arch::memory::heap
///< size variable and the pointer to the next hole.
memory_block * next; ///< Optional pointer to the next free memory, holds nullptr if there is none.
};
-
} // namespace teachos::arch::memory::heap
#endif // TEACHOS_ARCH_X86_64_MEMORY_HEAP_MEMORY_BLOCK_HPP
diff --git a/arch/x86_64/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/include/arch/memory/paging/page_entry.hpp
index 876ea3c..1de31b5 100644
--- a/arch/x86_64/include/arch/memory/paging/page_entry.hpp
+++ b/arch/x86_64/include/arch/memory/paging/page_entry.hpp
@@ -49,14 +49,13 @@ namespace teachos::arch::memory::paging
explicit entry(uint64_t flags);
/**
- * @brief Converts the given elf section flags into the corresponding correct entry flags.
+ * @brief Creates a new entry converting the given elf section flags into the corresponding correct entry flags.
*
* @note Enables us to set the correct flags on a entry depending on which elf section it is contained in. For
* example entries of .text sections should be executable and read only or entries of .data sections should be
* writable but not executable.
*
* @param elf_flags Elf section flags we want to convert into entry flags.
- * @return Entry that has the corresponding bit flags set.
*/
explicit entry(multiboot::elf_section_flags elf_flags);
diff --git a/arch/x86_64/include/arch/stl/shared_pointer.hpp b/arch/x86_64/include/arch/stl/shared_pointer.hpp
new file mode 100644
index 0000000..79a9f82
--- /dev/null
+++ b/arch/x86_64/include/arch/stl/shared_pointer.hpp
@@ -0,0 +1,120 @@
+#ifndef TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP
+#define TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP
+
+namespace teachos::arch::stl
+{
+ template<typename T>
+ struct shared_pointer
+ {
+ explicit shared_pointer(T * pointer = nullptr)
+ : pointer(pointer)
+ , ref_count(new std::atomic<int>(pointer != nullptr ? 1 : 0))
+ {
+ }
+
+ shared_pointer(const shared_pointer & other)
+ : pointer(other.pointer)
+ , ref_count(other.ref_count)
+ {
+ if (pointer != nullptr)
+ {
+ ++(*ref_count);
+ }
+ }
+
+ shared_pointer(shared_pointer && other) noexcept
+ : pointer(other.pointer)
+ , ref_count(other.ref_count)
+ {
+ other.pointer = nullptr;
+ other.ref_count = nullptr;
+ }
+
+ shared_pointer & operator=(const shared_pointer & other)
+ {
+ if (this != &other)
+ {
+ cleanup();
+ pointer = other.pointer;
+ ref_count = other.ref_count;
+
+ if (pointer != nullptr)
+ {
+ ++(*ref_count);
+ }
+ }
+
+ return *this;
+ }
+
+ shared_pointer & operator=(shared_pointer && other) noexcept
+ {
+ if (this != &other)
+ {
+ cleanup();
+ pointer = other.pointer;
+ ref_count = other.ref_count;
+ other.pointer = nullptr;
+ other.ref_count = nullptr;
+ }
+
+ return *this;
+ }
+
+ ~shared_pointer() { cleanup(); }
+
+ void cleanup()
+ {
+ if (pointer != nullptr && ref_count != nullptr && --(*ref_count) == 0)
+ {
+ delete pointer;
+ delete ref_count;
+ }
+ }
+
+ void reset(T * p = nullptr)
+ {
+ cleanup();
+ pointer = p;
+ ref_count = new std::atomic<int>(p != nullptr ? 1 : 0);
+ }
+
+ void swap(shared_pointer & other)
+ {
+ std::swap(pointer, other.pointer);
+ std::swap(ref_count, other.ref_count);
+ }
+
+ T & operator*() const { return *pointer; }
+
+ T * operator->() const { return pointer; }
+
+ T * get() const { return pointer; }
+
+ int use_count() const
+ {
+ if (pointer != nullptr)
+ {
+ return *ref_count;
+ }
+
+ return 0;
+ }
+
+ bool unique() const { return use_count() == 1; }
+
+ explicit operator bool() const { return pointer != nullptr; }
+
+ private:
+ T * pointer;
+ std::atomic<int> * ref_count;
+ };
+
+ template<typename T, typename... Args>
+ shared_pointer<T> make_shared(Args &&... args)
+ {
+ return shared_pointer<T>(new T(std::forward<Args>(args)...));
+ }
+} // namespace teachos::arch::stl
+
+#endif // TEACHOS_ARCH_X86_64_STL_SHARED_POINTER_HPP \ No newline at end of file
diff --git a/arch/x86_64/include/arch/stl/unique_pointer.hpp b/arch/x86_64/include/arch/stl/unique_pointer.hpp
new file mode 100644
index 0000000..0ec3c38
--- /dev/null
+++ b/arch/x86_64/include/arch/stl/unique_pointer.hpp
@@ -0,0 +1,68 @@
+#ifndef TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP
+#define TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP
+
+namespace teachos::arch::stl
+{
+ template<typename T>
+ struct unique_pointer
+ {
+ explicit unique_pointer(T * ptr = nullptr)
+ : pointer(ptr)
+ {
+ }
+
+ ~unique_pointer() { delete pointer; }
+
+ unique_pointer(const unique_pointer &) = delete;
+ unique_pointer & operator=(const unique_pointer &) = delete;
+
+ unique_pointer(unique_pointer && other) noexcept
+ : pointer(other.pointer)
+ {
+ other.pointer = nullptr;
+ }
+
+ unique_pointer & operator=(unique_pointer && other) noexcept
+ {
+ if (this != &other)
+ {
+ delete pointer;
+ pointer = other.pointer;
+ other.pointer = nullptr;
+ }
+ return *this;
+ }
+
+ T & operator*() const { return *pointer; }
+
+ T * operator->() const { return pointer; }
+
+ T * get() const { return pointer; }
+
+ T * release()
+ {
+ T * temp = pointer;
+ pointer = nullptr;
+ return temp;
+ }
+
+ void reset(T * ptr = nullptr)
+ {
+ delete pointer;
+ pointer = ptr;
+ }
+
+ void swap(unique_pointer & other) { std::swap(pointer, other.pointer); }
+
+ private:
+ T * pointer;
+ };
+
+ template<typename T, typename... Args>
+ unique_pointer<T> make_unique(Args &&... args)
+ {
+ return unique_pointer<T>(new T(std::forward<Args>(args)...));
+ }
+} // namespace teachos::arch::stl
+
+#endif // TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP \ No newline at end of file
diff --git a/arch/x86_64/include/arch/stl/vector.hpp b/arch/x86_64/include/arch/stl/vector.hpp
new file mode 100644
index 0000000..62be704
--- /dev/null
+++ b/arch/x86_64/include/arch/stl/vector.hpp
@@ -0,0 +1,193 @@
+#ifndef TEACHOS_ARCH_X86_64_STL_VECTOR_HPP
+#define TEACHOS_ARCH_X86_64_STL_VECTOR_HPP
+
+#include "arch/exception_handling/panic.hpp"
+#include "arch/shared/container.hpp"
+#include "arch/shared/contiguous_pointer_iterator.hpp"
+
+#include <algorithm>
+
+namespace teachos::arch::stl
+{
+ /**
+ * @brief Custom vector implementation mirroring the std::vector to allow for the usage of STL functionality with our
+ * custom memory management
+ *
+ * @tparam T Element the vector instance should contain
+ */
+ template<typename T>
+ struct vector
+ {
+ /**
+ * @brief Defaulted constructor. Initalizes empty vector
+ */
+ vector() = default;
+
+ /**
+ * @brief Constructs data with the given amount of elements containg the given value or alterantively the default
+ * constructed value
+ *
+ * @param capacity Amount of elements we want to create and set the given value for
+ * @param initial Inital value of all elements in the underlying data array
+ */
+ vector(size_t capacity, T initial = T{})
+ : capacity(capacity)
+ , size(capacity)
+ , data(new T[capacity]{})
+ {
+ auto const begin = data;
+ auto const end = data + size;
+ vector_container container{begin, end};
+ std::ranges::fill(container, inital);
+ }
+
+ /**
+ * @brief Copy constructor
+ *
+ * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all
+ * elements from it
+ *
+ * @param other Other instance of vector we want to copy the data from
+ */
+ vector(vector<T> const & other)
+ : size(size)
+ , capacity(capacity)
+ {
+ delete[] data;
+ data = new T[capacity]{};
+
+ auto const begin = other.data;
+ auto const end = other.data + size;
+ vector_container container{begin, end};
+ std::ranges::copy(container, data);
+ }
+
+ /**
+ * @brief Copy assignment operator
+ *
+ * @note Allocates underlying data container with the same capacity as vector we are copying from and copies all
+ * elements from it
+ *
+ * @param other Other instance of vector we want to copy the data from
+ * @return Newly created copy
+ */
+ vector<T> & operator=(vector<T> const & other)
+ {
+ delete[] data;
+ size = other.size();
+ capacity = other.capacity();
+ data = new T[capacity]{};
+
+ auto const begin = other.data;
+ auto const end = other.data + size;
+ vector_container container{begin, end};
+ std::ranges::copy(container, data);
+ return *this;
+ }
+
+ /**
+ * @brief Destructor
+ */
+ ~vector() { delete[] data; }
+
+ /**
+ * @brief Amount of elements currently contained in this vector, will fill up until we have reached the capacity. If
+ * that is the case the capacity is increased automatically
+ *
+ * @return Current amount of elements
+ */
+ size_t size() const { return size; }
+
+ /**
+ * @brief Amount of space the vector currently has, can be different than the size, because we allocate more than we
+ * exactly require to decrease the amount of allocations and deallocation to improve speed
+ *
+ * @return Current amount of space the vector has for elements
+ */
+ size_t capacity() const { return capacity; }
+
+ /**
+ * @brief Array indexing operator. Allowing to access element at the given index
+ *
+ * @note Does not do any bounds checks use at() for that
+ *
+ * @param index Index we want to access elements at
+ * @return Reference to the underlying element
+ */
+ T & operator[](size_t index) { return data[index]; }
+
+ /**
+ * @brief Array indexing operator. Allowing to access element at the given index
+ *
+ * @note Ensures we do not access element outside of the bounds of the array, if we do further execution is halted
+ *
+ * @param index Index we want to access elements at
+ * @return Reference to the underlying element
+ */
+ T & at(size_t index)
+ {
+ if (index >= size)
+ {
+ exception_handling::panic("[Vector] Attempted to read element at invalid index");
+ }
+ return this->operator[](size);
+ }
+
+ void push_back(T & const element) {}
+
+ void emplace_back(T && const element)
+ {
+ // If no cacacity, increase capacity
+ if (size == capacity)
+ {
+ reserve(capacity * 2);
+ }
+
+ data[size] = element;
+ size++;
+ }
+
+ void pop_back()
+ {
+ if (size <= 0)
+ {
+ exception_handling::panic("[Vector] Attempted to pop back last element of already empty vector");
+ }
+ size--;
+ }
+
+ T & front() { return *data; }
+
+ T & back() { return *(data + size); }
+
+ void reserve(size_t new_capacity)
+ {
+ if (new_capacity < size)
+ {
+ // Creating new array with less capacity than is required to keep all current elements makes no sense
+ return;
+ }
+
+ T * temp = new T[new_capacity];
+
+ auto const begin = other.data;
+ auto const end = other.data + capacity;
+ vector_container container{begin, end};
+ std::ranges::copy(container, temp);
+
+ delete[] data;
+ capacity = new_capacity;
+ data = temp;
+ }
+
+ private:
+ T * data = {}; ///< Pointer to the first element in the underlying data container
+ size_t capacity = {}; ///< Amount of space for elements in the underlying data container
+ size_t size = {}; ///< Amount of elements in the underlying data container
+
+ typedef shared::container<shared::contiguous_pointer_iterator<T>> vector_container;
+ };
+
+} // namespace teachos::arch::stl
+
+#endif // TEACHOS_ARCH_X86_64_STL_VECTOR_HPP
diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s
index 8d27ea1..2197dce 100644
--- a/arch/x86_64/src/boot/boot.s
+++ b/arch/x86_64/src/boot/boot.s
@@ -197,8 +197,10 @@ _start:
call enable_paging
call enable_sse
+ cli // Clears the interrupt flag during the GDT setup
lgdt (global_descriptor_table_pointer)
jmp $global_descriptor_table_code,$_transition_to_long_mode
+ // The interrupt flag is set in cpp after setting up the GDT
call halt
diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp
index 681f960..472aed5 100644
--- a/arch/x86_64/src/kernel/main.cpp
+++ b/arch/x86_64/src/kernel/main.cpp
@@ -1,8 +1,7 @@
#include "arch/kernel/main.hpp"
#include "arch/memory/heap/bump_allocator.hpp"
-#include "arch/memory/heap/concept.hpp"
-#include "arch/memory/heap/linked_list_allocator.hpp"
+#include "arch/memory/heap/global_heap_allocator.hpp"
#include "arch/memory/main.hpp"
#include "arch/memory/multiboot/reader.hpp"
#include "arch/video/vga/text.hpp"
@@ -22,12 +21,8 @@ namespace teachos::arch::kernel
auto heap_test() -> void
{
- memory::heap::linked_list_allocator heap_allocator{memory::heap::HEAP_START,
- memory::heap::HEAP_START + memory::heap::HEAP_SIZE};
- auto test = heap_allocator.allocate(1024);
- auto test2 = new (test) memory::multiboot::memory_information{};
- auto test3 = new (static_cast<void *>(static_cast<memory::multiboot::memory_information *>(test) + 1))
- memory::multiboot::memory_information{};
+ auto test2 = new memory::multiboot::memory_information{};
+ auto test3 = new memory::multiboot::memory_information{};
auto test4 = *test2;
auto test5 = *test3;
test4.kernel_end = 5000;
@@ -42,18 +37,11 @@ namespace teachos::arch::kernel
test2->kernel_end = 2000;
test2->kernel_start = 1000;
test2->multiboot_start = 2000;
- heap_allocator.deallocate(test, 1024);
+ delete test2;
+ delete test3;
- auto test9 = heap_allocator.allocate(1024);
- auto test10 = heap_allocator.allocate(1024);
- auto test11 = heap_allocator.allocate(1024);
- heap_allocator.deallocate(test9, 1024);
- auto test12 = heap_allocator.allocate(1024);
- auto test13 = heap_allocator.allocate(1024);
- heap_allocator.deallocate(test11, 1024);
- heap_allocator.deallocate(test10, 1024);
- heap_allocator.deallocate(test13, 1024);
- heap_allocator.deallocate(test12, 1024);
+ auto test9 = new int(50);
+ delete test9;
}
auto main() -> void
@@ -64,8 +52,10 @@ namespace teachos::arch::kernel
video::vga::text::newline();
memory::initialize_memory_management();
-
// stack_overflow_test(0);
+
+ memory::heap::global_heap_allocator::register_heap_allocator(memory::heap::heap_allocator_type::LINKED_LIST);
+
heap_test();
}
} // namespace teachos::arch::kernel
diff --git a/arch/x86_64/src/memory/cpu/control_register.cpp b/arch/x86_64/src/memory/cpu/control_register.cpp
index 298874f..7ee88b5 100644
--- a/arch/x86_64/src/memory/cpu/control_register.cpp
+++ b/arch/x86_64/src/memory/cpu/control_register.cpp
@@ -1,6 +1,6 @@
#include "arch/memory/cpu/control_register.hpp"
-#include "arch/exception_handling/assert.hpp"
+#include "arch/exception_handling/panic.hpp"
#include <type_traits>
@@ -24,8 +