Kernel: Use the Function class for smp_broadcast()/smp_unicast()

This avoids allocations for smp_broadcast() and smp_unicast() by
using the Function class.
This commit is contained in:
Gunnar Beutner 2021-05-20 02:06:57 +02:00 committed by Andreas Kling
parent cac7a8ced9
commit 8495d6aeca
Notes: sideshowbarker 2024-07-18 17:43:19 +09:00
2 changed files with 25 additions and 78 deletions

View File

@ -1980,9 +1980,8 @@ UNMAP_AFTER_INIT void Processor::smp_enable()
void Processor::smp_cleanup_message(ProcessorMessage& msg) void Processor::smp_cleanup_message(ProcessorMessage& msg)
{ {
switch (msg.type) { switch (msg.type) {
case ProcessorMessage::CallbackWithData: case ProcessorMessage::Callback:
if (msg.callback_with_data.free) msg.callback_value().~Function();
msg.callback_with_data.free(msg.callback_with_data.data);
break; break;
default: default:
break; break;
@ -2021,10 +2020,7 @@ bool Processor::smp_process_pending_messages()
switch (msg->type) { switch (msg->type) {
case ProcessorMessage::Callback: case ProcessorMessage::Callback:
msg->callback.handler(); msg->invoke_callback();
break;
case ProcessorMessage::CallbackWithData:
msg->callback_with_data.handler(msg->callback_with_data.data);
break; break;
case ProcessorMessage::FlushTlb: case ProcessorMessage::FlushTlb:
if (is_user_address(VirtualAddress(msg->flush_tlb.ptr))) { 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); 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<void()> callback, bool async)
{ {
auto& msg = smp_get_from_pool(); auto& msg = smp_get_from_pool();
msg.async = async; msg.async = async;
msg.type = ProcessorMessage::CallbackWithData; msg.type = ProcessorMessage::Callback;
msg.callback_with_data.handler = callback; new (msg.callback_storage) ProcessorMessage::CallbackFunction(move(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;
smp_broadcast_message(msg); smp_broadcast_message(msg);
if (!async) if (!async)
smp_broadcast_wait_sync(msg); 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<void()> callback, bool async)
{ {
auto& msg = smp_get_from_pool(); auto& msg = smp_get_from_pool();
msg.type = ProcessorMessage::CallbackWithData; msg.type = ProcessorMessage::Callback;
msg.callback_with_data.handler = callback; new (msg.callback_storage) ProcessorMessage::CallbackFunction(move(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;
smp_unicast_message(cpu, msg, async); smp_unicast_message(cpu, msg, async);
} }

View File

@ -574,23 +574,17 @@ struct MemoryManagerData;
struct ProcessorMessageEntry; struct ProcessorMessageEntry;
struct ProcessorMessage { struct ProcessorMessage {
using CallbackFunction = Function<void()>;
enum Type { enum Type {
FlushTlb, FlushTlb,
Callback, Callback,
CallbackWithData
}; };
Type type; Type type;
volatile u32 refs; // atomic volatile u32 refs; // atomic
union { union {
ProcessorMessage* next; // only valid while in the pool ProcessorMessage* next; // only valid while in the pool
struct { alignas(CallbackFunction) u8 callback_storage[sizeof(CallbackFunction)];
void (*handler)();
} callback;
struct {
void* data;
void (*handler)(void*);
void (*free)(void*);
} callback_with_data;
struct { struct {
const PageDirectory* page_directory; const PageDirectory* page_directory;
u8* ptr; u8* ptr;
@ -601,6 +595,17 @@ struct ProcessorMessage {
volatile bool async; volatile bool async;
ProcessorMessageEntry* per_proc_entries; ProcessorMessageEntry* per_proc_entries;
CallbackFunction& callback_value()
{
return *bit_cast<CallbackFunction*>(&callback_storage);
}
void invoke_callback()
{
VERIFY(type == Type::Callback);
callback_value()();
}
}; };
struct ProcessorMessageEntry { struct ProcessorMessageEntry {
@ -942,39 +947,8 @@ public:
static void smp_enable(); static void smp_enable();
bool smp_process_pending_messages(); bool smp_process_pending_messages();
template<typename Callback> static void smp_broadcast(Function<void()>, bool async);
static void smp_broadcast(Callback callback, bool async) static void smp_unicast(u32 cpu, Function<void()>, 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_flush_tlb(const PageDirectory*, VirtualAddress, size_t); static void smp_broadcast_flush_tlb(const PageDirectory*, VirtualAddress, size_t);
static u32 smp_wake_n_idle_processors(u32 wake_count); static u32 smp_wake_n_idle_processors(u32 wake_count);