Эх сурвалжийг харах

rewrite(allocator): locked version of kernel allocator

greatbridf 1 жил өмнө
parent
commit
759eb73ba3

+ 1 - 0
CMakeLists.txt

@@ -37,6 +37,7 @@ set(BOOTLOADER_SOURCES src/boot.s
 
 set(KERNEL_MAIN_SOURCES src/fs/fat.cpp
                         src/kinit.cpp
+                        src/kernel/allocator.cc
                         src/kernel/interrupt.cpp
                         src/kernel/process.cpp
                         src/kernel/tty.cpp

+ 0 - 1
gblibc/CMakeLists.txt

@@ -15,7 +15,6 @@ add_library(gblibc STATIC
     src/errno.c
     src/init.c
     src/internal.c
-    src/alloca.c
     src/stat.c
     src/time.c
     src/signal.c

+ 2 - 2
gblibc/include/alloca.h

@@ -3,12 +3,12 @@
 
 #include <stdint.h>
 
+#define alloca(size) __builtin_alloca(size)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-void* alloca(size_t size);
-
 #ifdef __cplusplus
 }
 #endif

+ 0 - 6
gblibc/src/alloca.c

@@ -1,6 +0,0 @@
-#include <alloca.h>
-
-void* alloca(size_t size)
-{
-    return __builtin_alloca(size);
-}

+ 4 - 6
include/kernel/mm.hpp

@@ -144,8 +144,7 @@ namespace memory {
 
 struct mm {
 public:
-    using pages_vector = std::vector<page,
-        types::allocator_adapter<page, types::kernel_ident_allocator>>;
+    using pages_vector = std::vector<page, types::memory::ident_allocator<page>>;
 
 public:
     void* start {};
@@ -201,8 +200,7 @@ private:
     };
 
 public:
-    using list_type = std::set<mm, comparator,
-        types::allocator_adapter<mm, types::kernel_ident_allocator>>;
+    using list_type = std::set<mm, comparator, types::memory::ident_allocator<mm>>;
     using iterator = list_type::iterator;
     using const_iterator = list_type::const_iterator;
 
@@ -247,7 +245,7 @@ public:
                 .system = system,
                 .mapped = 0,
             },
-            .pgs = types::_new<types::kernel_ident_allocator, mm::pages_vector>(),
+            .pgs = types::memory::kinew<mm::pages_vector>(),
         });
         assert(inserted);
         return *iter;
@@ -290,7 +288,7 @@ public:
 
             invalidate_tlb((uint32_t)area.start + (i++) * PAGE_SIZE);
         }
-        types::pdelete<types::kernel_ident_allocator>(area.pgs);
+        types::memory::kidelete<mm::pages_vector>(area.pgs);
     }
 
     constexpr mm* find(void* lp)

+ 1 - 1
include/kernel/tty.hpp

@@ -34,7 +34,7 @@ public:
     bool echo = true;
 
 protected:
-    types::buffer<types::kernel_ident_allocator> buf;
+    types::buffer buf;
     kernel::cond_var m_cv;
 
     pid_t fg_pgroup;

+ 5 - 7
include/kernel/vfs.hpp

