summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-05-20 02:06:57 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-20 09:09:10 +0200
commit8495d6aecaa338ce17172c762578617aefc60656 (patch)
tree110a4244bb7618e5590f8edc98b9f4913963f5dc
parentcac7a8ced9437a3187ab8d63dad42219c3f5e8b0 (diff)
downloadserenity-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.cpp45
-rw-r--r--Kernel/Arch/x86/CPU.h58
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);