The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ck/src/ck_ec_timeutil.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #ifndef CK_EC_TIMEUTIL_H
    2 #define CK_EC_TIMEUTIL_H
    3 #include <ck_cc.h>
    4 #include <ck_ec.h>
    5 #include <ck_limits.h>
    6 #include <ck_stdint.h>
    7 #include <sys/time.h>
    8 
    9 #define TIME_MAX ((time_t)((1ULL << ((sizeof(time_t) * CHAR_BIT) - 1)) - 1))
   10 #define NSEC_MAX ((1000L * 1000 * 1000) - 1)
   11 
   12 /*
   13  * Approximates (nsec * multiplier) >> shift. Clamps to UINT32_MAX on
   14  * overflow.
   15  */
   16 CK_CC_UNUSED static uint32_t
   17 wait_time_scale(uint32_t nsec,
   18                 uint32_t multiplier,
   19                 unsigned int shift)
   20 {
   21         uint64_t temp = (uint64_t)nsec * multiplier;
   22         uint64_t max = (uint64_t)UINT32_MAX << shift;
   23 
   24         if (temp >= max) {
   25                 return UINT32_MAX;
   26         }
   27 
   28         return temp >> shift;
   29 }
   30 
   31 
   32 /*
   33  * Returns ts + ns. ns is clamped to at most 1 second. Clamps the
   34  * return value to TIME_MAX, NSEC_MAX on overflow.
   35  *
   36  */
   37 CK_CC_UNUSED static struct timespec timespec_add_ns(const struct timespec ts,
   38                                                     uint32_t ns)
   39 {
   40         struct timespec ret = {
   41                 .tv_sec = TIME_MAX,
   42                 .tv_nsec = NSEC_MAX
   43         };
   44         time_t sec;
   45         uint32_t sum_ns;
   46 
   47         if (ns > (uint32_t)NSEC_MAX) {
   48                 if (ts.tv_sec >= TIME_MAX) {
   49                         return ret;
   50                 }
   51 
   52                 ret.tv_sec = ts.tv_sec + 1;
   53                 ret.tv_nsec = ts.tv_nsec;
   54                 return ret;
   55         }
   56 
   57         sec = ts.tv_sec;
   58         sum_ns = ns + ts.tv_nsec;
   59         if (sum_ns > NSEC_MAX) {
   60                 if (sec >= TIME_MAX) {
   61                         return ret;
   62                 }
   63 
   64                 sec++;
   65                 sum_ns -= (NSEC_MAX + 1);
   66         }
   67 
   68         ret.tv_sec = sec;
   69         ret.tv_nsec = sum_ns;
   70         return ret;
   71 }
   72 
   73 
   74 /*
   75  * Returns ts + inc. If inc is negative, it is normalized to 0.
   76  * Clamps the return value to TIME_MAX, NSEC_MAX on overflow.
   77  */
   78 CK_CC_UNUSED static struct timespec timespec_add(const struct timespec ts,
   79                                                  const struct timespec inc)
   80 {
   81         /* Initial return value is clamped to infinite future. */
   82         struct timespec ret = {
   83                 .tv_sec = TIME_MAX,
   84                 .tv_nsec = NSEC_MAX
   85         };
   86         time_t sec;
   87         unsigned long nsec;
   88 
   89         /* Non-positive delta is a no-op. Invalid nsec is another no-op. */
   90         if (inc.tv_sec < 0 || inc.tv_nsec < 0 || inc.tv_nsec > NSEC_MAX) {
   91                 return ts;
   92         }
   93 
   94         /* Detect overflow early. */
   95         if (inc.tv_sec > TIME_MAX - ts.tv_sec) {
   96                 return ret;
   97         }
   98 
   99         sec = ts.tv_sec + inc.tv_sec;
  100         /* This sum can't overflow if the inputs are valid.*/
  101         nsec = (unsigned long)ts.tv_nsec + inc.tv_nsec;
  102 
  103         if (nsec > NSEC_MAX) {
  104                 if (sec >= TIME_MAX) {
  105                         return ret;
  106                 }
  107 
  108                 sec++;
  109                 nsec -= (NSEC_MAX + 1);
  110         }
  111 
  112         ret.tv_sec = sec;
  113         ret.tv_nsec = nsec;
  114         return ret;
  115 }
  116 
  117 /* Compares two timespecs. Returns -1 if x < y, 0 if x == y, and 1 if x > y. */
  118 CK_CC_UNUSED static int timespec_cmp(const struct timespec x,
  119                                      const struct timespec y)
  120 {
  121         if (x.tv_sec != y.tv_sec) {
  122                 return (x.tv_sec < y.tv_sec) ? -1 : 1;
  123         }
  124 
  125         if (x.tv_nsec != y.tv_nsec) {
  126                 return (x.tv_nsec < y.tv_nsec) ? -1 : 1;
  127         }
  128 
  129         return 0;
  130 }
  131 
  132 /*
  133  * Overwrites now with the current CLOCK_MONOTONIC time, and returns
  134  * true if the current time is greater than or equal to the deadline,
  135  * or the clock is somehow broken.
  136  */
  137 CK_CC_UNUSED static bool check_deadline(struct timespec *now,
  138                                         const struct ck_ec_ops *ops,
  139                                         const struct timespec deadline)
  140 {
  141         int r;
  142 
  143         r = ops->gettime(ops, now);
  144         if (r != 0) {
  145                 return true;
  146         }
  147 
  148         return timespec_cmp(*now, deadline) >= 0;
  149 }
  150 #endif /* !CK_EC_TIMEUTIL_H */

Cache object: 099e3955f1c01a71b04833322536868f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.