@@ -108,12 +108,10 @@ public:
     struct dentry {
     public:
         using name_type = types::string<>;
-        template <typename T>
-        using allocator_type = types::kernel_allocator<T>;
 
     private:
-        std::list<dentry, types::allocator_adapter<dentry, allocator_type>>* children = nullptr;
-        types::hash_map<name_type, dentry*, types::linux_hasher, allocator_type>* idx_children = nullptr;
+        std::list<dentry>* children = nullptr;
+        types::hash_map<name_type, dentry*>* idx_children = nullptr;
 
     public:
         dentry* parent;
@@ -150,11 +148,11 @@ public:
         constexpr ~dentry()
         {
             if (children) {
-                types::pdelete<allocator_type>(children);
+                delete children;
                 children = nullptr;
             }
             if (idx_children) {
-                types::pdelete<allocator_type>(idx_children);
+                delete idx_children;
                 idx_children = nullptr;
             }
         }
@@ -235,7 +233,7 @@ private:
     static constexpr uint32_t WRITABLE = 2;
 
 private:
-    types::buffer<types::kernel_allocator> buf;
+    types::buffer buf;
     kernel::cond_var m_cv;
     uint32_t flags;
 

+ 53 - 302
include/types/allocator.hpp

@@ -1,334 +1,85 @@
 #pragma once
+#include <memory>
 #include <new>
 #include <utility>
 #include <type_traits>
-#include <bit>
+#include <cstddef>
+
 #include <stdint.h>
 #include <types/cplusplus.hpp>
 #include <types/types.h>
+#include <types/lock.hpp>
 
-namespace types {
-
-namespace __allocator {
-    class brk_memory_allocator {
-    public:
-        using byte = uint8_t;
-        using size_type = size_t;
-
-        struct mem_blk_flags {
-            uint8_t is_free;
-            uint8_t has_next;
-            uint8_t _unused2;
-            uint8_t _unused3;
-        };
-
-        struct mem_blk {
-            size_t size;
-            struct mem_blk_flags flags;
-            // the first byte of the memory space
-            // the minimal allocated space is 8 bytes
-            byte data[];
-        };
-
-    private:
-        byte* p_start;
-        byte* p_break;
-        byte* p_limit;
-
-        brk_memory_allocator() = delete;
-        brk_memory_allocator(const brk_memory_allocator&) = delete;
-        brk_memory_allocator(brk_memory_allocator&&) = delete;
-
-        constexpr byte* brk(byte* addr)
-        {
-            if (unlikely(addr >= p_limit))
-                return nullptr;
-            return p_break = addr;
-        }
-
-        constexpr byte* sbrk(size_type increment)
-        { return brk(p_break + increment); }
-
-        constexpr mem_blk* _next(mem_blk* blk, size_type blk_size)
-        {
-            auto* p = std::bit_cast<byte*>(blk);
-            p += sizeof(mem_blk);
-            p += blk_size;
-            return std::bit_cast<mem_blk*>(p);
-        }
-
-        // blk MUST be free
-        constexpr void unite_afterwards(mem_blk* blk)
-        {
-            while (blk->flags.has_next) {
-                auto* blk_next = _next(blk, blk->size);
-                if (!blk_next->flags.is_free)
-                    break;
-                blk->size += sizeof(mem_blk) + blk_next->size;
-                blk->flags.has_next = blk_next->flags.has_next;
-            }
-        }
-
-        // @param start_pos position where to start finding
-        // @param size the size of the block we're looking for
-        // @return found block if suitable block exists, if not, the last block
-        constexpr mem_blk* find_blk(mem_blk* start_pos, size_type size)
-        {
-            while (true) {
-                if (start_pos->flags.is_free) {
-                    unite_afterwards(start_pos);
-
-                    if (start_pos->size >= size)
-                        break;
-                }
-
-                if (!start_pos->flags.has_next)
-                    break;
-                start_pos = _next(start_pos, start_pos->size);
-            }
-            return start_pos;
-        }
-
-        constexpr mem_blk* allocate_new_block(mem_blk* blk_before, size_type size)
-        {
-            auto ret = sbrk(sizeof(mem_blk) + size);
-            if (!ret)
-                return nullptr;
-
-            mem_blk* blk = _next(blk_before, blk_before->size);
-
-            blk_before->flags.has_next = 1;
-
-            blk->flags.has_next = 0;
-            blk->flags.is_free = 1;
-            blk->size = size;
-
-            return blk;
-        }
-
-        constexpr void split_block(mem_blk* blk, size_type this_size)
-        {
-            // block is too small to get split
-            // that is, the block to be split should have enough room
-            // for "this_size" bytes and also could contain a new block
-            if (blk->size < this_size + sizeof(mem_blk) + 8)
-                return;
-
-            mem_blk* blk_next = _next(blk, this_size);
-
-            blk_next->size = blk->size
-                - this_size
-                - sizeof(mem_blk);
-
-            blk_next->flags.has_next = blk->flags.has_next;
-            blk_next->flags.is_free = 1;
-
-            blk->flags.has_next = 1;
-            blk->size = this_size;
-        }
+namespace kernel::kinit {
 
-    public:
-        constexpr brk_memory_allocator(byte* start, size_type limit)
-            : p_start(start)
-            , p_limit(start + limit)
-        {
-            brk(p_start);
-            auto* p_blk = std::bit_cast<mem_blk*>(sbrk(0));
-            p_blk->size = 8;
-            p_blk->flags.has_next = 0;
-            p_blk->flags.is_free = 1;
-        }
+void init_kernel_heap(void* start, std::size_t size);
 
-        constexpr void* alloc(size_type size)
-        {
-            // align to 8 bytes boundary
-            size = (size + 7) & ~7;
+} // namespace kernel::kinit
 
-            auto* block_allocated = find_blk(std::bit_cast<mem_blk*>(p_start), size);
-            if (!block_allocated->flags.has_next
-                && (!block_allocated->flags.is_free || block_allocated->size < size)) {
-                // 'block_allocated' in the argument list is the pointer
-                // pointing to the last block
-                block_allocated = allocate_new_block(block_allocated, size);
-                if (!block_allocated)
-                    return nullptr;
-            } else {
-                split_block(block_allocated, size);
-            }
+namespace types::memory {
 
-            block_allocated->flags.is_free = 0;
-
-            auto* blkpos = std::bit_cast<byte*>(block_allocated);
-            if (blkpos > p_start)
-                p_start = blkpos;
-            return block_allocated->data;
-        }
-
-        constexpr void free(void* ptr)
-        {
-            auto* blk = std::bit_cast<mem_blk*>(
-                std::bit_cast<byte*>(ptr) - sizeof(mem_blk));
-
-            blk->flags.is_free = 1;
-
-            if (std::bit_cast<byte*>(blk) < p_start)
-                p_start = std::bit_cast<byte*>(blk);
-
-            // unite free blocks nearby
-            unite_afterwards(blk);
-        }
-    };
-}; // namespace __allocator
-
-template <typename T>
-concept Allocator = requires(size_t size, typename T::value_type* ptr)
-{
-    typename T::value_type;
-    {
-        T::allocate_memory(size)
-    };
-    {
-        T::deallocate_memory(ptr)
-    };
-    std::is_same_v<typename T::value_type*, decltype(T::allocate_memory(size))>;
-    std::is_same_v<void, decltype(T::deallocate_memory(ptr))>;
-};
-
-template <Allocator T>
-class allocator_traits;
-
-namespace __allocator {
-    inline char __ident_heap[0x100000];
-    inline __allocator::brk_memory_allocator
-        m_alloc { (uint8_t*)__ident_heap, sizeof(__ident_heap) };
-} // namespace __allocator
-
-template <typename T>
-class kernel_ident_allocator {
+class brk_memory_allocator {
 public:
-    using value_type = T;
-
-    static constexpr value_type* allocate_memory(size_t count)
-    {
-        return static_cast<value_type*>(__allocator::m_alloc.alloc(count));
-    }
-
-    static constexpr void deallocate_memory(value_type* ptr)
-    {
-        __allocator::m_alloc.free(ptr);
-    }
-};
-
-template <template <typename _T> class Allocator, typename T, typename... Args>
-constexpr T* _new(Args&&... args)
-{
-    return allocator_traits<Allocator<T>>::allocate_and_construct(std::forward<Args>(args)...);
-}
-
-template <template <typename _T> class Allocator, typename T, typename... Args>
-constexpr T* pnew(T* = nullptr, Args&&... args)
-{
-    return _new<Allocator, T, Args...>(std::forward<Args>(args)...);
-}
-
-template <template <typename _T> class Allocator, typename T>
-constexpr void pdelete(T* ptr)
-{
-    allocator_traits<Allocator<T>>::deconstruct_and_deallocate(ptr);
-}
+    using byte = std::byte;
+    using size_type = std::size_t;
 
-template <Allocator _allocator>
-class allocator_traits {
-public:
-    using value_type = typename _allocator::value_type;
+private:
+    byte* p_start;
+    byte* p_limit;
+    byte* p_break;
+    types::mutex mtx;
 
-    static constexpr value_type* allocate(size_t count)
+    constexpr byte* brk(byte* addr)
     {
-        if (count == 0)
+        if (addr >= p_limit) [[unlikely]]
             return nullptr;
-        return _allocator::allocate_memory(sizeof(value_type) * count);
+        return p_break = addr;
     }
 
-    template <typename... Args>
-    static constexpr value_type* construct(value_type* ptr, Args&&... args)
-    {
-        new (ptr) value_type(std::forward<Args>(args)...);
-        return ptr;
-    }
-
-    template <typename... Args>
-    static constexpr value_type* allocate_and_construct(Args&&... args)
-    {
-        auto* ptr = allocate(1);
-        construct(ptr, std::forward<Args>(args)...);
-        return ptr;
-    }
+    constexpr byte* sbrk(size_type increment)
+    { return brk(p_break + increment); }
 
-    static constexpr void deconstruct(value_type* ptr)
-    {
-        if (!ptr)
-            return;
-        ptr->~value_type();
-    }
-
-    static constexpr void deallocate(value_type* ptr)
-    {
-        if (!ptr)
-            return;
-        _allocator::deallocate_memory(ptr);
-    }
+public:
+    explicit brk_memory_allocator(byte* start, size_type size);
+    brk_memory_allocator(const brk_memory_allocator&) = delete;
 
-    static constexpr void deconstruct_and_deallocate(value_type* ptr)
-    {
-        if (!ptr)
-            return;
-        deconstruct(ptr);
-        deallocate(ptr);
-    }
+    void* allocate(size_type size);
+    void deallocate(void* ptr);
 };
 
-namespace __allocator {
-    inline __allocator::brk_memory_allocator* m_palloc;
-    inline void init_kernel_heap(void* start, size_t sz)
-    {
-        m_palloc = pnew<kernel_ident_allocator>(m_palloc, (uint8_t*)start, sz);
-    }
-} // namespace __allocator
+void* kimalloc(std::size_t size);
+void kifree(void* ptr);
 
 template <typename T>
-class kernel_allocator {
-public:
+struct ident_allocator {
     using value_type = T;
-
-    static constexpr value_type* allocate_memory(size_t count)
-    {
-        return static_cast<value_type*>(__allocator::m_palloc->alloc(count));
-    }
-
-    static constexpr void deallocate_memory(value_type* ptr)
-    {
-        __allocator::m_palloc->free(ptr);
-    }
-};
-
-template <typename T, template <typename> typename Allocator>
-struct allocator_adapter {
-    using value_type = typename Allocator<T>::value_type;
     using propagate_on_container_move_assignment = std::true_type;
 
-    constexpr allocator_adapter() = default;
-
-    template <template <typename> typename UAlloc, typename U>
-    constexpr allocator_adapter(const allocator_adapter<U, UAlloc>&)
-        noexcept {}
-    
-    constexpr T* allocate(std::size_t n)
-    { return types::allocator_traits<Allocator<T>>::allocate(n); }
-    constexpr void deallocate(T* ptr, std::size_t)
-    { return types::allocator_traits<Allocator<T>>::deallocate(ptr); }
+    constexpr ident_allocator() = default;
 
     template <typename U>
-    struct rebind { using other = allocator_adapter<U, Allocator>; };
+    constexpr ident_allocator(const ident_allocator<U>&) noexcept {}
+    
+    inline T* allocate(std::size_t n)
+    { return (T*)kimalloc(n * sizeof(T)); }
+    inline void deallocate(T* ptr, std::size_t) { return kifree(ptr); }
 };
 
-} // namespace types
+template <typename T, typename... Args>
+constexpr T* kinew(Args&&... args)
+{
+    ident_allocator<T> alloc { };
+    T* ptr = std::allocator_traits<ident_allocator<T>>::allocate(alloc, 1);
+    std::allocator_traits<ident_allocator<T>>::construct(alloc, ptr, std::forward<Args>(args)...);
+    return ptr;
+}
+
+template <typename T>
+constexpr void kidelete(T* ptr)
+{
+    ident_allocator<T> alloc { };
+    std::allocator_traits<ident_allocator<T>>::destroy(alloc, ptr);
+    std::allocator_traits<ident_allocator<T>>::deallocate(alloc, ptr, 1);
+}
+
+} // namespace types::memory

+ 1 - 1
include/types/bitmap.hpp

@@ -14,7 +14,7 @@ private:
     unsigned char* m_bm;
     std::size_t m_size;
 
-    static constexpr std::size_t SZ = sizeof(unsigned char);
+    static constexpr std::size_t SZ = sizeof(unsigned char) * 8;
 
 public:
     constexpr bitmap(const deleter_type& del, unsigned char* bm, std::size_t size)

+ 15 - 10
include/types/buffer.hpp

@@ -1,15 +1,17 @@
 #pragma once
 
+#include <memory>
+
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
 
 namespace types {
 
-template <template <typename> class Allocator>
-class buffer {
+template <typename Allocator>
+class basic_buffer {
 public:
-    using allocator_type = Allocator<char>;
+    using alloc_traits = std::allocator_traits<Allocator>;
 
 private:
     char* const start;
@@ -17,6 +19,7 @@ private:
     char* base;
     char* head;
     size_t count;
+    Allocator alloc { };
 
 private:
     constexpr char _get_char(char* ptr)
@@ -48,8 +51,8 @@ private:
     }
 
 public:
-    constexpr buffer(size_t size)
-        : start { types::allocator_traits<allocator_type>::allocate(size) }
+    constexpr basic_buffer(size_t size)
+        : start { alloc_traits::allocate(alloc, size) }
         , end { start + size - 1 }
         , base { start }
         , head { start }
@@ -57,8 +60,8 @@ public:
     {
     }
 
-    constexpr buffer(const buffer& buf)
-        : start { types::allocator_traits<allocator_type>::allocate(buf.end + 1 - buf.start) }
+    constexpr basic_buffer(const basic_buffer& buf)
+        : start { alloc_traits::allocate(alloc, buf.end + 1 - buf.start) }
         , end { (uint32_t)start + (uint32_t)buf.end - (uint32_t)buf.start }
         , base { (uint32_t)start + (uint32_t)buf.base - (uint32_t)buf.start }
         , head { (uint32_t)start + (uint32_t)buf.base - (uint32_t)buf.start }
@@ -66,7 +69,7 @@ public:
     {
     }
 
-    constexpr buffer(buffer&& buf)
+    constexpr basic_buffer(basic_buffer&& buf)
         : start { buf.start }
         , end { buf.end }
         , base { buf.base }
@@ -75,10 +78,10 @@ public:
     {
     }
 
-    constexpr ~buffer()
+    constexpr ~basic_buffer()
     {
         if (start)
-            types::allocator_traits<allocator_type>::deallocate(start);
+            alloc_traits::deallocate(alloc, start, end - start);
     }
 
     constexpr bool empty(void) const
@@ -152,4 +155,6 @@ public:
     }
 };
 
+using buffer = basic_buffer<std::allocator<char>>;
+
 } // namespace types

+ 4 - 6
include/types/hash_map.hpp

@@ -86,7 +86,7 @@ struct linux_hasher<String<Allocator>,
 
 template <typename Key, typename Value,
     template <typename _Key, typename...> class Hasher = types::linux_hasher,
-    template <typename _T> class Allocator = types::kernel_allocator,
+    typename Allocator = std::allocator<std::pair<const Key, Value> >,
     std::enable_if_t<std::is_convertible_v<hash_t, decltype(
         Hasher<Key>::hash(std::declval<Key>(), std::declval<uint32_t>())
     )>, bool> = true>
@@ -103,11 +103,9 @@ public:
     using iterator_type = iterator<pair_type*>;
     using const_iterator_type = iterator<const pair_type*>;
 
-    template <typename T>
-    using adapted_allocator = types::allocator_adapter<T, Allocator>;
-
-    using bucket_type = std::list<pair_type, adapted_allocator<pair_type>>;
-    using bucket_array_type = std::vector<bucket_type, adapted_allocator<bucket_type>>;
+    using bucket_type = std::list<pair_type, Allocator>;
+    using bucket_array_type = std::vector<bucket_type, typename
+        std::allocator_traits<Allocator>:: template rebind_alloc<bucket_type>>;
 
     using hasher_type = Hasher<Key>;
 

+ 3 - 3
src/asm/interrupt.s

@@ -183,15 +183,15 @@ syscall_stub:
     pushal
 
     # stack alignment and push *data
-    movl %esp, %eax
+    movl %esp, %ebx
     subl $0x4, %esp
     andl $0xfffffff0, %esp
-    movl %eax, (%esp)
+    movl %ebx, (%esp)
 
     call syscall_entry
 
     # restore stack
-    popl %esp
+    mov %ebx, %esp
 
 .globl _syscall_stub_fork_return
 .type  _syscall_stub_fork_return @function

+ 208 - 0
src/kernel/allocator.cc

@@ -0,0 +1,208 @@
+#include <types/allocator.hpp>
+#include <types/lock.hpp>
+
+#include <bit>
+#include <cstddef>
+
+#include <assert.h>
+#include <stdint.h>
+
+namespace types::memory {
+
+struct mem_blk_flags {
+    uint8_t is_free;
+    uint8_t has_next;
+    uint8_t : 8; // unused1
+    uint8_t : 8; // unused2
+};
+
+struct mem_blk {
+    std::size_t size;
+    mem_blk_flags flags;
+    // the first byte of the memory space
+    // the minimal allocated space is 8 bytes
+    std::byte data[];
+};
+
+constexpr std::byte* aspbyte(void* pblk)
+{ return std::bit_cast<std::byte*>(pblk);}
+
+constexpr mem_blk* aspblk(void* pbyte)
+{ return std::bit_cast<mem_blk*>(pbyte);}
+
+constexpr mem_blk* next(mem_blk* blk, std::size_t blk_size)
+{
+    auto* p = aspbyte(blk);
+    p += sizeof(mem_blk);
+    p += blk_size;
+    return aspblk(p);
+}
+
+// blk MUST be free
+constexpr void unite_afterwards(mem_blk* blk)
+{
+    while (blk->flags.has_next) {
+        auto* blk_next = next(blk, blk->size);
+        if (!blk_next->flags.is_free)
+            break;
+        blk->size += sizeof(mem_blk) + blk_next->size;
+        blk->flags.has_next = blk_next->flags.has_next;
+    }
+}
+
+// @param start_pos position where to start finding
+// @param size the size of the block we're looking for
+// @return found block if suitable block exists, if not, the last block
+constexpr mem_blk* find_blk(mem_blk* start_pos, std::size_t size)
+{
+    while (true) {
+        if (start_pos->flags.is_free) {
+            unite_afterwards(start_pos);
+
+            if (start_pos->size >= size)
+                break;
+        }
+
+        if (!start_pos->flags.has_next)
+            break;
+        start_pos = next(start_pos, start_pos->size);
+    }
+    return start_pos;
+}
+
+constexpr void split_block(mem_blk* blk, std::size_t this_size)
+{
+    // block is too small to get split
+    // that is, the block to be split should have enough room
+    // for "this_size" bytes and also could contain a new block
+    if (blk->size < this_size + sizeof(mem_blk) + 8)
+        return;
+
+    mem_blk* blk_next = next(blk, this_size);
+
+    blk_next->size = blk->size
+        - this_size
+        - sizeof(mem_blk);
+
+    blk_next->flags.has_next = blk->flags.has_next;
+    blk_next->flags.is_free = 1;
+
+    blk->flags.has_next = 1;
+    blk->size = this_size;
+}
+
+brk_memory_allocator::brk_memory_allocator(byte* start, size_type size)
+    : p_start(start)
+    , p_limit(start + size)
+{
+    brk(p_start);
+    auto* p_blk = aspblk(sbrk(0));
+    p_blk->size = 8;
+    p_blk->flags.has_next = 0;
+    p_blk->flags.is_free = 1;
+}
+
+void* brk_memory_allocator::allocate(size_type size)
+{
+    types::lock_guard lck(mtx);
+    // align to 8 bytes boundary
+    size = (size + 7) & ~7;
+
+    auto* block_allocated = find_blk(aspblk(p_start), size);
+    if (!block_allocated->flags.has_next
+        && (!block_allocated->flags.is_free || block_allocated->size < size)) {
+        // 'block_allocated' in the argument list is the pointer
+        // pointing to the last block
+
+        if (!sbrk(sizeof(mem_blk) + size))
+            return nullptr;
+
+        block_allocated->flags.has_next = 1;
+
+        block_allocated = next(block_allocated, block_allocated->size);
+
+        block_allocated->flags.has_next = 0;
+        block_allocated->flags.is_free = 1;
+        block_allocated->size = size;
+    } else {
+        split_block(block_allocated, size);
+    }
+
+    block_allocated->flags.is_free = 0;
+
+    auto* blkpos = aspbyte(block_allocated);
+    if (blkpos > p_start)
+        p_start = blkpos;
+    return block_allocated->data;
+}
+
+void brk_memory_allocator::deallocate(void* ptr)
+{
+    types::lock_guard lck(mtx);
+    auto* blk = aspblk(aspbyte(ptr) - sizeof(mem_blk));
+
+    blk->flags.is_free = 1;
+
+    if (aspbyte(blk) < p_start)
+        p_start = aspbyte(blk);
+
+    // unite free blocks nearby
+    unite_afterwards(blk);
+}
+
+static std::byte ki_heap[0x100000];
+static brk_memory_allocator ki_alloc(ki_heap, sizeof(ki_heap));
+static brk_memory_allocator* k_alloc;
+
+void* kimalloc(std::size_t size)
+{
+    return ki_alloc.allocate(size);
+}
+
+void kifree(void* ptr)
+{
+    ki_alloc.deallocate(ptr);
+}
+
+} // namespace types::memory
+
+SECTION(".text.kinit")
+void kernel::kinit::init_kernel_heap(void *start, std::size_t size)
+{
+    using namespace types::memory;
+    k_alloc = kinew<brk_memory_allocator>((std::byte*)start, size);
+}
+
+void* operator new(size_t sz)
+{
+    void* ptr = types::memory::k_alloc->allocate(sz);
+    assert(ptr);
+    return ptr;
+}
+
+void* operator new[](size_t sz)
+{
+    void* ptr = types::memory::k_alloc->allocate(sz);
+    assert(ptr);
+    return ptr;
+}
+
+void operator delete(void* ptr)
+{
+    types::memory::k_alloc->deallocate(ptr);
+}
+
+void operator delete(void* ptr, size_t)
+{
+    types::memory::k_alloc->deallocate(ptr);
+}
+
+void operator delete[](void* ptr)
+{
+    types::memory::k_alloc->deallocate(ptr);
+}
+
+void operator delete[](void* ptr, size_t)
+{
+    types::memory::k_alloc->deallocate(ptr);
+}

+ 1 - 1
src/kernel/interrupt.cpp

@@ -282,7 +282,7 @@ extern "C" void int14_handler(int14_data* d)
 
         --*page->ref_count;
 
-        page->ref_count = types::pnew<types::kernel_ident_allocator>(page->ref_count, 1);
+        page->ref_count = types::memory::kinew<size_t>(1);
         page->attr &= ~PAGE_COW;
         page->phys_page_id = new_page;
     }

+ 8 - 44
src/kernel/mem.cpp

@@ -36,40 +36,6 @@ uint32_t e820_mem_map_count;
 uint32_t e820_mem_map_entry_size;
 struct mem_size_info mem_size_info;
 
-void* operator new(size_t sz)
-{
-    void* ptr = types::__allocator::m_palloc->alloc(sz);
-    assert(ptr);
-    return ptr;
-}
-
-void* operator new[](size_t sz)
-{
-    void* ptr = types::__allocator::m_palloc->alloc(sz);
-    assert(ptr);
-    return ptr;
-}
-
-void operator delete(void* ptr)
-{
-    types::__allocator::m_palloc->free(ptr);
-}
-
-void operator delete(void* ptr, size_t)
-{
-    types::__allocator::m_palloc->free(ptr);
-}
-
-void operator delete[](void* ptr)
-{
-    types::__allocator::m_palloc->free(ptr);
-}
-
-void operator delete[](void* ptr, size_t)
-{
-    types::__allocator::m_palloc->free(ptr);
-}
-
 constexpr void mark_addr_len(pptr_t start, size_t n)
 {
     if (n == 0)
@@ -121,7 +87,7 @@ page allocate_page(void)
 {
     return page {
         .phys_page_id = __alloc_raw_page(),
-        .ref_count = types::_new<types::kernel_ident_allocator, size_t>(0),
+        .ref_count = types::memory::kinew<size_t>(0),
         .pg_pteidx = 0,
         .attr = 0,
     };
@@ -130,7 +96,7 @@ page allocate_page(void)
 void free_page(page* pg)
 {
     if (*pg->ref_count == 1) {
-        types::pdelete<types::kernel_ident_allocator>(pg->ref_count);
+        types::memory::kidelete<size_t>(pg->ref_count);
         __free_raw_page(pg->phys_page_id);
     } else {
         --*pg->ref_count;
@@ -453,8 +419,7 @@ mm mm::split(void *addr)
     mm newmm {
         .start = addr,
         .attr { attr },
-        .pgs = types::_new<types::kernel_ident_allocator, mm::pages_vector>(
-        ),
+        .pgs = types::memory::kinew<mm::pages_vector>(),
         .mapped_file = mapped_file,
         .file_offset = attr.mapped ? file_offset + this_count * PAGE_SIZE : 0,
     };
@@ -517,21 +482,20 @@ void init_mem(void)
     init_mem_layout();
 
     // TODO: replace early kernel pd
-    auto* __kernel_mms = types::_new<types::kernel_ident_allocator,
-            kernel::memory::mm_list>(EARLY_KERNEL_PD_PAGE);
+    auto* __kernel_mms = types::memory::kinew<kernel::memory::mm_list>(EARLY_KERNEL_PD_PAGE);
     kernel::memory::mm_list::s_kernel_mms = __kernel_mms;
 
     // create empty_page struct
     empty_page.attr = 0;
     empty_page.phys_page_id = EMPTY_PAGE;
-    empty_page.ref_count = types::_new<types::kernel_ident_allocator, size_t>(2);
+    empty_page.ref_count = types::memory::kinew<size_t>(2);
     empty_page.pg_pteidx = 0x00002000;
 
     // 0xd0000000 to 0xd4000000 or 3.5GiB, size 64MiB
     __kernel_mms->add_empty_area(KERNEL_HEAP_START,
         64 * 1024 * 1024 / PAGE_SIZE, PAGE_COW, true, true);
 
-    types::__allocator::init_kernel_heap(KERNEL_HEAP_START,
+    kernel::kinit::init_kernel_heap(KERNEL_HEAP_START,
         vptrdiff(KERNEL_HEAP_LIMIT, KERNEL_HEAP_START));
 }
 
@@ -558,8 +522,8 @@ struct mapped_area {
     void* ptr;
 };
 
-static types::hash_map<page_t, mapped_area,
-    types::linux_hasher, types::kernel_ident_allocator>
+static types::hash_map<page_t, mapped_area, types::linux_hasher,
+    types::memory::ident_allocator<std::pair<page_t, mapped_area>>>
     mapped;
 static uint8_t _freebm[0x400 / 8];
 static types::bitmap freebm(

+ 7 - 19
src/kernel/vfs.cpp

@@ -21,9 +21,6 @@
 #include <types/path.hpp>
 #include <types/string.hpp>
 
-using types::allocator_traits;
-using types::kernel_allocator;
-
 struct tmpfs_file_entry {
     size_t ino;
     char filename[128];
@@ -33,8 +30,8 @@ fs::vfs::dentry::dentry(dentry* _parent, inode* _ind, name_type _name)
     : parent(_parent) , ind(_ind) , flags { } , name(_name)
 {
     if (!_ind || S_ISDIR(ind->mode)) {
-        children = types::pnew<allocator_type>(children);
-        idx_children = types::pnew<allocator_type>(idx_children);
+        children = new std::list<dentry>;
+        idx_children = new types::hash_map<name_type, dentry*>;
     }
 }
 
@@ -242,15 +239,8 @@ private:
     }
 
 protected:
-    inline vfe_t* mk_fe_vector(void)
-    {
-        return allocator_traits<kernel_allocator<vfe_t>>::allocate_and_construct();
-    }
-
-    inline fdata_t* mk_data_vector(void)
-    {
-        return allocator_traits<kernel_allocator<fdata_t>>::allocate_and_construct();
-    }
+    inline vfe_t* mk_fe_vector() { return new vfe_t{}; }
+    inline fdata_t* mk_data_vector() { return new fdata_t{}; }
 
     void mklink(fs::inode* dir, fs::inode* inode, const char* filename)
     {
@@ -659,7 +649,7 @@ int fs::vfs_stat(fs::vfs::dentry* ent, statx* stat, unsigned int mask)
     return ent->ind->fs->inode_statx(ent, stat, mask);
 }
 
-static std::list<fs::vfs*>* fs_es;
+static std::list<fs::vfs*, types::memory::ident_allocator<fs::vfs*>> fs_es;
 
 int fs::register_block_device(dev_t node, fs::blkdev_ops ops)
 {
@@ -822,7 +812,7 @@ ssize_t fs::char_device_write(dev_t node, const char* buf, size_t n)
 
 fs::vfs* fs::register_fs(vfs* fs)
 {
-    fs_es->push_back(fs);
+    fs_es.push_back(fs);
     return fs;
 }
 
@@ -951,10 +941,8 @@ void init_vfs(void)
     // TODO: add interface to bind console device to other devices
     register_char_device(make_device(2, 0), { console_read, console_write });
 
-    fs_es = types::pnew<types::kernel_ident_allocator>(fs_es);
-
     auto* rootfs = new tmpfs;
-    fs_es->push_back(rootfs);
+    fs_es.push_back(rootfs);
     fs_root = rootfs->root();
 
     vfs_mkdir(fs_root, "dev", 0755);

+ 3 - 3
src/kinit.cpp

@@ -71,16 +71,16 @@ static inline int init_console(const char* name)
     if (name[0] == 't' && name[1] == 't' && name[2] == 'y') {
         if (name[3] == 'S' || name[3] == 's') {
             if (name[4] == '0') {
-                console = types::_new<types::kernel_ident_allocator, serial_tty>(PORT_SERIAL0);
+                console = types::memory::kinew<serial_tty>(PORT_SERIAL0);
                 return GB_OK;
             }
             if (name[4] == '1') {
-                console = types::_new<types::kernel_ident_allocator, serial_tty>(PORT_SERIAL1);
+                console = types::memory::kinew<serial_tty>(PORT_SERIAL1);
                 return GB_OK;
             }
         }
         if (name[3] == 'V' && name[3] == 'G' && name[3] == 'A') {
-            console = types::_new<types::kernel_ident_allocator, vga_tty>();
+            console = types::memory::kinew<vga_tty>();
             return GB_OK;
         }
     }