File tree Expand file tree Collapse file tree 4 files changed +40
-20
lines changed Expand file tree Collapse file tree 4 files changed +40
-20
lines changed Original file line number Diff line number Diff line change 1212#include <linux/clocksource.h>
1313#include <linux/clockchips.h>
1414#include <linux/kernel_stat.h>
15+ #include <linux/math64.h>
1516
1617#include <asm/xen/hypervisor.h>
1718#include <asm/xen/hypercall.h>
@@ -150,11 +151,7 @@ static void do_stolen_accounting(void)
150151 if (stolen < 0 )
151152 stolen = 0 ;
152153
153- ticks = 0 ;
154- while (stolen >= NS_PER_TICK ) {
155- ticks ++ ;
156- stolen -= NS_PER_TICK ;
157- }
154+ ticks = iter_div_u64_rem (stolen , NS_PER_TICK , & stolen );
158155 __get_cpu_var (residual_stolen ) = stolen ;
159156 account_steal_time (NULL , ticks );
160157
@@ -166,11 +163,7 @@ static void do_stolen_accounting(void)
166163 if (blocked < 0 )
167164 blocked = 0 ;
168165
169- ticks = 0 ;
170- while (blocked >= NS_PER_TICK ) {
171- ticks ++ ;
172- blocked -= NS_PER_TICK ;
173- }
166+ ticks = iter_div_u64_rem (blocked , NS_PER_TICK , & blocked );
174167 __get_cpu_var (residual_blocked ) = blocked ;
175168 account_steal_time (idle_task (smp_processor_id ()), ticks );
176169}
Original file line number Diff line number Diff line change @@ -81,4 +81,25 @@ static inline s64 div_s64(s64 dividend, s32 divisor)
8181}
8282#endif
8383
84+ u32 iter_div_u64_rem (u64 dividend , u32 divisor , u64 * remainder );
85+
86+ static __always_inline u32
87+ __iter_div_u64_rem (u64 dividend , u32 divisor , u64 * remainder )
88+ {
89+ u32 ret = 0 ;
90+
91+ while (dividend >= divisor ) {
92+ /* The following asm() prevents the compiler from
93+ optimising this loop into a modulo operation. */
94+ asm("" : "+rm" (dividend ));
95+
96+ dividend -= divisor ;
97+ ret ++ ;
98+ }
99+
100+ * remainder = dividend ;
101+
102+ return ret ;
103+ }
104+
84105#endif /* _LINUX_MATH64_H */
Original file line number Diff line number Diff line change 66#ifdef __KERNEL__
77# include <linux/cache.h>
88# include <linux/seqlock.h>
9+ # include <linux/math64.h>
910#endif
1011
1112#ifndef _STRUCT_TIMESPEC
@@ -169,18 +170,13 @@ extern struct timeval ns_to_timeval(const s64 nsec);
169170 * timespec_add_ns - Adds nanoseconds to a timespec
170171 * @a: pointer to timespec to be incremented
171172 * @ns: unsigned nanoseconds value to be added
173+ *
174+ * This must always be inlined because its used from the x86-64 vdso,
175+ * which cannot call other kernel functions.
172176 */
173- static inline void timespec_add_ns (struct timespec * a , u64 ns )
177+ static __always_inline void timespec_add_ns (struct timespec * a , u64 ns )
174178{
175- ns += a -> tv_nsec ;
176- while (unlikely (ns >= NSEC_PER_SEC )) {
177- /* The following asm() prevents the compiler from
178- * optimising this loop into a modulo operation. */
179- asm("" : "+r" (ns ));
180-
181- ns -= NSEC_PER_SEC ;
182- a -> tv_sec ++ ;
183- }
179+ a -> tv_sec += __iter_div_u64_rem (a -> tv_nsec + ns , NSEC_PER_SEC , & ns );
184180 a -> tv_nsec = ns ;
185181}
186182#endif /* __KERNEL__ */
Original file line number Diff line number Diff line change @@ -98,3 +98,13 @@ EXPORT_SYMBOL(div64_u64);
9898#endif
9999
100100#endif /* BITS_PER_LONG == 32 */
101+
102+ /*
103+ * Iterative div/mod for use when dividend is not expected to be much
104+ * bigger than divisor.
105+ */
106+ u32 iter_div_u64_rem (u64 dividend , u32 divisor , u64 * remainder )
107+ {
108+ return __iter_div_u64_rem (dividend , divisor , remainder );
109+ }
110+ EXPORT_SYMBOL (iter_div_u64_rem );
You can’t perform that action at this time.
0 commit comments