From 9c08c836bf37bc395639b5e6d6aa1102c4c9c1a4 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 17 Mar 2026 12:08:59 -0400 Subject: [PATCH] kernel/smp: Use read spinlocks when prepending broadcast messages. Some brief testing shows that concurrency is unlikely here, but we might as well. --- src/system/kernel/smp.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index ff69ea1923..661787363e 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -732,6 +732,18 @@ return_free_message(struct smp_msg* msg) } +static void +prepend_message(struct smp_msg*& listHead, struct smp_msg* msg) +{ + struct smp_msg* next; + do { + cpu_pause(); + next = atomic_pointer_get(&listHead); + msg->next = next; + } while (atomic_pointer_test_and_set(&listHead, msg, next) != next); +} + + static struct smp_msg* check_for_message(int currentCPU, mailbox_source& sourceMailbox) { @@ -1010,13 +1022,7 @@ smp_send_ici(int32 targetCPU, int32 message, addr_t data, addr_t data2, msg->done = 0; // stick it in the appropriate cpu's mailbox - struct smp_msg* next; - do { - cpu_pause(); - next = atomic_pointer_get(&sCPUMessages[targetCPU]); - msg->next = next; - } while (atomic_pointer_test_and_set(&sCPUMessages[targetCPU], msg, - next) != next); + prepend_message(sCPUMessages[targetCPU], msg); arch_smp_send_ici(targetCPU); @@ -1079,10 +1085,9 @@ smp_broadcast_ici(int32 message, addr_t data, addr_t data2, addr_t data3, "mbox\n", currentCPU, msg); // stick it in the appropriate cpu's mailbox - acquire_write_spinlock_nocheck(&sBroadcastMessageSpinlock); - msg->next = sBroadcastMessages; - sBroadcastMessages = msg; - release_write_spinlock(&sBroadcastMessageSpinlock); + acquire_read_spinlock_nocheck(&sBroadcastMessageSpinlock); + prepend_message(sBroadcastMessages, msg); + release_read_spinlock(&sBroadcastMessageSpinlock); atomic_add(&sBroadcastMessageCounter, 1); @@ -1156,10 +1161,9 @@ smp_multicast_ici(const CPUSet& cpuMask, int32 message, addr_t data, || (self && targetCPUs == sNumCPUs); // stick it in the broadcast mailbox - acquire_write_spinlock_nocheck(&sBroadcastMessageSpinlock); - msg->next = sBroadcastMessages; - sBroadcastMessages = msg; - release_write_spinlock(&sBroadcastMessageSpinlock); + acquire_read_spinlock_nocheck(&sBroadcastMessageSpinlock); + prepend_message(sBroadcastMessages, msg); + release_read_spinlock(&sBroadcastMessageSpinlock); atomic_add(&sBroadcastMessageCounter, 1); for (int32 i = 0; i < sNumCPUs; i++) {