[Top] [All Lists]

[PATCH] MIPS: Fix the reentrancy problem of synchronise_count_slave()

Subject: [PATCH] MIPS: Fix the reentrancy problem of synchronise_count_slave()
From: Wu Zhangjin <>
Date: Sat, 26 Mar 2011 04:21:29 +0800
Cc: Ralf Baechle <>
Original-recipient: rfc822;
From: Wu Zhangjin <>

CPU stall has been observed when SYNC_R4K=y and CONFIG_HOTPLUG=y. The root
cause is that synchronise_count_slave() is not reenterable after SMP bootstrap
but the cpu online interface(cpu_up) will call it at SMP bootstrap and also
when 1 is written to /sys/devices/system/cpu/cpuX/online from user-space.

The scene looks like this:


                atomic_set(&count_count_start, 0);

count_count_start is set to 0 after all cpus are online:


        ncpus = num_online_cpus();
        for (i = 0; i < NR_LOOPS; i++) {
                while (atomic_read(&count_count_start) != ncpus)

In user-space, If one cpu is offline and online later,
synchronise_count_slave() will be called again, count_count_start is always 1
and will never equal to ncpus, therefore, the cpu will loop in the above while
and stall at last.

Except the above scene, after SMP bootstrap, whenever cpu_up() is called,
synchronise_count_slave() will be reentered, Similar stall will happen.

And in reality, If R4K is synced in SMP bootstrap, no need to re-sync it.

Therefore, to fix the reentrancy problem, this adds sync_finish_flag, set it to
1 after all cpus are synced and check it when enter into
synchronise_count_slave(), if sync_finish_flag is set, don't reenter but return

Signed-off-by: Wu Zhangjin <>
 arch/mips/kernel/sync-r4k.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c
index 05dd170..ebba8c9 100644
--- a/arch/mips/kernel/sync-r4k.c
+++ b/arch/mips/kernel/sync-r4k.c
@@ -24,6 +24,7 @@ static atomic_t __cpuinitdata count_start_flag = 
 static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0);
 static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0);
 static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata sync_finish_flag = ATOMIC_INIT(0);
 #define COUNTON        100
 #define NR_LOOPS 5
@@ -106,6 +107,9 @@ void __cpuinit synchronise_count_master(void)
         * so no point in alarming people
+       /* Safely mark the finish flag here */
+       atomic_set(&sync_finish_flag, 1);
 void __cpuinit synchronise_count_slave(void)
@@ -123,6 +127,10 @@ void __cpuinit synchronise_count_slave(void)
+       /* No need to re-sync it when sync have been done */
+       if (atomic_read(&sync_finish_flag))
+               return;

<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH] MIPS: Fix the reentrancy problem of synchronise_count_slave(), Wu Zhangjin <=