Skip to content

Commit 20d0873

Browse files
arndbKAGA-KOKO
authored andcommitted
time: Optimize ns_to_timespec64()
ns_to_timespec64() calls div_s64_rem(), which is a rather slow function on 32-bit architectures, as it cannot take advantage of the do_div() optimizations for constant arguments. Open-code the div_s64_rem() function in ns_to_timespec64(), so a constant divider can be passed into the optimized div_u64_rem() function. Signed-off-by: Arnd Bergmann <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 5614473 commit 20d0873

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

kernel/time/time.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -550,18 +550,21 @@ EXPORT_SYMBOL(set_normalized_timespec64);
550550
*/
551551
struct timespec64 ns_to_timespec64(const s64 nsec)
552552
{
553-
struct timespec64 ts;
553+
struct timespec64 ts = { 0, 0 };
554554
s32 rem;
555555

556-
if (!nsec)
557-
return (struct timespec64) {0, 0};
558-
559-
ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
560-
if (unlikely(rem < 0)) {
561-
ts.tv_sec--;
562-
rem += NSEC_PER_SEC;
556+
if (likely(nsec > 0)) {
557+
ts.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
558+
ts.tv_nsec = rem;
559+
} else if (nsec < 0) {
560+
/*
561+
* With negative times, tv_sec points to the earlier
562+
* second, and tv_nsec counts the nanoseconds since
563+
* then, so tv_nsec is always a positive number.
564+
*/
565+
ts.tv_sec = -div_u64_rem(-nsec - 1, NSEC_PER_SEC, &rem) - 1;
566+
ts.tv_nsec = NSEC_PER_SEC - rem - 1;
563567
}
564-
ts.tv_nsec = rem;
565568

566569
return ts;
567570
}

0 commit comments

Comments
 (0)