LCOV - code coverage report
Current view: top level - include/linux - time64.h (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 11 11 100.0 %
Date: 2023-07-31 20:08:07 Functions: 1 1 100.0 %

          Line data    Source code
       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             : 
       8             : typedef __s64 time64_t;
       9             : typedef __u64 timeu64_t;
      10             : 
      11             : #include <uapi/linux/time.h>
      12             : 
      13             : struct timespec64 {
      14             :         time64_t        tv_sec;                 /* seconds */
      15             :         long            tv_nsec;                /* nanoseconds */
      16             : };
      17             : 
      18             : struct 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             : 
      46             : static inline int timespec64_equal(const struct timespec64 *a,
      47             :                                    const struct timespec64 *b)
      48             : {
      49  1543821921 :         return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
      50             : }
      51             : 
      52             : /*
      53             :  * lhs < rhs:  return <0
      54             :  * lhs == rhs: return 0
      55             :  * lhs > rhs:  return >0
      56             :  */
      57             : static inline int timespec64_compare(const struct timespec64 *lhs, const struct timespec64 *rhs)
      58             : {
      59  1277899101 :         if (lhs->tv_sec < rhs->tv_sec)
      60             :                 return -1;
      61  1203956423 :         if (lhs->tv_sec > rhs->tv_sec)
      62             :                 return 1;
      63  1191201123 :         return lhs->tv_nsec - rhs->tv_nsec;
      64             : }
      65             : 
      66             : extern void set_normalized_timespec64(struct timespec64 *ts, time64_t sec, s64 nsec);
      67             : 
      68             : static inline struct timespec64 timespec64_add(struct timespec64 lhs,
      69             :                                                 struct timespec64 rhs)
      70             : {
      71             :         struct timespec64 ts_delta;
      72             :         set_normalized_timespec64(&ts_delta, lhs.tv_sec + rhs.tv_sec,
      73             :                                 lhs.tv_nsec + rhs.tv_nsec);
      74             :         return ts_delta;
      75             : }
      76             : 
      77             : /*
      78             :  * sub = lhs - rhs, in normalized form
      79             :  */
      80     1144895 : static inline struct timespec64 timespec64_sub(struct timespec64 lhs,
      81             :                                                 struct timespec64 rhs)
      82             : {
      83     1144895 :         struct timespec64 ts_delta;
      84     1144895 :         set_normalized_timespec64(&ts_delta, lhs.tv_sec - rhs.tv_sec,
      85     1144895 :                                 lhs.tv_nsec - rhs.tv_nsec);
      86     1144869 :         return ts_delta;
      87             : }
      88             : 
      89             : /*
      90             :  * Returns true if the timespec64 is norm, false if denorm:
      91             :  */
      92             : static inline bool timespec64_valid(const struct timespec64 *ts)
      93             : {
      94             :         /* Dates before 1970 are bogus */
      95     4459677 :         if (ts->tv_sec < 0)
      96             :                 return false;
      97             :         /* Can't have more nanoseconds then a second */
      98     4459677 :         if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
      99             :                 return false;
     100             :         return true;
     101             : }
     102             : 
     103             : static inline bool timespec64_valid_strict(const struct timespec64 *ts)
     104             : {
     105             :         if (!timespec64_valid(ts))
     106             :                 return false;
     107             :         /* Disallow values that could overflow ktime_t */
     108             :         if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
     109             :                 return false;
     110             :         return true;
     111             : }
     112             : 
     113             : static inline bool timespec64_valid_settod(const struct timespec64 *ts)
     114             : {
     115             :         if (!timespec64_valid(ts))
     116             :                 return false;
     117             :         /* Disallow values which cause overflow issues vs. CLOCK_REALTIME */
     118             :         if ((unsigned long long)ts->tv_sec >= TIME_SETTOD_SEC_MAX)
     119             :                 return false;
     120             :         return true;
     121             : }
     122             : 
     123             : /**
     124             :  * timespec64_to_ns - Convert timespec64 to nanoseconds
     125             :  * @ts:         pointer to the timespec64 variable to be converted
     126             :  *
     127             :  * Returns the scalar nanosecond representation of the timespec64
     128             :  * parameter.
     129             :  */
     130             : static inline s64 timespec64_to_ns(const struct timespec64 *ts)
     131             : {
     132             :         /* Prevent multiplication overflow / underflow */
     133             :         if (ts->tv_sec >= KTIME_SEC_MAX)
     134             :                 return KTIME_MAX;
     135             : 
     136             :         if (ts->tv_sec <= KTIME_SEC_MIN)
     137             :                 return KTIME_MIN;
     138             : 
     139             :         return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
     140             : }
     141             : 
     142             : /**
     143             :  * ns_to_timespec64 - Convert nanoseconds to timespec64
     144             :  * @nsec:       the nanoseconds value to be converted
     145             :  *
     146             :  * Returns the timespec64 representation of the nsec parameter.
     147             :  */
     148             : extern struct timespec64 ns_to_timespec64(s64 nsec);
     149             : 
     150             : /**
     151             :  * timespec64_add_ns - Adds nanoseconds to a timespec64
     152             :  * @a:          pointer to timespec64 to be incremented
     153             :  * @ns:         unsigned nanoseconds value to be added
     154             :  *
     155             :  * This must always be inlined because its used from the x86-64 vdso,
     156             :  * which cannot call other kernel functions.
     157             :  */
     158             : static __always_inline void timespec64_add_ns(struct timespec64 *a, u64 ns)
     159             : {
     160             :         a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
     161             :         a->tv_nsec = ns;
     162             : }
     163             : 
     164             : /*
     165             :  * timespec64_add_safe assumes both values are positive and checks for
     166             :  * overflow. It will return TIME64_MAX in case of overflow.
     167             :  */
     168             : extern struct timespec64 timespec64_add_safe(const struct timespec64 lhs,
     169             :                                          const struct timespec64 rhs);
     170             : 
     171             : #endif /* _LINUX_TIME64_H */

Generated by: LCOV version 1.14