From 191e7ef3001e422c2f58efe7381d13932e1c1537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 24 Feb 2025 08:40:46 +0000 Subject: Add noexpect to deallocate calls --- arch/x86_64/include/arch/memory/heap/bump_allocator.hpp | 2 +- arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp | 2 +- arch/x86_64/include/arch/memory/heap/heap_allocator.hpp | 2 +- arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp | 2 +- arch/x86_64/src/memory/heap/bump_allocator.cpp | 2 +- arch/x86_64/src/memory/heap/global_heap_allocator.cpp | 2 +- arch/x86_64/src/memory/heap/linked_list_allocator.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) 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 74734af..011f45c 100644 --- a/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/bump_allocator.hpp @@ -35,7 +35,7 @@ namespace teachos::arch::memory::heap * * @note Simply does nothing, because this allocator leaks all memory */ - auto deallocate(void * pointer) -> void override; + 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/global_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp index a1621b5..dff837e 100644 --- a/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp @@ -53,7 +53,7 @@ namespace teachos::arch::memory::heap * * @param pointer Previously allocated memory area, that should now be freed */ - static auto deallocate(void * pointer) -> void; + static auto deallocate(void * pointer) noexcept -> void; private: static heap_allocator * allocator_instance; ///< Instance used to actually allocate and deallocate diff --git a/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp index 01657f2..6aed3d8 100644 --- a/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/heap_allocator.hpp @@ -36,7 +36,7 @@ namespace teachos::arch::memory::heap * * @param pointer Previously allocated memory area, that should now be freed */ - virtual auto deallocate(void * pointer) -> void = 0; + virtual auto deallocate(void * pointer) noexcept -> void = 0; }; } // namespace teachos::arch::memory::heap 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 d53756d..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 @@ -35,7 +35,7 @@ namespace teachos::arch::memory::heap */ auto allocate(std::size_t size) -> void * override; - auto deallocate(void * pointer) -> void override; + auto deallocate(void * pointer) noexcept -> void override; private: /** diff --git a/arch/x86_64/src/memory/heap/bump_allocator.cpp b/arch/x86_64/src/memory/heap/bump_allocator.cpp index a9fb121..df95346 100644 --- a/arch/x86_64/src/memory/heap/bump_allocator.cpp +++ b/arch/x86_64/src/memory/heap/bump_allocator.cpp @@ -42,7 +42,7 @@ namespace teachos::arch::memory::heap } } - auto bump_allocator::deallocate(void * pointer) -> void + auto bump_allocator::deallocate(void * pointer) noexcept -> void { if (pointer) { diff --git a/arch/x86_64/src/memory/heap/global_heap_allocator.cpp b/arch/x86_64/src/memory/heap/global_heap_allocator.cpp index 235c544..c1ca160 100644 --- a/arch/x86_64/src/memory/heap/global_heap_allocator.cpp +++ b/arch/x86_64/src/memory/heap/global_heap_allocator.cpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory::heap auto global_heap_allocator::allocate(std::size_t size) -> void * { return get().allocate(size); } - auto global_heap_allocator::deallocate(void * pointer) -> void { get().deallocate(pointer); } + auto global_heap_allocator::deallocate(void * pointer) noexcept -> void { get().deallocate(pointer); } auto global_heap_allocator::register_heap_allocator(heap_allocator_type new_type) -> void { diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index 9beb466..a824c8a 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -59,7 +59,7 @@ namespace teachos::arch::memory::heap exception_handling::panic("[Linked List Allocator] Out of memory"); } - auto linked_list_allocator::deallocate(void * pointer) -> void + auto linked_list_allocator::deallocate(void * pointer) noexcept -> void { mutex.lock(); -- cgit v1.2.3 From b76fd5fcd04c7541c11c3d9c5b2edf1352d70c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 24 Feb 2025 10:11:26 +0000 Subject: Enable run time and compile time sanitizers to catch more errors --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 12ac210..7d30a2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ add_compile_options( "$<$:-Wextra>" "$<$:-Werror>" "$<$:-pedantic-errors>" + "$<$:-fsanitize=address,leak,bounds,alignment,return,integer-divide-by-zero,vla-bound,null,enum,pointer-overflow>" ) #[============================================================================[ -- cgit v1.2.3 From 2cbaf2d52bd9379e5c6e4a0d018b25d1c882193d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 25 Feb 2025 14:41:03 +0000 Subject: Create inital custom version of c++ vector --- CMakeLists.txt | 8 ++ arch/x86_64/CMakeLists.txt | 7 ++ arch/x86_64/include/arch/stl/vector.hpp | 193 ++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 arch/x86_64/include/arch/stl/vector.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d30a2c..8657cab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,13 @@ add_library("teachos::memory" ALIAS "_memory") add_library("_exception" OBJECT) add_library("teachos::exception" ALIAS "_exception") +#[============================================================================[ +# The Shared Library +#]============================================================================] + +add_library("_shared" OBJECT) +add_library("teachos::shared" ALIAS "_shared") + #[============================================================================[ # The Kernel #]============================================================================] @@ -129,6 +136,7 @@ target_link_libraries("_kernel" PRIVATE "teachos::video" "teachos::memory" "teachos::exception" + "teachos::shared" ) #[============================================================================[ diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 9665846..e9f8d5f 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -60,6 +60,13 @@ target_sources("_memory" PRIVATE "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/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 + +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 + 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 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 & operator=(vector 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> vector_container; + }; + +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_VECTOR_HPP -- cgit v1.2.3 From 462a4e09b1a67562dd1a122936c1ad0fc1771e0e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Feb 2025 07:15:03 +0000 Subject: add smart pointers --- arch/x86_64/include/arch/stl/shared_pointer.hpp | 120 ++++++++++++++++++++++++ arch/x86_64/include/arch/stl/unique_pointer.hpp | 68 ++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 arch/x86_64/include/arch/stl/shared_pointer.hpp create mode 100644 arch/x86_64/include/arch/stl/unique_pointer.hpp 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 + struct shared_pointer + { + explicit shared_pointer(T * pointer = nullptr) + : pointer(pointer) + , ref_count(new std::atomic(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(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 * ref_count; + }; + + template + shared_pointer make_shared(Args &&... args) + { + return shared_pointer(new T(std::forward(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 + 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 + unique_pointer make_unique(Args &&... args) + { + return unique_pointer(new T(std::forward(args)...)); + } +} // namespace teachos::arch::stl + +#endif // TEACHOS_ARCH_X86_64_STL_UNIQUE_POINTER_HPP \ No newline at end of file -- cgit v1.2.3 From dc86ba14f5d9cae44f9922f7a9627369e4a3172e Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Feb 2025 07:49:38 +0000 Subject: remove interrupt.hpp --- arch/x86_64/include/arch/kernel/interrupt.hpp | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 arch/x86_64/include/arch/kernel/interrupt.hpp diff --git a/arch/x86_64/include/arch/kernel/interrupt.hpp b/arch/x86_64/include/arch/kernel/interrupt.hpp deleted file mode 100644 index 521318d..0000000 --- a/arch/x86_64/include/arch/kernel/interrupt.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_KERNEL_INTERRUPT_HPP -#define TEACHOS_ARCH_X86_64_KERNEL_INTERRUPT_HPP - -#include - -namespace teachos::arch::kernel -{ - struct stack_frame - { - std::uint16_t instruction_pointer; - std::uint16_t cs; - std::uint16_t flags; - std::uint16_t sp; - std::uint16_t ss; - }; - - /** - * @brief Handles an interrupt - * - * https://clang.llvm.org/docs/AttributeReference.html#interrupt-x86 - */ - __attribute__((interrupt)) extern "C" auto interrupt_handler(struct stack_frame * frame) -> void; - -} // namespace teachos::arch::kernel - -#endif // TEACHOS_ARCH_X86_64_KERNEL_INTERRUPT_HPP -- cgit v1.2.3 From 2f1f0fa8b0dc1893219be68ab8bf653b5d6349fb Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Feb 2025 07:58:01 +0000 Subject: clear interrupt flag --- arch/x86_64/src/boot/boot.s | 2 ++ 1 file changed, 2 insertions(+) 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 -- cgit v1.2.3