Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:12

0001 /*-
0002  * SPDX-License-Identifier: BSD-3-Clause
0003  *
0004  * Copyright (C) 2016 embedded brains GmbH & Co. KG
0005  *
0006  * Copyright (c) 1982, 1986, 1993
0007  *  The Regents of the University of California.  All rights reserved.
0008  *
0009  * Redistribution and use in source and binary forms, with or without
0010  * modification, are permitted provided that the following conditions
0011  * are met:
0012  * 1. Redistributions of source code must retain the above copyright
0013  *    notice, this list of conditions and the following disclaimer.
0014  * 2. Redistributions in binary form must reproduce the above copyright
0015  *    notice, this list of conditions and the following disclaimer in the
0016  *    documentation and/or other materials provided with the distribution.
0017  * 3. Neither the name of the University nor the names of its contributors
0018  *    may be used to endorse or promote products derived from this software
0019  *    without specific prior written permission.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
0022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0031  * SUCH DAMAGE.
0032  *
0033  *  @(#)time.h  8.5 (Berkeley) 5/4/95
0034  * $FreeBSD$
0035  */
0036 
0037 /**
0038  * @file
0039  *
0040  * @ingroup RTEMSImplFreeBSDKernel
0041  *
0042  * @brief This header file provides time definitions for the kernel space
0043  *   (_KERNEL is defined before including <sys/time.h>).
0044  */
0045 
0046 #if defined(_SYS_TIME_H_) && defined(_KERNEL)
0047 
0048 #include <machine/_timecounter.h>
0049 
0050 /* Operations on timespecs */
0051 #ifndef timespecclear
0052 #define timespecclear(tvp)  ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
0053 #endif
0054 #ifndef timespecisset
0055 #define timespecisset(tvp)  ((tvp)->tv_sec || (tvp)->tv_nsec)
0056 #endif
0057 #ifndef timespeccmp
0058 #define timespeccmp(tvp, uvp, cmp)                  \
0059     (((tvp)->tv_sec == (uvp)->tv_sec) ?             \
0060         ((tvp)->tv_nsec cmp (uvp)->tv_nsec) :           \
0061         ((tvp)->tv_sec cmp (uvp)->tv_sec))
0062 #endif
0063 
0064 #ifndef timespecadd
0065 #define timespecadd(tsp, usp, vsp)                  \
0066     do {                                \
0067         (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;      \
0068         (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;   \
0069         if ((vsp)->tv_nsec >= 1000000000L) {            \
0070             (vsp)->tv_sec++;                \
0071             (vsp)->tv_nsec -= 1000000000L;          \
0072         }                           \
0073     } while (0)
0074 #endif
0075 #ifndef timespecsub
0076 #define timespecsub(tsp, usp, vsp)                  \
0077     do {                                \
0078         (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;      \
0079         (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;   \
0080         if ((vsp)->tv_nsec < 0) {               \
0081             (vsp)->tv_sec--;                \
0082             (vsp)->tv_nsec += 1000000000L;          \
0083         }                           \
0084     } while (0)
0085 #endif
0086 
0087 /*
0088  * Simple macros to convert ticks to milliseconds
0089  * or microseconds and vice-versa. The answer
0090  * will always be at least 1. Note the return
0091  * value is a uint32_t however we step up the
0092  * operations to 64 bit to avoid any overflow/underflow
0093  * problems.
0094  */
0095 #define TICKS_2_MSEC(t) max(1, (uint32_t)(hz == 1000) ? \
0096       (t) : (((uint64_t)(t) * (uint64_t)1000)/(uint64_t)hz))
0097 #define TICKS_2_USEC(t) max(1, (uint32_t)(hz == 1000) ? \
0098       ((t) * 1000) : (((uint64_t)(t) * (uint64_t)1000000)/(uint64_t)hz))
0099 #define MSEC_2_TICKS(m) max(1, (uint32_t)((hz == 1000) ? \
0100       (m) : ((uint64_t)(m) * (uint64_t)hz)/(uint64_t)1000))
0101 #define USEC_2_TICKS(u) max(1, (uint32_t)((hz == 1000) ? \
0102      ((u) / 1000) : ((uint64_t)(u) * (uint64_t)hz)/(uint64_t)1000000))
0103 
0104 /* Operations on timevals. */
0105 
0106 #define timevalclear(tvp)       ((tvp)->tv_sec = (tvp)->tv_usec = 0)
0107 #define timevalisset(tvp)       ((tvp)->tv_sec || (tvp)->tv_usec)
0108 #define timevalcmp(tvp, uvp, cmp)                   \
0109     (((tvp)->tv_sec == (uvp)->tv_sec) ?             \
0110         ((tvp)->tv_usec cmp (uvp)->tv_usec) :           \
0111         ((tvp)->tv_sec cmp (uvp)->tv_sec))
0112 
0113 /* timevaladd and timevalsub are not inlined */
0114 
0115 /*
0116  * Kernel to clock driver interface.
0117  */
0118 void    inittodr(time_t base);
0119 void    resettodr(void);
0120 
0121 #define time_second _Timecounter_Time_second
0122 #define time_uptime _Timecounter_Time_uptime
0123 extern struct timeval boottime;
0124 extern struct bintime tc_tick_bt;
0125 extern sbintime_t tc_tick_sbt;
0126 extern struct bintime tick_bt;
0127 extern sbintime_t tick_sbt;
0128 extern int tc_precexp;
0129 extern int tc_timepercentage;
0130 extern struct bintime bt_timethreshold;
0131 extern struct bintime bt_tickthreshold;
0132 extern sbintime_t sbt_timethreshold;
0133 extern sbintime_t sbt_tickthreshold;
0134 
0135 /*
0136  * Functions for looking at our clock: [get]{bin,nano,micro}[up]time()
0137  *
0138  * Functions without the "get" prefix returns the best timestamp
0139  * we can produce in the given format.
0140  *
0141  * "bin"   == struct bintime  == seconds + 64 bit fraction of seconds.
0142  * "nano"  == struct timespec == seconds + nanoseconds.
0143  * "micro" == struct timeval  == seconds + microseconds.
0144  *
0145  * Functions containing "up" returns time relative to boot and
0146  * should be used for calculating time intervals.
0147  *
0148  * Functions without "up" returns UTC time.
0149  *
0150  * Functions with the "get" prefix returns a less precise result
0151  * much faster than the functions without "get" prefix and should
0152  * be used where a precision of 1/hz seconds is acceptable or where
0153  * performance is priority. (NB: "precision", _not_ "resolution" !)
0154  */
0155 
0156 #define binuptime(_bt) _Timecounter_Binuptime(_bt)
0157 #define nanouptime(_tsp) _Timecounter_Nanouptime(_tsp)
0158 #define microuptime(_tvp) _Timecounter_Microuptime(_tvp)
0159 
0160 static __inline sbintime_t
0161 sbinuptime(void)
0162 {
0163     struct bintime _bt;
0164 
0165     binuptime(&_bt);
0166     return (bttosbt(_bt));
0167 }
0168 
0169 #define bintime(_bt) _Timecounter_Bintime(_bt)
0170 #define nanotime(_tsp) _Timecounter_Nanotime(_tsp)
0171 #define microtime(_tvp) _Timecounter_Microtime(_tvp)
0172 
0173 #define getbinuptime(_bt) _Timecounter_Getbinuptime(_bt)
0174 #define getnanouptime(_tsp) _Timecounter_Getnanouptime(_tsp)
0175 #define getmicrouptime(_tvp) _Timecounter_Getmicrouptime(_tvp)
0176 
0177 static __inline sbintime_t
0178 getsbinuptime(void)
0179 {
0180     struct bintime _bt;
0181 
0182     getbinuptime(&_bt);
0183     return (bttosbt(_bt));
0184 }
0185 
0186 #define getbintime(_bt) _Timecounter_Getbintime(_bt)
0187 #define getnanotime(_tsp) _Timecounter_Getnanotime(_tsp)
0188 #define getmicrotime(_tvp) _Timecounter_Getmicrotime(_tvp)
0189 
0190 #define getboottime(_tvp) _Timecounter_Getboottime(_tvp)
0191 #define getboottimebin(_bt) _Timecounter_Getboottimebin(_bt)
0192 
0193 /* Other functions */
0194 int itimerdecr(struct itimerval *itp, int usec);
0195 int itimerfix(struct timeval *tv);
0196 int ppsratecheck(struct timeval *, int *, int);
0197 int ratecheck(struct timeval *, const struct timeval *);
0198 void    timevaladd(struct timeval *t1, const struct timeval *t2);
0199 void    timevalsub(struct timeval *t1, const struct timeval *t2);
0200 int tvtohz(struct timeval *tv);
0201 
0202 #define TC_DEFAULTPERC      5
0203 
0204 #define BT2FREQ(bt)                                                     \
0205     (((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) /           \
0206         ((bt)->frac >> 1))
0207 
0208 #define SBT2FREQ(sbt)   ((SBT_1S + ((sbt) >> 1)) / (sbt))
0209 
0210 #define FREQ2BT(freq, bt)                                               \
0211 {                                   \
0212     (bt)->sec = 0;                                                  \
0213     (bt)->frac = ((uint64_t)0x8000000000000000  / (freq)) << 1;     \
0214 }
0215 
0216 #define TIMESEL(sbt, sbt2)                      \
0217     (((sbt2) >= sbt_timethreshold) ?                \
0218         ((*(sbt) = getsbinuptime()), 1) : ((*(sbt) = sbinuptime()), 0))
0219 
0220 #else /* !_SYS_TIME_H_ || !_KERNEL */
0221 #error "must be included via <sys/time.h> in kernel space"
0222 #endif /* _SYS_TIME_H_ && _KERNEL */