kernel: Add CPUSet::{Clear, Set}BitAtomic() functions

This commit is contained in:
Pawel Dziepak 2014-01-24 01:40:06 +01:00
parent 03451e4cc1
commit 82bcd89b92
3 changed files with 39 additions and 22 deletions

View File

@ -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)));

View File

@ -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();

View File

@ -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);