mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:37: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
|
||||
// the queue at any given time. We rely on the fact that the messages
|
||||
// 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);
|
||||
ProcessorMessageEntry* next = nullptr;
|
||||
do {
|
||||
for (;;) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue