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.
Unified · Split
| @@ -1254,6 +1254,12 @@ static void sched_avg_update(struct rq *rq) · 1253 unmodified lines | |||
| 1254 | s64 period = sched_avg_period(); | 1254 | s64 period = sched_avg_period(); |
| 1255 | 1255 | ||
| 1256 | while ((s64)(rq->clock - rq->age_stamp) > period) { | 1256 | while ((s64)(rq->clock - rq->age_stamp) > period) { |
| 1257 | /* | ||
| 1258 | * Inline assembly required to prevent the compiler | ||
| 1259 | * optimising this loop into a divmod call. | ||
| 1260 | * See __iter_div_u64_rem() for another example of this. | ||
| 1261 | */ | ||
| 1262 | asm("" : "+rm" (rq->age_stamp)); | ||
| 1257 | rq->age_stamp += period; | 1263 | rq->age_stamp += period; |
| 1258 | rq->rt_avg /= 2; | 1264 | rq->rt_avg /= 2; |
| 1259 | } | 1265 | } |