aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Deacon <[email protected]>2010-05-24 12:11:43 -0700
committerIngo Molnar <[email protected]>2010-06-25 16:11:50 +0200
commit0d98bb2656e9bd2dfda2d089db1fe1dbdab41504 (patch)
tree2172bbdd7fb21640062b2a692ded3d9cebc2382c
parent3c93717cfa51316e4dbb471e7c0f9d243359d5f8 (diff)
sched: Prevent compiler from optimising the sched_avg_update() loop
GCC 4.4.1 on ARM has been observed to replace the while loop in sched_avg_update with a call to uldivmod, resulting in the following build failure at link-time: kernel/built-in.o: In function `sched_avg_update': kernel/sched.c:1261: undefined reference to `__aeabi_uldivmod' kernel/sched.c:1261: undefined reference to `__aeabi_uldivmod' make: *** [.tmp_vmlinux1] Error 1 This patch introduces a fake data hazard to the loop body to prevent the compiler optimising the loop away. Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Acked-by: Peter Zijlstra <[email protected]> Cc: Catalin Marinas <[email protected]> Cc: Russell King <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
-rw-r--r--kernel/sched.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 6c9e7c8735bf..a24d6d5d83f6 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1254,6 +1254,12 @@ static void sched_avg_update(struct rq *rq)
s64 period = sched_avg_period();
while ((s64)(rq->clock - rq->age_stamp) > period) {
+ /*
+ * Inline assembly required to prevent the compiler
+ * optimising this loop into a divmod call.
+ * See __iter_div_u64_rem() for another example of this.
+ */
+ asm("" : "+rm" (rq->age_stamp));
rq->age_stamp += period;
rq->rt_avg /= 2;
}