Skip to content

Commit

Permalink
ARC: SMP resurrect #17: cpu_relax() needs to be compiler barrier too
Browse files Browse the repository at this point in the history
A lot of SMP loops are based off of loads from memory.

	while (p->on_cpu) {
		cpu_relax();
	}

However the data involved is not volatile - which makes gcc prune away
the load, resulting in unconditional branch-to-self.

The first instance was csd_lock_wait() which I though of fixing by
making call_single_data->flag as volatile.

However next got a loop in try_to_wake_up(), which busy-waits on
task_struct->cpu.

So the solution (ugly as it may be) is to make cpu_relax() a memory
barrier which solves both the above cases (as intended, not by fluke).
Incidently, Documentation/volatile-considered-harmful.txt seems to
confirm that cpu_relax() indeed has to be a barrier.

As a small optimization, it has been done only for SMP case.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
  • Loading branch information
vineetgarc committed Oct 25, 2012
1 parent 5eb0ea2 commit 3173487
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion arch/arc/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@ unsigned long thread_saved_pc(struct task_struct *t);
/* Prepare to copy thread state - unlazy all lazy status */
#define prepare_to_copy(tsk) do { } while (0)

#define cpu_relax() do { } while (0)
/*
* A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
* get optimised away by gcc
*/
#ifdef CONFIG_SMP
#define cpu_relax() __asm__ __volatile__ ("" : : : "memory")
#else
#define cpu_relax() do { } while (0)
#endif

/*
* Create a new kernel thread
Expand Down

0 comments on commit 3173487

Please sign in to comment.