VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c@ 99286

Last change on this file since 99286 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.3 KB
Line 
1/* $Id: time-r0drv-linux.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Time, Ring-0 Driver, Linux.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_TIME
42#include "the-linux-kernel.h"
43#include "internal/iprt.h"
44/* Make sure we have the setting functions we need for RTTimeNow: */
45#if RTLNX_VER_MAX(2,6,16)
46# define RTTIME_INCL_TIMEVAL
47#elif RTLNX_VER_MAX(3,17,0)
48# define RTTIME_INCL_TIMESPEC
49#endif
50#include <iprt/time.h>
51#include <iprt/asm.h>
52
53
54
55DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
56{
57#if RTLNX_VER_MIN(5,6,0)
58 /*
59 * Starting with kernel version 5.6-rc3 only 64-bit time interfaces
60 * are allowed in the kernel.
61 */
62 uint64_t u64;
63 struct timespec64 Ts = { 0, 0 };
64
65 ktime_get_ts64(&Ts);
66 u64 = Ts.tv_sec * RT_NS_1SEC_64 + Ts.tv_nsec;
67 return u64;
68
69#elif RTLNX_VER_MIN(2,6,16) /* This must match timer-r0drv-linux.c! */
70 /*
71 * Use ktime_get_ts, this is also what clock_gettime(CLOCK_MONOTONIC,) is using.
72 */
73 uint64_t u64;
74 struct timespec Ts = { 0, 0 };
75 ktime_get_ts(&Ts);
76 u64 = Ts.tv_sec * RT_NS_1SEC_64 + Ts.tv_nsec;
77 return u64;
78
79#elif RTLNX_VER_MIN(2,5,60)
80 /*
81 * Seems there is no way of getting to the exact source of
82 * sys_clock_gettime(CLOCK_MONOTONIC, &ts) here, I think. But
83 * 64-bit jiffies adjusted for the initial value should be pretty
84 * much the same I hope.
85 */
86 uint64_t u64 = get_jiffies_64();
87# ifdef INITIAL_JIFFIES
88 u64 += INITIAL_JIFFIES;
89# endif
90 u64 *= TICK_NSEC;
91 return u64;
92
93#else /* < 2.5.60 */
94# if BITS_PER_LONG >= 64
95 /*
96 * This is the same as above, except that there is no get_jiffies_64()
97 * here and we rely on long, and therefor jiffies, being 64-bit instead.
98 */
99 uint64_t u64 = jiffies;
100# ifdef INITIAL_JIFFIES
101 u64 += INITIAL_JIFFIES;
102# endif
103 u64 *= TICK_NSEC;
104 return u64;
105
106# else /* 32 bit jiffies */
107 /*
108 * We'll have to try track jiffy rollovers here or we'll be
109 * in trouble every time it flips.
110 *
111 * The high dword of the s_u64Last is the rollover count, the
112 * low dword is the previous jiffies. Updating is done by
113 * atomic compare & exchange of course.
114 */
115 static uint64_t volatile s_u64Last = 0;
116 uint64_t u64;
117
118 for (;;)
119 {
120 uint64_t u64NewLast;
121 int32_t iDelta;
122 uint32_t cRollovers;
123 uint32_t u32LastJiffies;
124
125 /* sample the values */
126 unsigned long ulNow = jiffies;
127 uint64_t u64Last = s_u64Last;
128 if (ulNow != jiffies)
129 continue; /* try again */
130# ifdef INITIAL_JIFFIES
131 ulNow += INITIAL_JIFFIES;
132# endif
133
134 u32LastJiffies = (uint32_t)u64Last;
135 cRollovers = u64Last >> 32;
136
137 /*
138 * Check for rollover and update the static last value.
139 *
140 * We have to make sure we update it successfully to rule out
141 * an underrun because of racing someone.
142 */
143 iDelta = ulNow - u32LastJiffies;
144 if (iDelta < 0)
145 {
146 cRollovers++;
147 u64NewLast = RT_MAKE_U64(ulNow, cRollovers);
148 if (!ASMAtomicCmpXchgU64(&s_u64Last, u64NewLast, u64Last))
149 continue; /* race, try again */
150 }
151 else
152 {
153 u64NewLast = RT_MAKE_U64(ulNow, cRollovers);
154 ASMAtomicCmpXchgU64(&s_u64Last, u64NewLast, u64Last);
155 }
156
157 /* calculate the return value */
158 u64 = ulNow;
159 u64 *= TICK_NSEC;
160 u64 += cRollovers * (_4G * TICK_NSEC);
161 break;
162 }
163
164 return u64;
165# endif /* 32 bit jiffies */
166#endif /* < 2.5.60 */
167}
168
169
170RTDECL(uint64_t) RTTimeNanoTS(void)
171{
172 return rtTimeGetSystemNanoTS();
173}
174RT_EXPORT_SYMBOL(RTTimeNanoTS);
175
176
177RTDECL(uint64_t) RTTimeMilliTS(void)
178{
179 return rtTimeGetSystemNanoTS() / RT_NS_1MS;
180}
181RT_EXPORT_SYMBOL(RTTimeMilliTS);
182
183
184RTDECL(uint64_t) RTTimeSystemNanoTS(void)
185{
186 return rtTimeGetSystemNanoTS();
187}
188RT_EXPORT_SYMBOL(RTTimeSystemNanoTS);
189
190
191RTDECL(uint64_t) RTTimeSystemMilliTS(void)
192{
193 return rtTimeGetSystemNanoTS() / RT_NS_1MS;
194}
195RT_EXPORT_SYMBOL(RTTimeSystemMilliTS);
196
197
198RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
199{
200 IPRT_LINUX_SAVE_EFL_AC();
201#if RTLNX_VER_MIN(3,17,0)
202 struct timespec64 Ts;
203 ktime_get_real_ts64(&Ts); /* ktime_get_real_ts64 was added as a macro in 3.17, function since 4.18. */
204 IPRT_LINUX_RESTORE_EFL_AC();
205 return RTTimeSpecSetTimespec64(pTime, &Ts);
206
207#elif RTLNX_VER_MIN(2,6,16)
208 struct timespec Ts;
209 ktime_get_real_ts(&Ts); /* ktime_get_real_ts was removed in Linux 4.20. */
210 IPRT_LINUX_RESTORE_EFL_AC();
211 return RTTimeSpecSetTimespec(pTime, &Ts);
212
213#else /* < 2.6.16 */
214 struct timeval Tv;
215 do_gettimeofday(&Tv);
216 IPRT_LINUX_RESTORE_EFL_AC();
217 return RTTimeSpecSetTimeval(pTime, &Tv);
218#endif
219}
220RT_EXPORT_SYMBOL(RTTimeNow);
221
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette