Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _LINUX_TIME64_H
0003 #define _LINUX_TIME64_H
0004 
0005 #include <linux/math64.h>
0006 #include <vdso/time64.h>
0007 
0008 typedef __s64 time64_t;
0009 typedef __u64 timeu64_t;
0010 
0011 #include <uapi/linux/time.h>
0012 
0013 struct timespec64 {
0014     time64_t    tv_sec;         /* seconds */
0015     long        tv_nsec;        /* nanoseconds */
0016 };
0017 
0018 struct itimerspec64 {
0019     struct timespec64 it_interval;
0020     struct timespec64 it_value;
0021 };
0022 
0023 /* Parameters used to convert the timespec values: */
0024 #define PSEC_PER_NSEC           1000L
0025 
0026 /* Located here for timespec[64]_valid_strict */
0027 #define TIME64_MAX          ((s64)~((u64)1 << 63))
0028 #define TIME64_MIN          (-TIME64_MAX - 1)
0029 
0030 #define KTIME_MAX           ((s64)~((u64)1 << 63))
0031 #define KTIME_MIN           (-KTIME_MAX - 1)
0032 #define KTIME_SEC_MAX           (KTIME_MAX / NSEC_PER_SEC)
0033 #define KTIME_SEC_MIN           (KTIME_MIN / NSEC_PER_SEC)
0034 
0035 /*
0036  * Limits for settimeofday():
0037  *
0038  * To prevent setting the time close to the wraparound point time setting
0039  * is limited so a reasonable uptime can be accomodated. Uptime of 30 years
0040  * should be really sufficient, which means the cutoff is 2232. At that
0041  * point the cutoff is just a small part of the larger problem.
0042  */
0043 #define TIME_UPTIME_SEC_MAX     (30LL * 365 * 24 *3600)
0044 #define TIME_SETTOD_SEC_MAX     (KTIME_SEC_MAX - TIME_UPTIME_SEC_MAX)
0045 
0046 static inline int timespec64_equal(const struct timespec64 *a,
0047                    const struct timespec64 *b)
0048 {
0049     return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
0050 }
0051 
0052 /*
0053  * lhs < rhs:  return <0
0054  * lhs == rhs: return 0
0055  * lhs > rhs:  return >0
0056  */
0057 static inline int timespec64_compare(const struct timespec64 *lhs, const struct timespec64 *rhs)
0058 {
0059     if (lhs->tv_sec < rhs->tv_sec)
0060         return -1;
0061     if (lhs->tv_sec > rhs->tv_sec)
0062         return 1;
0063     return lhs->tv_nsec - rhs->tv_nsec;
0064 }
0065 
0066 extern void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec);
0067 
0068 static inline struct timespec64 timespec64_add(struct timespec64 lhs,
0069                         struct timespec64 rhs)
0070 {
0071     struct timespec64 ts_delta;
0072     set_normalized_timespec64(&ts_delta, lhs.tv_sec + rhs.tv_sec,
0073                 lhs.tv_nsec + rhs.tv_nsec);
0074     return ts_delta;
0075 }
0076 
0077 /*
0078  * sub = lhs - rhs, in normalized form
0079  */
0080 static inline struct timespec64 timespec64_sub(struct timespec64 lhs,
0081                         struct timespec64 rhs)
0082 {
0083     struct timespec64 ts_delta;
0084     set_normalized_timespec64(&ts_delta, lhs.tv_sec - rhs.tv_sec,
0085                 lhs.tv_nsec - rhs.tv_nsec);
0086     return ts_delta;
0087 }
0088 
0089 /*
0090  * Returns true if the timespec64 is norm, false if denorm:
0091  */
0092 static inline bool timespec64_valid(const struct timespec64 *ts)
0093 {
0094     /* Dates before 1970 are bogus */
0095     if (ts->tv_sec < 0)
0096         return false;
0097     /* Can't have more nanoseconds then a second */
0098     if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
0099         return false;
0100     return true;
0101 }
0102 
0103 static inline bool timespec64_valid_strict(const struct timespec64 *ts)
0104 {
0105     if (!timespec64_valid(ts))
0106         return false;
0107     /* Disallow values that could overflow ktime_t */
0108     if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
0109         return false;
0110     return true;
0111 }
0112 
0113 static inline bool timespec64_valid_settod(const struct timespec64 *ts)
0114 {
0115     if (!timespec64_valid(ts))
0116         return false;
0117     /* Disallow values which cause overflow issues vs. CLOCK_REALTIME */
0118     if ((unsigned long long)ts->tv_sec >= TIME_SETTOD_SEC_MAX)
0119         return false;
0120     return true;
0121 }
0122 
0123 /**
0124  * timespec64_to_ns - Convert timespec64 to nanoseconds
0125  * @ts:     pointer to the timespec64 variable to be converted
0126  *
0127  * Returns the scalar nanosecond representation of the timespec64
0128  * parameter.
0129  */
0130 static inline s64 timespec64_to_ns(const struct timespec64 *ts)
0131 {
0132     /* Prevent multiplication overflow / underflow */
0133     if (ts->tv_sec >= KTIME_SEC_MAX)
0134         return KTIME_MAX;
0135 
0136     if (ts->tv_sec <= KTIME_SEC_MIN)
0137         return KTIME_MIN;
0138 
0139     return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
0140 }
0141 
0142 /**
0143  * ns_to_timespec64 - Convert nanoseconds to timespec64
0144  * @nsec:   the nanoseconds value to be converted
0145  *
0146  * Returns the timespec64 representation of the nsec parameter.
0147  */
0148 extern struct timespec64 ns_to_timespec64(s64 nsec);
0149 
0150 /**
0151  * timespec64_add_ns - Adds nanoseconds to a timespec64
0152  * @a:      pointer to timespec64 to be incremented
0153  * @ns:     unsigned nanoseconds value to be added
0154  *
0155  * This must always be inlined because its used from the x86-64 vdso,
0156  * which cannot call other kernel functions.
0157  */
0158 static __always_inline void timespec64_add_ns(struct timespec64 *a, u64 ns)
0159 {
0160     a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
0161     a->tv_nsec = ns;
0162 }
0163 
0164 /*
0165  * timespec64_add_safe assumes both values are positive and checks for
0166  * overflow. It will return TIME64_MAX in case of overflow.
0167  */
0168 extern struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
0169                      const struct timespec64 rhs);
0170 
0171 #endif /* _LINUX_TIME64_H */