diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index 3f45f124b1c..65de1af1466 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) +void Processor::smp_broadcast(Function callback, 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) -{ - 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) +void Processor::smp_unicast(u32 cpu, Function callback, 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) -{ - 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 4929ccba629..d17e1ffb236 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; + 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(&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 - static void smp_broadcast(Callback callback, bool async) - { - auto* data = new Callback(move(callback)); - smp_broadcast( - [](void* data) { - (*reinterpret_cast(data))(); - }, - data, - [](void* data) { - delete reinterpret_cast(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 - static void smp_unicast(u32 cpu, Callback callback, bool async) - { - auto* data = new Callback(move(callback)); - smp_unicast( - cpu, - [](void* data) { - (*reinterpret_cast(data))(); - }, - data, - [](void* data) { - delete reinterpret_cast(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, bool async); + static void smp_unicast(u32 cpu, Function, bool async); static void smp_broadcast_flush_tlb(const PageDirectory*, VirtualAddress, size_t); static u32 smp_wake_n_idle_processors(u32 wake_count);