diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-05-20 02:06:57 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-20 09:09:10 +0200 |
commit | 8495d6aecaa338ce17172c762578617aefc60656 (patch) | |
tree | 110a4244bb7618e5590f8edc98b9f4913963f5dc | |
parent | cac7a8ced9437a3187ab8d63dad42219c3f5e8b0 (diff) | |
download | serenity-8495d6aecaa338ce17172c762578617aefc60656.zip |
Kernel: Use the Function class for smp_broadcast()/smp_unicast()
This avoids allocations for smp_broadcast() and smp_unicast() by
using the Function class.
-rw-r--r-- | Kernel/Arch/i386/CPU.cpp | 45 | ||||
-rw-r--r-- | Kernel/Arch/x86/CPU.h | 58 |
2 files changed, 25 insertions, 78 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index 3f45f124b1..65de1af146 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -1980,9 +1980,8 @@ UNMAP_AFTER_INIT void Processor::smp_enable() void Processor::smp_cleanup_message(ProcessorMessage& msg) { switch (msg.type) { - case ProcessorMessage::CallbackWithData: - if (msg.callback_with_data.free) - msg.callback_with_data.free(msg.callback_with_data.data); + case ProcessorMessage::Callback: + msg.callback_value().~Function(); break; default: break; @@ -2021,10 +2020,7 @@ bool Processor::smp_process_pending_messages() switch (msg->type) { case ProcessorMessage::Callback: - msg->callback.handler(); - break; - case ProcessorMessage::CallbackWithData: - msg->callback_with_data.handler(msg->callback_with_data.data); + msg->invoke_callback(); break; case ProcessorMessage::FlushTlb: if (is_user_address(VirtualAddress(msg->flush_tlb.ptr))) { @@ -2119,25 +2115,12 @@ void Processor::smp_broadcast_wait_sync(ProcessorMessage& msg) smp_return_to_pool(msg); } -void Processor::smp_broadcast(void (*callback)(void*), void* data, void (*free_data)(void*), bool async) -{ - auto& msg = smp_get_from_pool(); - msg.async = async; - msg.type = ProcessorMessage::CallbackWithData; - msg.callback_with_data.handler = callback; - msg.callback_with_data.data = data; - msg.callback_with_data.free = free_data; - smp_broadcast_message(msg); - if (!async) - smp_broadcast_wait_sync(msg); -} - -void Processor::smp_broadcast(void (*callback)(), bool async) +void Processor::smp_broadcast(Function<void()> callback, bool async) { auto& msg = smp_get_from_pool(); msg.async = async; - msg.type = ProcessorMessage::CallbackWithData; - msg.callback.handler = callback; + msg.type = ProcessorMessage::Callback; + new (msg.callback_storage) ProcessorMessage::CallbackFunction(move(callback)); smp_broadcast_message(msg); if (!async) smp_broadcast_wait_sync(msg); @@ -2174,21 +2157,11 @@ void Processor::smp_unicast_message(u32 cpu, ProcessorMessage& msg, bool async) } } -void Processor::smp_unicast(u32 cpu, void (*callback)(void*), void* data, void (*free_data)(void*), bool async) -{ - auto& msg = smp_get_from_pool(); - msg.type = ProcessorMessage::CallbackWithData; - msg.callback_with_data.handler = callback; - msg.callback_with_data.data = data; - msg.callback_with_data.free = free_data; - smp_unicast_message(cpu, msg, async); -} - -void Processor::smp_unicast(u32 cpu, void (*callback)(), bool async) +void Processor::smp_unicast(u32 cpu, Function<void()> callback, bool async) { auto& msg = smp_get_from_pool(); - msg.type = ProcessorMessage::CallbackWithData; - msg.callback.handler = callback; + msg.type = ProcessorMessage::Callback; + new (msg.callback_storage) ProcessorMessage::CallbackFunction(move(callback)); smp_unicast_message(cpu, msg, async); } diff --git a/Kernel/Arch/x86/CPU.h b/Kernel/Arch/x86/CPU.h index 4929ccba62..d17e1ffb23 100644 --- a/Kernel/Arch/x86/CPU.h +++ b/Kernel/Arch/x86/CPU.h @@ -574,23 +574,17 @@ struct MemoryManagerData; struct ProcessorMessageEntry; struct ProcessorMessage { + using CallbackFunction = Function<void()>; + enum Type { FlushTlb, Callback, - CallbackWithData }; Type type; volatile u32 refs; // atomic union { ProcessorMessage* next; // only valid while in the pool - struct { - void (*handler)(); - } callback; - struct { - void* data; - void (*handler)(void*); - void (*free)(void*); - } callback_with_data; + alignas(CallbackFunction) u8 callback_storage[sizeof(CallbackFunction)]; struct { const PageDirectory* page_directory; u8* ptr; @@ -601,6 +595,17 @@ struct ProcessorMessage { volatile bool async; ProcessorMessageEntry* per_proc_entries; + + CallbackFunction& callback_value() + { + return *bit_cast<CallbackFunction*>(&callback_storage); + } + + void invoke_callback() + { + VERIFY(type == Type::Callback); + callback_value()(); + } }; struct ProcessorMessageEntry { @@ -942,39 +947,8 @@ public: static void smp_enable(); bool smp_process_pending_messages(); - template<typename Callback> - static void smp_broadcast(Callback callback, bool async) - { - auto* data = new Callback(move(callback)); - smp_broadcast( - [](void* data) { - (*reinterpret_cast<Callback*>(data))(); - }, - data, - [](void* data) { - delete reinterpret_cast<Callback*>(data); - }, - async); - } - static void smp_broadcast(void (*callback)(), bool async); - static void smp_broadcast(void (*callback)(void*), void* data, void (*free_data)(void*), bool async); - template<typename Callback> - static void smp_unicast(u32 cpu, Callback callback, bool async) - { - auto* data = new Callback(move(callback)); - smp_unicast( - cpu, - [](void* data) { - (*reinterpret_cast<Callback*>(data))(); - }, - data, - [](void* data) { - delete reinterpret_cast<Callback*>(data); - }, - async); - } - static void smp_unicast(u32 cpu, void (*callback)(), bool async); - static void smp_unicast(u32 cpu, void (*callback)(void*), void* data, void (*free_data)(void*), bool async); + static void smp_broadcast(Function<void()>, bool async); + static void smp_unicast(u32 cpu, Function<void()>, bool async); static void smp_broadcast_flush_tlb(const PageDirectory*, VirtualAddress, size_t); static u32 smp_wake_n_idle_processors(u32 wake_count); |