Skip to content

Commit 561920a

Browse files
Suresh SiddhaJens Axboe
authored andcommitted
generic-ipi: fix the smp_mb() placement
smp_mb() is needed (to make the memory operations visible globally) before sending the ipi on the sender and the receiver (on Alpha atleast) needs smp_read_barrier_depends() in the handler before reading the call_single_queue list in a lock-free fashion. On x86, x2apic mode register accesses for sending IPI's don't have serializing semantics. So the need for smp_mb() before sending the IPI becomes more critical in x2apic mode. Remove the unnecessary smp_mb() in csd_flag_wait(), as the presence of that smp_mb() doesn't mean anything on the sender, when the ipi receiver is not doing any thing special (like memory fence) after clearing the CSD_FLAG_WAIT. Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
1 parent e78042e commit 561920a

File tree

1 file changed

+12
-6
lines changed

1 file changed

+12
-6
lines changed

kernel/smp.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ static void csd_flag_wait(struct call_single_data *data)
5151
{
5252
/* Wait for response */
5353
do {
54-
/*
55-
* We need to see the flags store in the IPI handler
56-
*/
57-
smp_mb();
5854
if (!(data->flags & CSD_FLAG_WAIT))
5955
break;
6056
cpu_relax();
@@ -76,6 +72,11 @@ static void generic_exec_single(int cpu, struct call_single_data *data)
7672
list_add_tail(&data->list, &dst->list);
7773
spin_unlock_irqrestore(&dst->lock, flags);
7874

75+
/*
76+
* Make the list addition visible before sending the ipi.
77+
*/
78+
smp_mb();
79+
7980
if (ipi)
8081
arch_send_call_function_single_ipi(cpu);
8182

@@ -157,7 +158,7 @@ void generic_smp_call_function_single_interrupt(void)
157158
* Need to see other stores to list head for checking whether
158159
* list is empty without holding q->lock
159160
*/
160-
smp_mb();
161+
smp_read_barrier_depends();
161162
while (!list_empty(&q->list)) {
162163
unsigned int data_flags;
163164

@@ -191,7 +192,7 @@ void generic_smp_call_function_single_interrupt(void)
191192
/*
192193
* See comment on outer loop
193194
*/
194-
smp_mb();
195+
smp_read_barrier_depends();
195196
}
196197
}
197198

@@ -370,6 +371,11 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
370371
list_add_tail_rcu(&data->csd.list, &call_function_queue);
371372
spin_unlock_irqrestore(&call_function_lock, flags);
372373

374+
/*
375+
* Make the list addition visible before sending the ipi.
376+
*/
377+
smp_mb();
378+
373379
/* Send a message to all CPUs in the map */
374380
arch_send_call_function_ipi(mask);
375381

0 commit comments

Comments
 (0)