File Index
Files and directories
Sign in
FILE

time64.h

File preview with syntax highlighting.

linux-6.19.14/include/linux/time64.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _LINUX_TIME64_H
  3#define _LINUX_TIME64_H
  4
  5#include <linux/math64.h>
  6#include <vdso/time64.h>
  7
  8typedef __s64 time64_t;
  9typedef __u64 timeu64_t;
 10
 11#include <uapi/linux/time.h>
 12
 13struct timespec64 {
 14	time64_t	tv_sec;			/* seconds */
 15	long		tv_nsec;		/* nanoseconds */
 16};
 17
 18struct itimerspec64 {
 19	struct timespec64 it_interval;
 20	struct timespec64 it_value;
 21};
 22
 23/* Parameters used to convert the timespec values: */
 24#define PSEC_PER_NSEC			1000L
 25
 26/* Located here for timespec[64]_valid_strict */
 27#define TIME64_MAX			((s64)~((u64)1 << 63))
 28#define TIME64_MIN			(-TIME64_MAX - 1)
 29
 30#define KTIME_MAX			((s64)~((u64)1 << 63))
 31#define KTIME_MIN			(-KTIME_MAX - 1)
 32#define KTIME_SEC_MAX			(KTIME_MAX / NSEC_PER_SEC)
 33#define KTIME_SEC_MIN			(KTIME_MIN / NSEC_PER_SEC)
 34
 35/*
 36 * Limits for settimeofday():
 37 *
 38 * To prevent setting the time close to the wraparound point time setting
 39 * is limited so a reasonable uptime can be accomodated. Uptime of 30 years
 40 * should be really sufficient, which means the cutoff is 2232. At that
 41 * point the cutoff is just a small part of the larger problem.
 42 */
 43#define TIME_UPTIME_SEC_MAX		(30LL * 365 * 24 *3600)
 44#define TIME_SETTOD_SEC_MAX		(KTIME_SEC_MAX - TIME_UPTIME_SEC_MAX)
 45
 46static inline int timespec64_equal(const struct timespec64 *a,
 47				   const struct timespec64 *b)
 48{
 49	return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
 50}
 51
 52static inline bool timespec64_is_epoch(const struct timespec64 *ts)
 53{
 54	return ts->tv_sec == 0 && ts->tv_nsec == 0;
 55}
 56
 57/*
 58 * lhs < rhs:  return <0
 59 * lhs == rhs: return 0
 60 * lhs > rhs:  return >0
 61 */
 62static inline int timespec64_compare(const struct timespec64 *lhs, const struct timespec64 *rhs)
 63{
 64	if (lhs->tv_sec < rhs->tv_sec)
 65		return -1;
 66	if (lhs->tv_sec > rhs->tv_sec)
 67		return 1;
 68	return lhs->tv_nsec - rhs->tv_nsec;
 69}
 70
 71extern void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec);
 72
 73static inline struct timespec64 timespec64_add(struct timespec64 lhs,
 74						struct timespec64 rhs)
 75{
 76	struct timespec64 ts_delta;
 77	set_normalized_timespec64(&ts_delta, lhs.tv_sec + rhs.tv_sec,
 78				lhs.tv_nsec + rhs.tv_nsec);
 79	return ts_delta;
 80}
 81
 82/*
 83 * sub = lhs - rhs, in normalized form
 84 */
 85static inline struct timespec64 timespec64_sub(struct timespec64 lhs,
 86						struct timespec64 rhs)
 87{
 88	struct timespec64 ts_delta;
 89	set_normalized_timespec64(&ts_delta, lhs.tv_sec - rhs.tv_sec,
 90				lhs.tv_nsec - rhs.tv_nsec);
 91	return ts_delta;
 92}
 93
 94/*
 95 * Returns true if the timespec64 is norm, false if denorm:
 96 */
 97static inline bool timespec64_valid(const struct timespec64 *ts)
 98{
 99	/* Dates before 1970 are bogus */
100	if (ts->tv_sec < 0)
101		return false;
102	/* Can't have more nanoseconds then a second */
103	if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
104		return false;
105	return true;
106}
107
108static inline bool timespec64_valid_strict(const struct timespec64 *ts)
109{
110	if (!timespec64_valid(ts))
111		return false;
112	/* Disallow values that could overflow ktime_t */
113	if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
114		return false;
115	return true;
116}
117
118static inline bool timespec64_valid_settod(const struct timespec64 *ts)
119{
120	if (!timespec64_valid(ts))
121		return false;
122	/* Disallow values which cause overflow issues vs. CLOCK_REALTIME */
123	if ((unsigned long long)ts->tv_sec >= TIME_SETTOD_SEC_MAX)
124		return false;
125	return true;
126}
127
128/**
129 * timespec64_to_ns - Convert timespec64 to nanoseconds
130 * @ts:		pointer to the timespec64 variable to be converted
131 *
132 * Returns the scalar nanosecond representation of the timespec64
133 * parameter.
134 */
135static inline s64 timespec64_to_ns(const struct timespec64 *ts)
136{
137	/* Prevent multiplication overflow / underflow */
138	if (ts->tv_sec >= KTIME_SEC_MAX)
139		return KTIME_MAX;
140
141	if (ts->tv_sec <= KTIME_SEC_MIN)
142		return KTIME_MIN;
143
144	return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
145}
146
147/**
148 * ns_to_timespec64 - Convert nanoseconds to timespec64
149 * @nsec:	the nanoseconds value to be converted
150 *
151 * Returns the timespec64 representation of the nsec parameter.
152 */
153extern struct timespec64 ns_to_timespec64(s64 nsec);
154
155/**
156 * timespec64_add_ns - Adds nanoseconds to a timespec64
157 * @a:		pointer to timespec64 to be incremented
158 * @ns:		unsigned nanoseconds value to be added
159 *
160 * This must always be inlined because its used from the x86-64 vdso,
161 * which cannot call other kernel functions.
162 */
163static __always_inline void timespec64_add_ns(struct timespec64 *a, u64 ns)
164{
165	a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
166	a->tv_nsec = ns;
167}
168
169/*
170 * timespec64_add_safe assumes both values are positive and checks for
171 * overflow. It will return TIME64_MAX in case of overflow.
172 */
173extern struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
174					 const struct timespec64 rhs);
175
176#endif /* _LINUX_TIME64_H */
~/ Read-only file preview.