aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2025-02-27 08:23:59 +0000
committerFabian Imhof <fabian.imhof@ost.ch>2025-02-27 08:23:59 +0000
commitcc67705d0154f1d55aa234714389ec2db00e9406 (patch)
tree326e841bf04ab71ae5a2eb0a34266dc553ed1153
parentb7a37a1899772e16ce5550c6be3ff9cfd9825fe7 (diff)
parent3fb836101a2032e93f7b82c924ce208d7377a5ea (diff)
downloadteachos-cc67705d0154f1d55aa234714389ec2db00e9406.tar.xz
teachos-cc67705d0154f1d55aa234714389ec2db00e9406.zip
Merge remote-tracking branch 'origin/develop_ba' into feat_inital_context_switching
-rw-r--r--CMakeLists.txt9
-rw-r--r--arch/x86_64/CMakeLists.txt7
-rw-r--r--arch/x86_64/include/arch/kernel/interrupt.hpp26
-rw-r--r--arch/x86_64/include/arch/memory/heap/bump_allocator.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/heap/global_heap_allocator.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/heap/heap_allocator.hpp2
-rw-r--r--arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp2
-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/memory/heap/bump_allocator.cpp2
-rw-r--r--arch/x86_64/src/memory/heap/global_heap_allocator.cpp2
-rw-r--r--arch/x86_64/src/memory/heap/linked_list_allocator.cpp2
14 files changed, 406 insertions, 33 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 12ac210..8657cab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -75,6 +75,7 @@ add_compile_options(
"$<$<CXX_COMPILER_ID:GNU>:-Wextra>"
"$<$<CXX_COMPILER_ID:GNU>:-Werror>"
"$<$<CXX_COMPILER_ID:GNU>:-pedantic-errors>"
+ "$<$<CXX_COMPILER_ID:GNU>:-fsanitize=address,leak,bounds,alignment,return,integer-divide-by-zero,vla-bound,null,enum,pointer-overflow>"
)
#[============================================================================[
@@ -115,6 +116,13 @@ 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
#]============================================================================]
@@ -128,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/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 <cstdint>
-
-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
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/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/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();