spin_until_cond() will wait until nmi_ipi_busy == false, and
nmi_ipi_lock_start() does not seem to change nmi_ipi_busy, so there is
no way this while will ever repeat.
Replace this 'while' by an 'if', so it does not look like it can repeat.
Signed-off-by: Leonardo Bras <redacted>
---
arch/powerpc/kernel/smp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ea6adbf6a221..7c904d6fb4d2 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -473,7 +473,7 @@ static int __smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *),
return 0;
nmi_ipi_lock_start(&flags);
- while (nmi_ipi_busy) {
+ if (nmi_ipi_busy) {
nmi_ipi_unlock_end(&flags);
spin_until_cond(!nmi_ipi_busy);
nmi_ipi_lock_start(&flags);--
2.24.1
On Thu, Mar 26, 2020 at 05:37:52PM -0300, Leonardo Bras wrote:
spin_until_cond() will wait until nmi_ipi_busy == false, and
nmi_ipi_lock_start() does not seem to change nmi_ipi_busy, so there is
no way this while will ever repeat.
Replace this 'while' by an 'if', so it does not look like it can repeat.
Nack, it can repeat. The scenario is that cpu A is in this code,
inside spin_until_cond(); cpu B has previously set nmi_ipi_busy, and
cpu C is also waiting for nmi_ipi_busy to be cleared, like cpu A.
When cpu B clears nmi_ipi_busy, both cpu A and cpu C will see that and
will race inside nmi_ipi_lock_start(). One of them, say cpu C, will
take the lock and proceed to set nmi_ipi_busy and then call
nmi_ipi_unlock(). Then the other cpu (cpu A) will then take the lock
and return from nmi_ipi_lock_start() and find nmi_ipi_busy == true.
At that point it needs to go through the while loop body once more.
Paul.
On Fri, 2020-03-27 at 08:40 +1100, Paul Mackerras wrote:
On Thu, Mar 26, 2020 at 05:37:52PM -0300, Leonardo Bras wrote:
quoted
spin_until_cond() will wait until nmi_ipi_busy == false, and
nmi_ipi_lock_start() does not seem to change nmi_ipi_busy, so there is
no way this while will ever repeat.
Replace this 'while' by an 'if', so it does not look like it can repeat.
Nack, it can repeat. The scenario is that cpu A is in this code,
inside spin_until_cond(); cpu B has previously set nmi_ipi_busy, and
cpu C is also waiting for nmi_ipi_busy to be cleared, like cpu A.
When cpu B clears nmi_ipi_busy, both cpu A and cpu C will see that and
will race inside nmi_ipi_lock_start(). One of them, say cpu C, will
take the lock and proceed to set nmi_ipi_busy and then call
nmi_ipi_unlock(). Then the other cpu (cpu A) will then take the lock
and return from nmi_ipi_lock_start() and find nmi_ipi_busy == true.
At that point it needs to go through the while loop body once more.
Paul.
Ok, got it.
Thanks for explaining Paul!