From 9744c41ebbc5f40838b4422e5a89fac0379d47e7 Mon Sep 17 00:00:00 2001 From: Ivan Chikish Date: Thu, 6 Jul 2023 22:10:15 +0300 Subject: [PATCH] [orbis-kernel] Implement kfree Incomplete implementation. --- .../include/orbis/KernelAllocator.hpp | 2 + orbis-kernel/include/orbis/KernelContext.hpp | 36 +++++++------- orbis-kernel/src/KernelContext.cpp | 49 ++++++++++++++++--- 3 files changed, 61 insertions(+), 26 deletions(-) diff --git a/orbis-kernel/include/orbis/KernelAllocator.hpp b/orbis-kernel/include/orbis/KernelAllocator.hpp index 852dbceca..879d55312 100644 --- a/orbis-kernel/include/orbis/KernelAllocator.hpp +++ b/orbis-kernel/include/orbis/KernelAllocator.hpp @@ -37,6 +37,8 @@ template using kvector = std::vector>; template using kdeque = std::deque>; template > using kmap = std::map>>; +template > +using kmultimap = std::multimap>>; template , typename Pred = std::equal_to> using kunmap = diff --git a/orbis-kernel/include/orbis/KernelContext.hpp b/orbis-kernel/include/orbis/KernelContext.hpp index 242733888..0d1879a5a 100644 --- a/orbis-kernel/include/orbis/KernelContext.hpp +++ b/orbis-kernel/include/orbis/KernelContext.hpp @@ -1,11 +1,12 @@ #pragma once +#include "evf.hpp" #include "utils/LinkedNode.hpp" #include "utils/SharedMutex.hpp" -#include "evf.hpp" -#include "orbis/thread/types.hpp" #include "KernelAllocator.hpp" +#include "orbis/thread/types.hpp" #include +#include #include namespace orbis { @@ -20,13 +21,15 @@ public: void deleteProcess(Process *proc); Process *findProcessById(pid_t pid) const; - static void *kalloc(std::size_t size, - std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__); - static void kfree(void *ptr, std::size_t size); + void *kalloc(std::size_t size, + std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__); + void kfree(void *ptr, std::size_t size); - std::pair createEventFlag(utils::kstring name, std::int32_t flags) { - auto [it, inserted] = m_event_flags.try_emplace(std::move(name), knew(flags)); - return { it->second.get(), inserted }; + std::pair createEventFlag(utils::kstring name, + std::int32_t flags) { + auto [it, inserted] = + m_event_flags.try_emplace(std::move(name), knew(flags)); + return {it->second.get(), inserted}; } Ref findEventFlag(std::string_view name) { @@ -34,22 +37,19 @@ public: return it->second; } - return{}; + return {}; } private: + mutable pthread_mutex_t m_heap_mtx; + void *m_heap_next = this + 1; + bool m_heap_is_freeing = false; + utils::kmultimap m_free_heap; + utils::kmultimap m_used_node; + mutable shared_mutex m_proc_mtx; utils::LinkedNode *m_processes = nullptr; utils::kmap> m_event_flags; - - struct node { - std::size_t size; - node *next; - }; - - mutable shared_mutex m_heap_mtx; - void *m_heap_next = this + 1; - node *m_free_list = nullptr; }; extern KernelContext &g_context; diff --git a/orbis-kernel/src/KernelContext.cpp b/orbis-kernel/src/KernelContext.cpp index 427857521..e83192c4a 100644 --- a/orbis-kernel/src/KernelContext.cpp +++ b/orbis-kernel/src/KernelContext.cpp @@ -16,6 +16,14 @@ KernelContext &g_context = *[]() -> KernelContext * { }(); KernelContext::KernelContext() { + // Initialize recursive heap mutex + pthread_mutexattr_t mtx_attr; + pthread_mutexattr_init(&mtx_attr); + pthread_mutexattr_settype(&mtx_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutexattr_setpshared(&mtx_attr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&m_heap_mtx, &mtx_attr); + pthread_mutexattr_destroy(&mtx_attr); + std::printf("orbis::KernelContext initialized, addr=%p", this); } KernelContext::~KernelContext() {} @@ -66,28 +74,53 @@ Process *KernelContext::findProcessById(pid_t pid) const { } void *KernelContext::kalloc(std::size_t size, std::size_t align) { - std::lock_guard lock(g_context.m_heap_mtx); - align = std::max(align, sizeof(node)); - auto heap = reinterpret_cast(g_context.m_heap_next); + pthread_mutex_lock(&m_heap_mtx); + if (!m_heap_is_freeing) { + // Try to reuse previously freed block + for (auto [it, end] = m_free_heap.equal_range(size); it != end; it++) { + auto result = it->second; + if (!(reinterpret_cast(result) & (align - 1))) { + m_used_node.insert(m_free_heap.extract(it)); + pthread_mutex_unlock(&m_heap_mtx); + return result; + } + } + } + + align = std::max(align, __STDCPP_DEFAULT_NEW_ALIGNMENT__); + auto heap = reinterpret_cast(m_heap_next); heap = (heap + (align - 1)) & ~(align - 1); auto result = reinterpret_cast(heap); - g_context.m_heap_next = reinterpret_cast(heap + size); + m_heap_next = reinterpret_cast(heap + size); + pthread_mutex_unlock(&m_heap_mtx); return result; } void KernelContext::kfree(void *ptr, std::size_t size) { - std::lock_guard lock(g_context.m_heap_mtx); + pthread_mutex_lock(&m_heap_mtx); if (!size) std::abort(); - // TODO: create node and put it into + if (m_heap_is_freeing) + std::abort(); + m_heap_is_freeing = true; + if (!m_used_node.empty()) { + auto node = m_used_node.extract(m_used_node.begin()); + node.key() = size; + node.mapped() = ptr; + m_free_heap.insert(std::move(node)); + } else { + m_free_heap.emplace(size, ptr); + } + m_heap_is_freeing = false; + pthread_mutex_unlock(&m_heap_mtx); } inline namespace utils { void kfree(void *ptr, std::size_t size) { - return KernelContext::kfree(ptr, size); + return g_context.kfree(ptr, size); } void *kalloc(std::size_t size, std::size_t align) { - return KernelContext::kalloc(size, align); + return g_context.kalloc(size, align); } } // namespace utils } // namespace orbis