xref: /openbmc/linux/include/linux/time64.h (revision 361a3bf00582469877f8d18ff20f1efa6b781274)
1*361a3bf0SJohn Stultz #ifndef _LINUX_TIME64_H
2*361a3bf0SJohn Stultz #define _LINUX_TIME64_H
3*361a3bf0SJohn Stultz 
4*361a3bf0SJohn Stultz #include <uapi/linux/time.h>
5*361a3bf0SJohn Stultz 
6*361a3bf0SJohn Stultz typedef __s64 time64_t;
7*361a3bf0SJohn Stultz 
8*361a3bf0SJohn Stultz /*
9*361a3bf0SJohn Stultz  * This wants to go into uapi/linux/time.h once we agreed about the
10*361a3bf0SJohn Stultz  * userspace interfaces.
11*361a3bf0SJohn Stultz  */
12*361a3bf0SJohn Stultz #if __BITS_PER_LONG == 64
13*361a3bf0SJohn Stultz # define timespec64 timespec
14*361a3bf0SJohn Stultz #else
15*361a3bf0SJohn Stultz struct timespec64 {
16*361a3bf0SJohn Stultz 	time64_t	tv_sec;			/* seconds */
17*361a3bf0SJohn Stultz 	long		tv_nsec;		/* nanoseconds */
18*361a3bf0SJohn Stultz };
19*361a3bf0SJohn Stultz #endif
20*361a3bf0SJohn Stultz 
21*361a3bf0SJohn Stultz /* Parameters used to convert the timespec values: */
22*361a3bf0SJohn Stultz #define MSEC_PER_SEC	1000L
23*361a3bf0SJohn Stultz #define USEC_PER_MSEC	1000L
24*361a3bf0SJohn Stultz #define NSEC_PER_USEC	1000L
25*361a3bf0SJohn Stultz #define NSEC_PER_MSEC	1000000L
26*361a3bf0SJohn Stultz #define USEC_PER_SEC	1000000L
27*361a3bf0SJohn Stultz #define NSEC_PER_SEC	1000000000L
28*361a3bf0SJohn Stultz #define FSEC_PER_SEC	1000000000000000LL
29*361a3bf0SJohn Stultz 
30*361a3bf0SJohn Stultz /* Located here for timespec[64]_valid_strict */
31*361a3bf0SJohn Stultz #define KTIME_MAX			((s64)~((u64)1 << 63))
32*361a3bf0SJohn Stultz #define KTIME_SEC_MAX			(KTIME_MAX / NSEC_PER_SEC)
33*361a3bf0SJohn Stultz 
34*361a3bf0SJohn Stultz #if __BITS_PER_LONG == 64
35*361a3bf0SJohn Stultz 
36*361a3bf0SJohn Stultz # define timespec64_equal		timespec_equal
37*361a3bf0SJohn Stultz # define timespec64_compare		timespec_compare
38*361a3bf0SJohn Stultz # define set_normalized_timespec64	set_normalized_timespec
39*361a3bf0SJohn Stultz # define timespec64_add_safe		timespec_add_safe
40*361a3bf0SJohn Stultz # define timespec64_add			timespec_add
41*361a3bf0SJohn Stultz # define timespec64_sub			timespec_sub
42*361a3bf0SJohn Stultz # define timespec64_valid		timespec_valid
43*361a3bf0SJohn Stultz # define timespec64_valid_strict	timespec_valid_strict
44*361a3bf0SJohn Stultz # define timespec64_to_ns		timespec_to_ns
45*361a3bf0SJohn Stultz # define ns_to_timespec64		ns_to_timespec
46*361a3bf0SJohn Stultz # define timespec64_add_ns		timespec_add_ns
47*361a3bf0SJohn Stultz 
48*361a3bf0SJohn Stultz #else
49*361a3bf0SJohn Stultz 
50*361a3bf0SJohn Stultz static inline int timespec64_equal(const struct timespec64 *a,
51*361a3bf0SJohn Stultz 				   const struct timespec64 *b)
52*361a3bf0SJohn Stultz {
53*361a3bf0SJohn Stultz 	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
54*361a3bf0SJohn Stultz }
55*361a3bf0SJohn Stultz 
56*361a3bf0SJohn Stultz /*
57*361a3bf0SJohn Stultz  * lhs < rhs:  return <0
58*361a3bf0SJohn Stultz  * lhs == rhs: return 0
59*361a3bf0SJohn Stultz  * lhs > rhs:  return >0
60*361a3bf0SJohn Stultz  */
61*361a3bf0SJohn Stultz static inline int timespec64_compare(const struct timespec64 *lhs, const struct timespec64 *rhs)
62*361a3bf0SJohn Stultz {
63*361a3bf0SJohn Stultz 	if (lhs->tv_sec < rhs->tv_sec)
64*361a3bf0SJohn Stultz 		return -1;
65*361a3bf0SJohn Stultz 	if (lhs->tv_sec > rhs->tv_sec)
66*361a3bf0SJohn Stultz 		return 1;
67*361a3bf0SJohn Stultz 	return lhs->tv_nsec - rhs->tv_nsec;
68*361a3bf0SJohn Stultz }
69*361a3bf0SJohn Stultz 
70*361a3bf0SJohn Stultz extern void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec);
71*361a3bf0SJohn Stultz 
72*361a3bf0SJohn Stultz /*
73*361a3bf0SJohn Stultz  * timespec64_add_safe assumes both values are positive and checks for
74*361a3bf0SJohn Stultz  * overflow. It will return TIME_T_MAX if the returned value would be
75*361a3bf0SJohn Stultz  * smaller then either of the arguments.
76*361a3bf0SJohn Stultz  */
77*361a3bf0SJohn Stultz extern struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
78*361a3bf0SJohn Stultz 					 const struct timespec64 rhs);
79*361a3bf0SJohn Stultz 
80*361a3bf0SJohn Stultz 
81*361a3bf0SJohn Stultz static inline struct timespec64 timespec64_add(struct timespec64 lhs,
82*361a3bf0SJohn Stultz 						struct timespec64 rhs)
83*361a3bf0SJohn Stultz {
84*361a3bf0SJohn Stultz 	struct timespec64 ts_delta;
85*361a3bf0SJohn Stultz 	set_normalized_timespec64(&ts_delta, lhs.tv_sec + rhs.tv_sec,
86*361a3bf0SJohn Stultz 				lhs.tv_nsec + rhs.tv_nsec);
87*361a3bf0SJohn Stultz 	return ts_delta;
88*361a3bf0SJohn Stultz }
89*361a3bf0SJohn Stultz 
90*361a3bf0SJohn Stultz /*
91*361a3bf0SJohn Stultz  * sub = lhs - rhs, in normalized form
92*361a3bf0SJohn Stultz  */
93*361a3bf0SJohn Stultz static inline struct timespec64 timespec64_sub(struct timespec64 lhs,
94*361a3bf0SJohn Stultz 						struct timespec64 rhs)
95*361a3bf0SJohn Stultz {
96*361a3bf0SJohn Stultz 	struct timespec64 ts_delta;
97*361a3bf0SJohn Stultz 	set_normalized_timespec64(&ts_delta, lhs.tv_sec - rhs.tv_sec,
98*361a3bf0SJohn Stultz 				lhs.tv_nsec - rhs.tv_nsec);
99*361a3bf0SJohn Stultz 	return ts_delta;
100*361a3bf0SJohn Stultz }
101*361a3bf0SJohn Stultz 
102*361a3bf0SJohn Stultz /*
103*361a3bf0SJohn Stultz  * Returns true if the timespec64 is norm, false if denorm:
104*361a3bf0SJohn Stultz  */
105*361a3bf0SJohn Stultz static inline bool timespec64_valid(const struct timespec64 *ts)
106*361a3bf0SJohn Stultz {
107*361a3bf0SJohn Stultz 	/* Dates before 1970 are bogus */
108*361a3bf0SJohn Stultz 	if (ts->tv_sec < 0)
109*361a3bf0SJohn Stultz 		return false;
110*361a3bf0SJohn Stultz 	/* Can't have more nanoseconds then a second */
111*361a3bf0SJohn Stultz 	if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
112*361a3bf0SJohn Stultz 		return false;
113*361a3bf0SJohn Stultz 	return true;
114*361a3bf0SJohn Stultz }
115*361a3bf0SJohn Stultz 
116*361a3bf0SJohn Stultz static inline bool timespec64_valid_strict(const struct timespec64 *ts)
117*361a3bf0SJohn Stultz {
118*361a3bf0SJohn Stultz 	if (!timespec64_valid(ts))
119*361a3bf0SJohn Stultz 		return false;
120*361a3bf0SJohn Stultz 	/* Disallow values that could overflow ktime_t */
121*361a3bf0SJohn Stultz 	if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
122*361a3bf0SJohn Stultz 		return false;
123*361a3bf0SJohn Stultz 	return true;
124*361a3bf0SJohn Stultz }
125*361a3bf0SJohn Stultz 
126*361a3bf0SJohn Stultz /**
127*361a3bf0SJohn Stultz  * timespec64_to_ns - Convert timespec64 to nanoseconds
128*361a3bf0SJohn Stultz  * @ts:		pointer to the timespec64 variable to be converted
129*361a3bf0SJohn Stultz  *
130*361a3bf0SJohn Stultz  * Returns the scalar nanosecond representation of the timespec64
131*361a3bf0SJohn Stultz  * parameter.
132*361a3bf0SJohn Stultz  */
133*361a3bf0SJohn Stultz static inline s64 timespec64_to_ns(const struct timespec64 *ts)
134*361a3bf0SJohn Stultz {
135*361a3bf0SJohn Stultz 	return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
136*361a3bf0SJohn Stultz }
137*361a3bf0SJohn Stultz 
138*361a3bf0SJohn Stultz /**
139*361a3bf0SJohn Stultz  * ns_to_timespec64 - Convert nanoseconds to timespec64
140*361a3bf0SJohn Stultz  * @nsec:	the nanoseconds value to be converted
141*361a3bf0SJohn Stultz  *
142*361a3bf0SJohn Stultz  * Returns the timespec64 representation of the nsec parameter.
143*361a3bf0SJohn Stultz  */
144*361a3bf0SJohn Stultz extern struct timespec64 ns_to_timespec64(const s64 nsec);
145*361a3bf0SJohn Stultz 
146*361a3bf0SJohn Stultz /**
147*361a3bf0SJohn Stultz  * timespec64_add_ns - Adds nanoseconds to a timespec64
148*361a3bf0SJohn Stultz  * @a:		pointer to timespec64 to be incremented
149*361a3bf0SJohn Stultz  * @ns:		unsigned nanoseconds value to be added
150*361a3bf0SJohn Stultz  *
151*361a3bf0SJohn Stultz  * This must always be inlined because its used from the x86-64 vdso,
152*361a3bf0SJohn Stultz  * which cannot call other kernel functions.
153*361a3bf0SJohn Stultz  */
154*361a3bf0SJohn Stultz static __always_inline void timespec64_add_ns(struct timespec64 *a, u64 ns)
155*361a3bf0SJohn Stultz {
156*361a3bf0SJohn Stultz 	a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
157*361a3bf0SJohn Stultz 	a->tv_nsec = ns;
158*361a3bf0SJohn Stultz }
159*361a3bf0SJohn Stultz 
160*361a3bf0SJohn Stultz #endif
161*361a3bf0SJohn Stultz 
162*361a3bf0SJohn Stultz #endif /* _LINUX_TIME64_H */
163