Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24e4a8c3 authored by John Stultz's avatar John Stultz
Browse files

ktime: Kill non-scalar ktime_t implementation for 2038



The non-scalar ktime_t implementation is basically a timespec
which has to be changed to support dates past 2038 on 32bit
systems.

This patch removes the non-scalar ktime_t implementation, forcing
the scalar s64 nanosecond version on all architectures.

This may have additional performance overhead on some 32bit
systems when converting between ktime_t and timespec structures,
however the majority of 32bit systems (arm and i386) were already
using scalar ktime_t, so no performance regressions will be seen
on those platforms.

On affected platforms, I'm open to finding optimizations, including
avoiding converting to timespecs where possible.

[ tglx: We can now cleanup the ktime_t.tv64 mess, but thats a
  different issue and we can throw a coccinelle script at it ]

Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent 76f41088
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -64,7 +64,6 @@ config ARM
	select HAVE_UID16
	select HAVE_VIRT_CPU_ACCOUNTING_GEN
	select IRQ_FORCED_THREADING
	select KTIME_SCALAR
	select MODULES_USE_ELF_REL
	select NO_BOOTMEM
	select OLD_SIGACTION
+0 −1
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ config HEXAGON
	select GENERIC_IOMAP
	select GENERIC_SMP_IDLE_THREAD
	select STACKTRACE_SUPPORT
	select KTIME_SCALAR
	select GENERIC_CLOCKEVENTS
	select GENERIC_CLOCKEVENTS_BROADCAST
	select MODULES_USE_ELF_RELA
+0 −1
Original line number Diff line number Diff line
@@ -137,7 +137,6 @@ config S390
	select HAVE_SYSCALL_TRACEPOINTS
	select HAVE_UID16 if 32BIT
	select HAVE_VIRT_CPU_ACCOUNTING
	select KTIME_SCALAR if 32BIT
	select MODULES_USE_ELF_RELA
	select NO_BOOTMEM
	select OLD_SIGACTION
+0 −1
Original line number Diff line number Diff line
@@ -111,7 +111,6 @@ config X86
	select ARCH_CLOCKSOURCE_DATA
	select GENERIC_CLOCKEVENTS_BROADCAST if X86_64 || (X86_32 && X86_LOCAL_APIC)
	select GENERIC_TIME_VSYSCALL
	select KTIME_SCALAR if X86_32
	select GENERIC_STRNCPY_FROM_USER
	select GENERIC_STRNLEN_USER
	select HAVE_CONTEXT_TRACKING if X86_64
+1 −172
Original line number Diff line number Diff line
@@ -27,43 +27,19 @@
/*
 * ktime_t:
 *
 * On 64-bit CPUs a single 64-bit variable is used to store the hrtimers
 * A single 64-bit variable is used to store the hrtimers
 * internal representation of time values in scalar nanoseconds. The
 * design plays out best on 64-bit CPUs, where most conversions are
 * NOPs and most arithmetic ktime_t operations are plain arithmetic
 * operations.
 *
 * On 32-bit CPUs an optimized representation of the timespec structure
 * is used to avoid expensive conversions from and to timespecs. The
 * endian-aware order of the tv struct members is chosen to allow
 * mathematical operations on the tv64 member of the union too, which
 * for certain operations produces better code.
 *
 * For architectures with efficient support for 64/32-bit conversions the
 * plain scalar nanosecond based representation can be selected by the
 * config switch CONFIG_KTIME_SCALAR.
 */
union ktime {
	s64	tv64;
#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
	struct {
# ifdef __BIG_ENDIAN
	s32	sec, nsec;
# else
	s32	nsec, sec;
# endif
	} tv;
#endif
};

typedef union ktime ktime_t;		/* Kill this */

/*
 * ktime_t definitions when using the 64-bit scalar representation:
 */

#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)

/**
 * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
 * @secs:	seconds to set
@@ -123,153 +99,6 @@ static inline ktime_t timeval_to_ktime(struct timeval tv)
/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */
#define ktime_to_ns(kt)			((kt).tv64)

#else	/* !((BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)) */

