diff --git a/headers/private/kernel/smp.h b/headers/private/kernel/smp.h index 43126eb697..0da58a0cd3 100644 --- a/headers/private/kernel/smp.h +++ b/headers/private/kernel/smp.h @@ -50,6 +50,9 @@ public: inline void SetBit(int32 cpu); inline void ClearBit(int32 cpu); + inline void SetBitAtomic(int32 cpu); + inline void ClearBitAtomic(int32 cpu); + inline bool GetBit(int32 cpu) const; inline bool IsEmpty() const; @@ -118,12 +121,28 @@ inline void CPUSet::SetBit(int32 cpu) { int32* element = (int32*)&fBitmap[cpu % kArraySize]; - atomic_or(element, 1u << (cpu / kArraySize)); + *element |= 1u << (cpu / kArraySize); } inline void CPUSet::ClearBit(int32 cpu) +{ + int32* element = (int32*)&fBitmap[cpu % kArraySize]; + *element &= ~uint32(1u << (cpu / kArraySize)); +} + + +inline void +CPUSet::SetBitAtomic(int32 cpu) +{ + int32* element = (int32*)&fBitmap[cpu % kArraySize]; + atomic_or(element, 1u << (cpu / kArraySize)); +} + + +inline void +CPUSet::ClearBitAtomic(int32 cpu) { int32* element = (int32*)&fBitmap[cpu % kArraySize]; atomic_and(element, ~uint32(1u << (cpu / kArraySize))); diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index 9fbbaa3ad3..11031b5264 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -229,8 +229,8 @@ arch_thread_context_switch(Thread* from, Thread* to) != activePagingStructures) { // update on which CPUs the address space is used int cpu = cpuData->cpu_num; - activePagingStructures->active_on_cpus.ClearBit(cpu); - toPagingStructures->active_on_cpus.SetBit(cpu); + activePagingStructures->active_on_cpus.ClearBitAtomic(cpu); + toPagingStructures->active_on_cpus.SetBitAtomic(cpu); // assign the new paging structures to the CPU toPagingStructures->AddReference(); diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index 325fa7206d..4c4b357f68 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -822,7 +822,7 @@ check_for_message(int currentCPU, mailbox_source& sourceMailbox) } // mark it so we wont try to process this one again - msg->proc_bitmap.ClearBit(currentCPU); + msg->proc_bitmap.ClearBitAtomic(currentCPU); atomic_add(&gCPU[currentCPU].ici_counter, 1); sourceMailbox = MAILBOX_BCAST; @@ -1000,7 +1000,7 @@ static void process_early_cpu_call(int32 cpu) { sEarlyCPUCallFunction(sEarlyCPUCallCookie, cpu); - sEarlyCPUCallSet.ClearBit(cpu); + sEarlyCPUCallSet.ClearBitAtomic(cpu); atomic_add(&sEarlyCPUCallCount, 1); } @@ -1112,21 +1112,25 @@ smp_send_multicast_ici(CPUSet& cpuMask, int32 message, addr_t data, return; int currentCPU = smp_get_current_cpu(); - bool broadcast = true; - - // count target CPUs - int32 targetCPUs = 0; - for (int32 i = 0; i < sNumCPUs; i++) { - if (cpuMask.GetBit(i)) - targetCPUs++; - else if (i != currentCPU) - broadcast = false; - } // find_free_message leaves interrupts disabled struct smp_msg *msg; int state = find_free_message(&msg); + msg->proc_bitmap = cpuMask; + msg->proc_bitmap.ClearBit(currentCPU); + + int32 targetCPUs = 0; + for (int32 i = 0; i < sNumCPUs; i++) { + if (msg->proc_bitmap.GetBit(i)) + targetCPUs++; + } + + if (targetCPUs == 0) { + panic("smp_send_multicast_ici(): 0 CPU mask"); + return; + } + msg->message = message; msg->data = data; msg->data2 = data2; @@ -1136,13 +1140,7 @@ smp_send_multicast_ici(CPUSet& cpuMask, int32 message, addr_t data, msg->flags = flags; msg->done = 0; - msg->proc_bitmap = cpuMask; - msg->proc_bitmap.ClearBit(currentCPU); - if (msg->proc_bitmap.IsEmpty()) { - panic("smp_send_multicast_ici(): 0 CPU mask"); - return; - } - + bool broadcast = targetCPUs == sNumCPUs - 1; // stick it in the broadcast mailbox acquire_spinlock_nocheck(&sBroadcastMessageSpinlock);