kernel/smp: Move the per-CPU SMP message mailbox into cpu_ent.
Putting all the per-CPU messages in one array means they'll all be on the same cache lines. The cpu_ent structure is cache-line-aligned, so this means they'll be on separate cache lines.
This commit is contained in:
@@ -64,6 +64,7 @@ typedef struct CACHE_LINE_ALIGN cpu_ent {
|
|||||||
bigtime_t last_kernel_time;
|
bigtime_t last_kernel_time;
|
||||||
bigtime_t last_user_time;
|
bigtime_t last_user_time;
|
||||||
|
|
||||||
|
struct smp_msg* cpu_msg;
|
||||||
int32 ici_counter;
|
int32 ici_counter;
|
||||||
|
|
||||||
// used in the kernel debugger
|
// used in the kernel debugger
|
||||||
|
|||||||
+13
-14
@@ -97,8 +97,6 @@ static struct smp_msg* sFreeMessages = NULL;
|
|||||||
static int32 sFreeMessageCount = 0;
|
static int32 sFreeMessageCount = 0;
|
||||||
static rw_spinlock sFreeMessageSpinlock = B_RW_SPINLOCK_INITIALIZER;
|
static rw_spinlock sFreeMessageSpinlock = B_RW_SPINLOCK_INITIALIZER;
|
||||||
|
|
||||||
static struct smp_msg* sCPUMessages[SMP_MAX_CPUS] = { NULL, };
|
|
||||||
|
|
||||||
static struct smp_msg* sBroadcastMessages = NULL;
|
static struct smp_msg* sBroadcastMessages = NULL;
|
||||||
static rw_spinlock sBroadcastMessageSpinlock = B_RW_SPINLOCK_INITIALIZER;
|
static rw_spinlock sBroadcastMessageSpinlock = B_RW_SPINLOCK_INITIALIZER;
|
||||||
static int32 sBroadcastMessageCounter;
|
static int32 sBroadcastMessageCounter;
|
||||||
@@ -214,7 +212,7 @@ update_lock_held(spinlock* lock)
|
|||||||
#endif // B_DEBUG_SPINLOCK_CONTENTION
|
#endif // B_DEBUG_SPINLOCK_CONTENTION
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
dump_ici_messages(int argc, char** argv)
|
dump_ici_messages(int argc, char** argv)
|
||||||
{
|
{
|
||||||
// count broadcast messages
|
// count broadcast messages
|
||||||
@@ -239,14 +237,14 @@ dump_ici_messages(int argc, char** argv)
|
|||||||
// count per-CPU messages
|
// count per-CPU messages
|
||||||
for (int32 i = 0; i < sNumCPUs; i++) {
|
for (int32 i = 0; i < sNumCPUs; i++) {
|
||||||
count = 0;
|
count = 0;
|
||||||
message = sCPUMessages[i];
|
message = gCPU[i].cpu_msg;
|
||||||
while (message != NULL) {
|
while (message != NULL) {
|
||||||
count++;
|
count++;
|
||||||
message = message->next;
|
message = message->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("CPU %" B_PRId32 " messages: %" B_PRId32 ", first: %p\n", i,
|
kprintf("CPU %" B_PRId32 " messages: %" B_PRId32 ", first: %p\n", i,
|
||||||
count, sCPUMessages[i]);
|
count, gCPU[i].cpu_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -733,12 +731,12 @@ return_free_message(struct smp_msg* msg)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
prepend_message(struct smp_msg*& listHead, struct smp_msg* msg)
|
prepend_message(struct smp_msg*& mailbox, struct smp_msg* msg)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
struct smp_msg* next = atomic_pointer_get(&listHead);
|
struct smp_msg* next = atomic_pointer_get(&mailbox);
|
||||||
msg->next = next;
|
msg->next = next;
|
||||||
if (atomic_pointer_test_and_set(&listHead, msg, next) == next)
|
if (atomic_pointer_test_and_set(&mailbox, msg, next) == next)
|
||||||
break;
|
break;
|
||||||
cpu_pause();
|
cpu_pause();
|
||||||
}
|
}
|
||||||
@@ -751,15 +749,16 @@ check_for_message(int currentCPU, mailbox_source& sourceMailbox)
|
|||||||
if (!sICIEnabled)
|
if (!sICIEnabled)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
struct smp_msg* msg = atomic_pointer_get(&sCPUMessages[currentCPU]);
|
struct smp_msg** mailbox = &gCPU[currentCPU].cpu_msg;
|
||||||
|
struct smp_msg* msg = atomic_pointer_get(mailbox);
|
||||||
if (msg != NULL) {
|
if (msg != NULL) {
|
||||||
// since only this CPU ever dequeues, we can just use atomics
|
// since only this CPU ever dequeues, we can just use atomics
|
||||||
while (true) {
|
while (true) {
|
||||||
if (atomic_pointer_test_and_set(&sCPUMessages[currentCPU], msg->next, msg) == msg)
|
if (atomic_pointer_test_and_set(mailbox, msg->next, msg) == msg)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
cpu_pause();
|
cpu_pause();
|
||||||
msg = atomic_pointer_get(&sCPUMessages[currentCPU]);
|
msg = atomic_pointer_get(mailbox);
|
||||||
ASSERT(msg != NULL);
|
ASSERT(msg != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,7 +778,7 @@ check_for_message(int currentCPU, mailbox_source& sourceMailbox)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark it so we wont try to process this one again
|
// mark it so we won't try to process this one again
|
||||||
msg->proc_bitmap.ClearBitAtomic(currentCPU);
|
msg->proc_bitmap.ClearBitAtomic(currentCPU);
|
||||||
atomic_add(&gCPU[currentCPU].ici_counter, 1);
|
atomic_add(&gCPU[currentCPU].ici_counter, 1);
|
||||||
|
|
||||||
@@ -1029,7 +1028,7 @@ smp_send_ici(int32 targetCPU, int32 message, addr_t data, addr_t data2,
|
|||||||
msg->done = 0;
|
msg->done = 0;
|
||||||
|
|
||||||
// stick it in the appropriate cpu's mailbox
|
// stick it in the appropriate cpu's mailbox
|
||||||
prepend_message(sCPUMessages[targetCPU], msg);
|
prepend_message(gCPU[targetCPU].cpu_msg, msg);
|
||||||
|
|
||||||
arch_smp_send_ici(targetCPU);
|
arch_smp_send_ici(targetCPU);
|
||||||
|
|
||||||
@@ -1171,7 +1170,7 @@ smp_multicast_ici(const CPUSet& cpuMask, int32 message, addr_t data,
|
|||||||
|
|
||||||
if ((!self && targetCPUs == 1) || (self && targetCPUs == 2)) {
|
if ((!self && targetCPUs == 1) || (self && targetCPUs == 2)) {
|
||||||
// stick it in the appropriate cpu's mailbox
|
// stick it in the appropriate cpu's mailbox
|
||||||
prepend_message(sCPUMessages[firstNonCurrentCPU], msg);
|
prepend_message(gCPU[firstNonCurrentCPU].cpu_msg, msg);
|
||||||
|
|
||||||
arch_smp_send_ici(firstNonCurrentCPU);
|
arch_smp_send_ici(firstNonCurrentCPU);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user