/*
 * Helper macros/inlines to get the ktime_t math right in the timespec
 * representation. The macros are sometimes ugly - their actual use is
 * pretty okay-ish, given the circumstances. We do all this for
 * performance reasons. The pure scalar nsec_t based code was nice and
 * simple, but created too many 64-bit / 32-bit conversions and divisions.
 *
 * Be especially aware that negative values are represented in a way
 * that the tv.sec field is negative and the tv.nsec field is greater
 * or equal to zero but less than nanoseconds per second. This is the
 * same representation which is used by timespecs.
 *
 *   tv.sec < 0 and 0 >= tv.nsec < NSEC_PER_SEC
 */

/* Set a ktime_t variable to a value in sec/nsec representation: */
static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
{
	return (ktime_t) { .tv = { .sec = secs, .nsec = nsecs } };
}

/**
 * ktime_sub - subtract two ktime_t variables
 * @lhs:	minuend
 * @rhs:	subtrahend
 *
 * Return: The remainder of the subtraction.
 */
static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs)
{
	ktime_t res;

	res.tv64 = lhs.tv64 - rhs.tv64;
	if (res.tv.nsec < 0)
		res.tv.nsec += NSEC_PER_SEC;

	return res;
}

/**
 * ktime_add - add two ktime_t variables
 * @add1:	addend1
 * @add2:	addend2
 *
 * Return: The sum of @add1 and @add2.
 */
static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
{
	ktime_t res;

	res.tv64 = add1.tv64 + add2.tv64;
	/*
	 * performance trick: the (u32) -NSEC gives 0x00000000Fxxxxxxx
	 * so we subtract NSEC_PER_SEC and add 1 to the upper 32 bit.
	 *
	 * it's equivalent to:
	 *   tv.nsec -= NSEC_PER_SEC
	 *   tv.sec ++;
	 */
	if (res.tv.nsec >= NSEC_PER_SEC)
		res.tv64 += (u32)-NSEC_PER_SEC;

	return res;
}

/**
 * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
 * @kt:		addend
 * @nsec:	the scalar nsec value to add
 *
 * Return: The sum of @kt and @nsec in ktime_t format.
 */
extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);

/**
 * ktime_sub_ns - Subtract a scalar nanoseconds value from a ktime_t variable
 * @kt:		minuend
 * @nsec:	the scalar nsec value to subtract
 *
 * Return: The subtraction of @nsec from @kt in ktime_t format.
 */
extern ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec);

/**
 * timespec_to_ktime - convert a timespec to ktime_t format
 * @ts:		the timespec variable to convert
 *
 * Return: A ktime_t variable with the converted timespec value.
 */
static inline ktime_t timespec_to_ktime(const struct timespec ts)
{
	return (ktime_t) { .tv = { .sec = (s32)ts.tv_sec,
			   	   .nsec = (s32)ts.tv_nsec } };
}

/**
 * timeval_to_ktime - convert a timeval to ktime_t format
 * @tv:		the timeval variable to convert
 *
 * Return: A ktime_t variable with the converted timeval value.
 */
static inline ktime_t timeval_to_ktime(const struct timeval tv)
{
	return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec,
				   .nsec = (s32)(tv.tv_usec *
						 NSEC_PER_USEC) } };
}

/**
 * ktime_to_timespec - convert a ktime_t variable to timespec format
 * @kt:		the ktime_t variable to convert
 *
 * Return: The timespec representation of the ktime value.
 */
static inline struct timespec ktime_to_timespec(const ktime_t kt)
{
	return (struct timespec) { .tv_sec = (time_t) kt.tv.sec,
				   .tv_nsec = (long) kt.tv.nsec };
}

/**
 * ktime_to_timeval - convert a ktime_t variable to timeval format
 * @kt:		the ktime_t variable to convert
 *
 * Return: The timeval representation of the ktime value.
 */
static inline struct timeval ktime_to_timeval(const ktime_t kt)
{
	return (struct timeval) {
		.tv_sec = (time_t) kt.tv.sec,
		.tv_usec = (suseconds_t) (kt.tv.nsec / NSEC_PER_USEC) };
}

/**
 * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
 * @kt:		the ktime_t variable to convert
 *
 * Return: The scalar nanoseconds representation of @kt.
 */
static inline s64 ktime_to_ns(const ktime_t kt)
{
	return (s64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
}

#endif	/* !((BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)) */

/**
 * ktime_equal - Compares two ktime_t variables to see if they are equal
Loading