mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 10:17:35 +00:00
Kernel/SMP: Make SMP message queueing work correctly
- Use the receiver's per-CPU entry in the message, instead of the sender's. (Using the sender's entry wasn't safe for broadcast messages since the same entry ended up on multiple message queues.) - Retry the CAS until it *succeeds* instead of *fails*. This closes a race window, and also ensures a correct return value. The return value is used by the caller to decide whether to broadcast an IPI. This was the main reason smp=on was so slow. We had CPUs busy-waiting until someone else triggered an IPI and moved things along. - Add a CPU pause hint to the spin loop. :^)
This commit is contained in:
parent
6283acb6b7
commit
ab5c422a29
1 changed files with 9 additions and 3 deletions
|
@ -863,12 +863,18 @@ bool Processor::smp_enqueue_message(ProcessorMessage& msg)
|
||||||
// Note that it's quite possible that the other processor may pop
|
// Note that it's quite possible that the other processor may pop
|
||||||
// the queue at any given time. We rely on the fact that the messages
|
// the queue at any given time. We rely on the fact that the messages
|
||||||
// are pooled and never get freed!
|
// are pooled and never get freed!
|
||||||
auto& msg_entry = msg.per_proc_entries[id()];
|
auto& msg_entry = msg.per_proc_entries[get_id()];
|
||||||
VERIFY(msg_entry.msg == &msg);
|
VERIFY(msg_entry.msg == &msg);
|
||||||
ProcessorMessageEntry* next = nullptr;
|
ProcessorMessageEntry* next = nullptr;
|
||||||
do {
|
for (;;) {
|
||||||
msg_entry.next = next;
|
msg_entry.next = next;
|
||||||
} while (m_message_queue.compare_exchange_strong(next, &msg_entry, AK::MemoryOrder::memory_order_acq_rel));
|
if (m_message_queue.compare_exchange_strong(next, &msg_entry, AK::MemoryOrder::memory_order_acq_rel))
|
||||||
|
break;
|
||||||
|
Processor::pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the enqueued message was the only message in the queue when posted,
|
||||||
|
// we return true. This is used by callers when deciding whether to generate an IPI.
|
||||||
return next == nullptr;
|
return next == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue