diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2021-07-15 12:08:35 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-16 20:51:13 +0200 |
commit | dd4ed4d22dc96737d8b0342886e24c9544fc1a63 (patch) | |
tree | 5787378768e639c34a6c2988c26ee2e28ba1a13c /Kernel | |
parent | c176680443eb81161c888ecf023709d19745ec85 (diff) | |
download | serenity-dd4ed4d22dc96737d8b0342886e24c9544fc1a63.zip |
Kernel: Implement aligned `operator new` and use it
The compiler will use these to allocate objects that have alignment
requirements greater than that of our normal `operator new` (4/8 byte
aligned).
This means we can now use smart pointers for over-aligned types.
Fixes a FIXME.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Heap/kmalloc.cpp | 27 | ||||
-rw-r--r-- | Kernel/Heap/kmalloc.h | 8 | ||||
-rw-r--r-- | Kernel/Thread.cpp | 12 | ||||
-rw-r--r-- | Kernel/Thread.h | 4 |
4 files changed, 41 insertions, 10 deletions
diff --git a/Kernel/Heap/kmalloc.cpp b/Kernel/Heap/kmalloc.cpp index 2d9c808e8b..4546f43c15 100644 --- a/Kernel/Heap/kmalloc.cpp +++ b/Kernel/Heap/kmalloc.cpp @@ -301,6 +301,16 @@ size_t kmalloc_good_size(size_t size) return size; } +[[gnu::malloc, gnu::alloc_size(1), gnu::alloc_align(2)]] static void* kmalloc_aligned_cxx(size_t size, size_t alignment) +{ + VERIFY(alignment <= 4096); + void* ptr = kmalloc(size + alignment + sizeof(ptrdiff_t)); + size_t max_addr = (size_t)ptr + alignment; + void* aligned_ptr = (void*)(max_addr - (max_addr % alignment)); + ((ptrdiff_t*)aligned_ptr)[-1] = (ptrdiff_t)((u8*)aligned_ptr - (u8*)ptr); + return aligned_ptr; +} + void* operator new(size_t size) { void* ptr = kmalloc(size); @@ -313,6 +323,18 @@ void* operator new(size_t size, const std::nothrow_t&) noexcept return kmalloc(size); } +void* operator new(size_t size, std::align_val_t al) +{ + void* ptr = kmalloc_aligned_cxx(size, (size_t)al); + VERIFY(ptr); + return ptr; +} + +void* operator new(size_t size, std::align_val_t al, const std::nothrow_t&) noexcept +{ + return kmalloc_aligned_cxx(size, (size_t)al); +} + void* operator new[](size_t size) { void* ptr = kmalloc(size); @@ -336,6 +358,11 @@ void operator delete(void* ptr, size_t size) noexcept return kfree_sized(ptr, size); } +void operator delete(void* ptr, size_t, std::align_val_t) noexcept +{ + return kfree_aligned(ptr); +} + void operator delete[](void*) noexcept { // All deletes in kernel code should have a known size. diff --git a/Kernel/Heap/kmalloc.h b/Kernel/Heap/kmalloc.h index 72fdb2e3b7..2c005d2a80 100644 --- a/Kernel/Heap/kmalloc.h +++ b/Kernel/Heap/kmalloc.h @@ -34,6 +34,8 @@ struct nothrow_t { }; extern const nothrow_t nothrow; + +enum class align_val_t : size_t {}; }; void kmalloc_init(); @@ -59,10 +61,16 @@ inline void* operator new[](size_t, void* p) { return p; } [[nodiscard]] void* operator new(size_t size); [[nodiscard]] void* operator new(size_t size, const std::nothrow_t&) noexcept; +[[nodiscard]] void* operator new(size_t size, std::align_val_t); +[[nodiscard]] void* operator new(size_t size, std::align_val_t, const std::nothrow_t&) noexcept; + void operator delete(void* ptr) noexcept; void operator delete(void* ptr, size_t) noexcept; +void operator delete(void* ptr, size_t, std::align_val_t) noexcept; + [[nodiscard]] void* operator new[](size_t size); [[nodiscard]] void* operator new[](size_t size, const std::nothrow_t&) noexcept; + void operator delete[](void* ptrs) noexcept; void operator delete[](void* ptr, size_t) noexcept; diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index d28f8af155..fc1fec3bdb 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -38,11 +38,9 @@ UNMAP_AFTER_INIT void Thread::initialize() KResultOr<NonnullRefPtr<Thread>> Thread::try_create(NonnullRefPtr<Process> process) { - // FIXME: Once we have aligned + nothrow operator new, we can avoid the manual kfree. - FPUState* fpu_state = (FPUState*)kmalloc_aligned<16>(sizeof(FPUState)); + auto fpu_state = try_make<FPUState>(); if (!fpu_state) return ENOMEM; - ArmedScopeGuard fpu_guard([fpu_state]() { kfree_aligned(fpu_state); }); auto kernel_stack_region = MM.allocate_kernel_region(default_kernel_stack_size, {}, Region::Access::Read | Region::Access::Write, AllocationStrategy::AllocateNow); if (!kernel_stack_region) @@ -53,18 +51,17 @@ KResultOr<NonnullRefPtr<Thread>> Thread::try_create(NonnullRefPtr<Process> proce if (!block_timer) return ENOMEM; - auto thread = adopt_ref_if_nonnull(new (nothrow) Thread(move(process), kernel_stack_region.release_nonnull(), block_timer.release_nonnull(), fpu_state)); + auto thread = adopt_ref_if_nonnull(new (nothrow) Thread(move(process), kernel_stack_region.release_nonnull(), block_timer.release_nonnull(), fpu_state.release_nonnull())); if (!thread) return ENOMEM; - fpu_guard.disarm(); return thread.release_nonnull(); } -Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Region> kernel_stack_region, NonnullRefPtr<Timer> block_timer, FPUState* fpu_state) +Thread::Thread(NonnullRefPtr<Process> process, NonnullOwnPtr<Region> kernel_stack_region, NonnullRefPtr<Timer> block_timer, NonnullOwnPtr<FPUState> fpu_state) : m_process(move(process)) , m_kernel_stack_region(move(kernel_stack_region)) - , m_fpu_state(fpu_state) + , m_fpu_state(move(fpu_state)) , m_name(m_process->name()) , m_block_timer(block_timer) , m_global_procfs_inode_index(ProcFSComponentRegistry::the().allocate_inode_index()) @@ -533,7 +530,6 @@ void Thread::finalize() if (m_dump_backtrace_on_finalization) dbgln("{}", backtrace()); - kfree_aligned(m_fpu_state); drop_thread_count(false); } diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 7b75b2a2b4..da5bcd751a 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1192,7 +1192,7 @@ public: String backtrace(); private: - Thread(NonnullRefPtr<Process>, NonnullOwnPtr<Region>, NonnullRefPtr<Timer>, FPUState*); + Thread(NonnullRefPtr<Process>, NonnullOwnPtr<Region>, NonnullRefPtr<Timer>, NonnullOwnPtr<FPUState>); IntrusiveListNode<Thread> m_process_thread_list_node; int m_runnable_priority { -1 }; @@ -1318,7 +1318,7 @@ private: unsigned m_ipv4_socket_read_bytes { 0 }; unsigned m_ipv4_socket_write_bytes { 0 }; - FPUState* m_fpu_state { nullptr }; + OwnPtr<FPUState> m_fpu_state; State m_state { Invalid }; String m_name; u32 m_priority { THREAD_PRIORITY_NORMAL }; |