| Commit | Line | Data |
|---|---|---|
| 8c10bfcf MD |
1 | /* |
| 2 | * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. | |
| 3 | * | |
| 4 | * This code is derived from software contributed to The DragonFly Project | |
| 5 | * by Matthew Dillon <dillon@backplane.com> | |
| 6 | * | |
| 7 | * Redistribution and use in source and binary forms, with or without | |
| 8 | * modification, are permitted provided that the following conditions | |
| 9 | * are met: | |
| 10 | * | |
| 11 | * 1. Redistributions of source code must retain the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer. | |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 14 | * notice, this list of conditions and the following disclaimer in | |
| 15 | * the documentation and/or other materials provided with the | |
| 16 | * distribution. | |
| 17 | * 3. Neither the name of The DragonFly Project nor the names of its | |
| 18 | * contributors may be used to endorse or promote products derived | |
| 19 | * from this software without specific, prior written permission. | |
| 20 | * | |
| 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
| 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 32 | * SUCH DAMAGE. | |
| 33 | * | |
| 984263bc MD |
34 | * Copyright (c) 1997, 1998 Poul-Henning Kamp <phk@FreeBSD.org> |
| 35 | * Copyright (c) 1982, 1986, 1991, 1993 | |
| 36 | * The Regents of the University of California. All rights reserved. | |
| 37 | * (c) UNIX System Laboratories, Inc. | |
| 38 | * All or some portions of this file are derived from material licensed | |
| 39 | * to the University of California by American Telephone and Telegraph | |
| 40 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
| 41 | * the permission of UNIX System Laboratories, Inc. | |
| 42 | * | |
| 43 | * Redistribution and use in source and binary forms, with or without | |
| 44 | * modification, are permitted provided that the following conditions | |
| 45 | * are met: | |
| 46 | * 1. Redistributions of source code must retain the above copyright | |
| 47 | * notice, this list of conditions and the following disclaimer. | |
| 48 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 49 | * notice, this list of conditions and the following disclaimer in the | |
| 50 | * documentation and/or other materials provided with the distribution. | |
| 51 | * 3. All advertising materials mentioning features or use of this software | |
| 52 | * must display the following acknowledgement: | |
| 53 | * This product includes software developed by the University of | |
| 54 | * California, Berkeley and its contributors. | |
| 55 | * 4. Neither the name of the University nor the names of its contributors | |
| 56 | * may be used to endorse or promote products derived from this software | |
| 57 | * without specific prior written permission. | |
| 58 | * | |
| 59 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| 60 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 61 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 62 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| 63 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 64 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 65 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 66 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 67 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 68 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 69 | * SUCH DAMAGE. | |
| 70 | * | |
| 71 | * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 | |
| 72 | * $FreeBSD: src/sys/kern/kern_clock.c,v 1.105.2.10 2002/10/17 13:19:40 maxim Exp $ | |
| c730be20 | 73 | * $DragonFly: src/sys/kern/kern_clock.c,v 1.62 2008/09/09 04:06:13 dillon Exp $ |
| 984263bc MD |
74 | */ |
| 75 | ||
| 76 | #include "opt_ntp.h" | |
| 2b71c8f1 | 77 | #include "opt_polling.h" |
| b3a7093f | 78 | #include "opt_ifpoll.h" |
| 07522099 | 79 | #include "opt_pctrack.h" |
| 984263bc MD |
80 | |
| 81 | #include <sys/param.h> | |
| 82 | #include <sys/systm.h> | |
| 984263bc MD |
83 | #include <sys/callout.h> |
| 84 | #include <sys/kernel.h> | |
| f5d21610 | 85 | #include <sys/kinfo.h> |
| 984263bc MD |
86 | #include <sys/proc.h> |
| 87 | #include <sys/malloc.h> | |
| 88 | #include <sys/resourcevar.h> | |
| 89 | #include <sys/signalvar.h> | |
| 90 | #include <sys/timex.h> | |
| 91 | #include <sys/timepps.h> | |
| 92 | #include <vm/vm.h> | |
| 93 | #include <sys/lock.h> | |
| 94 | #include <vm/pmap.h> | |
| 95 | #include <vm/vm_map.h> | |
| 5ffd1608 | 96 | #include <vm/vm_extern.h> |
| 984263bc | 97 | #include <sys/sysctl.h> |
| 684a93c4 | 98 | |
| 2689779e | 99 | #include <sys/thread2.h> |
| 984263bc MD |
100 | |
| 101 | #include <machine/cpu.h> | |
| 102 | #include <machine/limits.h> | |
| 103 | #include <machine/smp.h> | |
| d2412a2e MD |
104 | #include <machine/cpufunc.h> |
| 105 | #include <machine/specialreg.h> | |
| 106 | #include <machine/clock.h> | |
| 984263bc MD |
107 | |
| 108 | #ifdef GPROF | |
| 109 | #include <sys/gmon.h> | |
| 110 | #endif | |
| 111 | ||
| 112 | #ifdef DEVICE_POLLING | |
| 94ebffcd | 113 | extern void init_device_poll_pcpu(int); |
| 3e61f60e | 114 | #endif |
| 984263bc | 115 | |
| b3a7093f SZ |
116 | #ifdef IFPOLL_ENABLE |
| 117 | extern void ifpoll_init_pcpu(int); | |
| 118 | #endif | |
| 119 | ||
| 07522099 MD |
120 | #ifdef DEBUG_PCTRACK |
| 121 | static void do_pctrack(struct intrframe *frame, int which); | |
| 122 | #endif | |
| 123 | ||
| 402ed7e1 | 124 | static void initclocks (void *dummy); |
| ba39e2e0 | 125 | SYSINIT(clocks, SI_BOOT2_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) |
| 984263bc | 126 | |
| 6ad39cae MD |
127 | /* |
| 128 | * Some of these don't belong here, but it's easiest to concentrate them. | |
| 9eea7f0c | 129 | * Note that cpu_time counts in microseconds, but most userland programs |
| 6ad39cae MD |
130 | * just compare relative times against the total by delta. |
| 131 | */ | |
| 9eea7f0c | 132 | struct kinfo_cputime cputime_percpu[MAXCPU]; |
| 07522099 MD |
133 | #ifdef DEBUG_PCTRACK |
| 134 | struct kinfo_pcheader cputime_pcheader = { PCTRACK_SIZE, PCTRACK_ARYSIZE }; | |
| 135 | struct kinfo_pctrack cputime_pctrack[MAXCPU][PCTRACK_SIZE]; | |
| 136 | #endif | |
| 137 | ||
| 9eea7f0c HP |
138 | #ifdef SMP |
| 139 | static int | |
| 140 | sysctl_cputime(SYSCTL_HANDLER_ARGS) | |
| 141 | { | |
| 142 | int cpu, error = 0; | |
| 143 | size_t size = sizeof(struct kinfo_cputime); | |
| 144 | ||
| 145 | for (cpu = 0; cpu < ncpus; ++cpu) { | |
| 146 | if ((error = SYSCTL_OUT(req, &cputime_percpu[cpu], size))) | |
| 147 | break; | |
| 148 | } | |
| 984263bc | 149 | |
| 9eea7f0c HP |
150 | return (error); |
| 151 | } | |
| 152 | SYSCTL_PROC(_kern, OID_AUTO, cputime, (CTLTYPE_OPAQUE|CTLFLAG_RD), 0, 0, | |
| 153 | sysctl_cputime, "S,kinfo_cputime", "CPU time statistics"); | |
| 154 | #else | |
| 155 | SYSCTL_STRUCT(_kern, OID_AUTO, cputime, CTLFLAG_RD, &cpu_time, kinfo_cputime, | |
| 156 | "CPU time statistics"); | |
| 157 | #endif | |
| 984263bc | 158 | |
| 06636a8e AHJ |
159 | static int |
| 160 | sysctl_cp_time(SYSCTL_HANDLER_ARGS) | |
| 161 | { | |
| 162 | long cpu_states[5] = {0}; | |
| 163 | int cpu, error = 0; | |
| 164 | size_t size = sizeof(cpu_states); | |
| 165 | ||
| 166 | for (cpu = 0; cpu < ncpus; ++cpu) { | |
| 167 | cpu_states[0] += cputime_percpu[cpu].cp_user; | |
| 168 | cpu_states[1] += cputime_percpu[cpu].cp_nice; | |
| 169 | cpu_states[2] += cputime_percpu[cpu].cp_sys; | |
| 170 | cpu_states[3] += cputime_percpu[cpu].cp_intr; | |
| 171 | cpu_states[4] += cputime_percpu[cpu].cp_idle; | |
| 172 | } | |
| 173 | ||
| 174 | error = SYSCTL_OUT(req, cpu_states, size); | |
| 175 | ||
| 176 | return (error); | |
| 177 | } | |
| 178 | ||
| 179 | SYSCTL_PROC(_kern, OID_AUTO, cp_time, (CTLTYPE_LONG|CTLFLAG_RD), 0, 0, | |
| 180 | sysctl_cp_time, "LU", "CPU time statistics"); | |
| 181 | ||
| 88c4d2f6 MD |
182 | /* |
| 183 | * boottime is used to calculate the 'real' uptime. Do not confuse this with | |
| 184 | * microuptime(). microtime() is not drift compensated. The real uptime | |
| 60b2809b MD |
185 | * with compensation is nanotime() - bootime. boottime is recalculated |
| 186 | * whenever the real time is set based on the compensated elapsed time | |
| 187 | * in seconds (gd->gd_time_seconds). | |
| 88c4d2f6 | 188 | * |
| 88c4d2f6 MD |
189 | * The gd_time_seconds and gd_cpuclock_base fields remain fairly monotonic. |
| 190 | * Slight adjustments to gd_cpuclock_base are made to phase-lock it to | |
| 191 | * the real time. | |
| 192 | */ | |
| 193 | struct timespec boottime; /* boot time (realtime) for reference only */ | |
| 88c4d2f6 | 194 | time_t time_second; /* read-only 'passive' uptime in seconds */ |
| 984263bc | 195 | |
| 5eb5a6bc MD |
196 | /* |
| 197 | * basetime is used to calculate the compensated real time of day. The | |
| 198 | * basetime can be modified on a per-tick basis by the adjtime(), | |
| 199 | * ntp_adjtime(), and sysctl-based time correction APIs. | |
| 200 | * | |
| 201 | * Note that frequency corrections can also be made by adjusting | |
| 202 | * gd_cpuclock_base. | |
| 203 | * | |
| 204 | * basetime is a tail-chasing FIFO, updated only by cpu #0. The FIFO is | |
| 205 | * used on both SMP and UP systems to avoid MP races between cpu's and | |
| 206 | * interrupt races on UP systems. | |
| 207 | */ | |
| 208 | #define BASETIME_ARYSIZE 16 | |
| 209 | #define BASETIME_ARYMASK (BASETIME_ARYSIZE - 1) | |
| 210 | static struct timespec basetime[BASETIME_ARYSIZE]; | |
| 211 | static volatile int basetime_index; | |
| 212 | ||
| 213 | static int | |
| 214 | sysctl_get_basetime(SYSCTL_HANDLER_ARGS) | |
| 215 | { | |
| 216 | struct timespec *bt; | |
| 217 | int error; | |
| 35238fa5 | 218 | int index; |
| 5eb5a6bc | 219 | |
| 35238fa5 MD |
220 | /* |
| 221 | * Because basetime data and index may be updated by another cpu, | |
| 222 | * a load fence is required to ensure that the data we read has | |
| 223 | * not been speculatively read relative to a possibly updated index. | |
| 224 | */ | |
| 225 | index = basetime_index; | |
| 226 | cpu_lfence(); | |
| 227 | bt = &basetime[index]; | |
| 08f95c49 | 228 | error = SYSCTL_OUT(req, bt, sizeof(*bt)); |
| 5eb5a6bc MD |
229 | return (error); |
| 230 | } | |
| 231 | ||
| 984263bc | 232 | SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RD, |
| 08f95c49 | 233 | &boottime, timespec, "System boottime"); |
| 5eb5a6bc | 234 | SYSCTL_PROC(_kern, OID_AUTO, basetime, CTLTYPE_STRUCT|CTLFLAG_RD, 0, 0, |
| 08f95c49 | 235 | sysctl_get_basetime, "S,timespec", "System basetime"); |
| 984263bc | 236 | |
| 96d52ac8 SZ |
237 | static void hardclock(systimer_t info, int, struct intrframe *frame); |
| 238 | static void statclock(systimer_t info, int, struct intrframe *frame); | |
| 239 | static void schedclock(systimer_t info, int, struct intrframe *frame); | |
| 5eb5a6bc | 240 | static void getnanotime_nbt(struct timespec *nbt, struct timespec *tsp); |
| 88c4d2f6 MD |
241 | |
| 242 | int ticks; /* system master ticks at hz */ | |
| da3639ef | 243 | int clocks_running; /* tsleep/timeout clocks operational */ |
| 88c4d2f6 MD |
244 | int64_t nsec_adj; /* ntpd per-tick adjustment in nsec << 32 */ |
| 245 | int64_t nsec_acc; /* accumulator */ | |
| 984263bc | 246 | |
| 4026c000 JS |
247 | /* NTPD time correction fields */ |
| 248 | int64_t ntp_tick_permanent; /* per-tick adjustment in nsec << 32 */ | |
| 249 | int64_t ntp_tick_acc; /* accumulator for per-tick adjustment */ | |
| 250 | int64_t ntp_delta; /* one-time correction in nsec */ | |
| 251 | int64_t ntp_big_delta = 1000000000; | |
| 252 | int32_t ntp_tick_delta; /* current adjustment rate */ | |
| 253 | int32_t ntp_default_tick_delta; /* adjustment rate for ntp_delta */ | |
| 48590578 JS |
254 | time_t ntp_leap_second; /* time of next leap second */ |
| 255 | int ntp_leap_insert; /* whether to insert or remove a second */ | |
| 4026c000 | 256 | |
| 984263bc | 257 | /* |
| 88c4d2f6 | 258 | * Finish initializing clock frequencies and start all clocks running. |
| 984263bc | 259 | */ |
| 88c4d2f6 MD |
260 | /* ARGSUSED*/ |
| 261 | static void | |
| 262 | initclocks(void *dummy) | |
| 984263bc | 263 | { |
| 88c4d2f6 MD |
264 | /*psratio = profhz / stathz;*/ |
| 265 | initclocks_pcpu(); | |
| da3639ef | 266 | clocks_running = 1; |
| 984263bc MD |
267 | } |
| 268 | ||
| 88c4d2f6 MD |
269 | /* |
| 270 | * Called on a per-cpu basis | |
| 271 | */ | |
| 272 | void | |
| 273 | initclocks_pcpu(void) | |
| 274 | { | |
| 275 | struct globaldata *gd = mycpu; | |
| 984263bc | 276 | |
| 88c4d2f6 MD |
277 | crit_enter(); |
| 278 | if (gd->gd_cpuid == 0) { | |
| 279 | gd->gd_time_seconds = 1; | |
| 044ee7c4 | 280 | gd->gd_cpuclock_base = sys_cputimer->count(); |
| 88c4d2f6 MD |
281 | } else { |
| 282 | /* XXX */ | |
| 283 | gd->gd_time_seconds = globaldata_find(0)->gd_time_seconds; | |
| 284 | gd->gd_cpuclock_base = globaldata_find(0)->gd_cpuclock_base; | |
| 285 | } | |
| 0d1dffdf | 286 | |
| 43adde98 SZ |
287 | systimer_intr_enable(); |
| 288 | ||
| 94ebffcd SZ |
289 | #ifdef DEVICE_POLLING |
| 290 | init_device_poll_pcpu(gd->gd_cpuid); | |
| 291 | #endif | |
| 292 | ||
| b3a7093f SZ |
293 | #ifdef IFPOLL_ENABLE |
| 294 | ifpoll_init_pcpu(gd->gd_cpuid); | |
| 295 | #endif | |
| 296 | ||
| 0d1dffdf MD |
297 | /* |
| 298 | * Use a non-queued periodic systimer to prevent multiple ticks from | |
| 299 | * building up if the sysclock jumps forward (8254 gets reset). The | |
| 300 | * sysclock will never jump backwards. Our time sync is based on | |
| 301 | * the actual sysclock, not the ticks count. | |
| 302 | */ | |
| 303 | systimer_init_periodic_nq(&gd->gd_hardclock, hardclock, NULL, hz); | |
| 304 | systimer_init_periodic_nq(&gd->gd_statclock, statclock, NULL, stathz); | |
| 88c4d2f6 | 305 | /* XXX correct the frequency for scheduler / estcpu tests */ |
| 0d1dffdf | 306 | systimer_init_periodic_nq(&gd->gd_schedclock, schedclock, |
| 8478264a | 307 | NULL, ESTCPUFREQ); |
| 88c4d2f6 MD |
308 | crit_exit(); |
| 309 | } | |
| 984263bc MD |
310 | |
| 311 | /* | |
| 88c4d2f6 MD |
312 | * This sets the current real time of day. Timespecs are in seconds and |
| 313 | * nanoseconds. We do not mess with gd_time_seconds and gd_cpuclock_base, | |
| 314 | * instead we adjust basetime so basetime + gd_* results in the current | |
| 315 | * time of day. This way the gd_* fields are guarenteed to represent | |
| 316 | * a monotonically increasing 'uptime' value. | |
| 5eb5a6bc MD |
317 | * |
| 318 | * When set_timeofday() is called from userland, the system call forces it | |
| 319 | * onto cpu #0 since only cpu #0 can update basetime_index. | |
| 984263bc | 320 | */ |
| 88c4d2f6 MD |
321 | void |
| 322 | set_timeofday(struct timespec *ts) | |
| 323 | { | |
| 5eb5a6bc MD |
324 | struct timespec *nbt; |
| 325 | int ni; | |
| 984263bc | 326 | |
| 88c4d2f6 MD |
327 | /* |
| 328 | * XXX SMP / non-atomic basetime updates | |
| 329 | */ | |
| 330 | crit_enter(); | |
| 5eb5a6bc MD |
331 | ni = (basetime_index + 1) & BASETIME_ARYMASK; |
| 332 | nbt = &basetime[ni]; | |
| 333 | nanouptime(nbt); | |
| 334 | nbt->tv_sec = ts->tv_sec - nbt->tv_sec; | |
| 335 | nbt->tv_nsec = ts->tv_nsec - nbt->tv_nsec; | |
| 336 | if (nbt->tv_nsec < 0) { | |
| 337 | nbt->tv_nsec += 1000000000; | |
| 338 | --nbt->tv_sec; | |
| 88c4d2f6 | 339 | } |
| a81931cc MD |
340 | |
| 341 | /* | |
| 342 | * Note that basetime diverges from boottime as the clock drift is | |
| 343 | * compensated for, so we cannot do away with boottime. When setting | |
| 344 | * the absolute time of day the drift is 0 (for an instant) and we | |
| 345 | * can simply assign boottime to basetime. | |
| 346 | * | |
| 347 | * Note that nanouptime() is based on gd_time_seconds which is drift | |
| 348 | * compensated up to a point (it is guarenteed to remain monotonically | |
| 349 | * increasing). gd_time_seconds is thus our best uptime guess and | |
| 350 | * suitable for use in the boottime calculation. It is already taken | |
| 351 | * into account in the basetime calculation above. | |
| 352 | */ | |
| 5eb5a6bc | 353 | boottime.tv_sec = nbt->tv_sec; |
| 4026c000 | 354 | ntp_delta = 0; |
| 5eb5a6bc MD |
355 | |
| 356 | /* | |
| 35238fa5 MD |
357 | * We now have a new basetime, make sure all other cpus have it, |
| 358 | * then update the index. | |
| 5eb5a6bc | 359 | */ |
| 35238fa5 | 360 | cpu_sfence(); |
| 5eb5a6bc MD |
361 | basetime_index = ni; |
| 362 | ||
| 88c4d2f6 MD |
363 | crit_exit(); |
| 364 | } | |
| 365 | ||
| 984263bc | 366 | /* |
| 88c4d2f6 MD |
367 | * Each cpu has its own hardclock, but we only increments ticks and softticks |
| 368 | * on cpu #0. | |
| 369 | * | |
| 370 | * NOTE! systimer! the MP lock might not be held here. We can only safely | |
| 371 | * manipulate objects owned by the current cpu. | |
| 984263bc | 372 | */ |
| 984263bc | 373 | static void |
| 96d52ac8 | 374 | hardclock(systimer_t info, int in_ipi __unused, struct intrframe *frame) |
| 984263bc | 375 | { |
| 88c4d2f6 MD |
376 | sysclock_t cputicks; |
| 377 | struct proc *p; | |
| 88c4d2f6 | 378 | struct globaldata *gd = mycpu; |
| 984263bc MD |
379 | |
| 380 | /* | |
| 88c4d2f6 MD |
381 | * Realtime updates are per-cpu. Note that timer corrections as |
| 382 | * returned by microtime() and friends make an additional adjustment | |
| 383 | * using a system-wise 'basetime', but the running time is always | |
| 384 | * taken from the per-cpu globaldata area. Since the same clock | |
| 385 | * is distributing (XXX SMP) to all cpus, the per-cpu timebases | |
| 386 | * stay in synch. | |
| 387 | * | |
| 388 | * Note that we never allow info->time (aka gd->gd_hardclock.time) | |
| fad57d0e MD |
389 | * to reverse index gd_cpuclock_base, but that it is possible for |
| 390 | * it to temporarily get behind in the seconds if something in the | |
| 391 | * system locks interrupts for a long period of time. Since periodic | |
| 392 | * timers count events, though everything should resynch again | |
| 393 | * immediately. | |
| 984263bc | 394 | */ |
| 88c4d2f6 | 395 | cputicks = info->time - gd->gd_cpuclock_base; |
| 044ee7c4 | 396 | if (cputicks >= sys_cputimer->freq) { |
| 88c4d2f6 | 397 | ++gd->gd_time_seconds; |
| 044ee7c4 | 398 | gd->gd_cpuclock_base += sys_cputimer->freq; |
| 88c4d2f6 | 399 | } |
| 984263bc MD |
400 | |
| 401 | /* | |
| 92b561b7 MD |
402 | * The system-wide ticks counter and NTP related timedelta/tickdelta |
| 403 | * adjustments only occur on cpu #0. NTP adjustments are accomplished | |
| 404 | * by updating basetime. | |
| 984263bc | 405 | */ |
| 88c4d2f6 | 406 | if (gd->gd_cpuid == 0) { |
| 5eb5a6bc | 407 | struct timespec *nbt; |
| 88c4d2f6 MD |
408 | struct timespec nts; |
| 409 | int leap; | |
| 5eb5a6bc | 410 | int ni; |
| 984263bc | 411 | |
| 88c4d2f6 | 412 | ++ticks; |
| 984263bc | 413 | |
| 88c4d2f6 MD |
414 | #if 0 |
| 415 | if (tco->tc_poll_pps) | |
| 416 | tco->tc_poll_pps(tco); | |
| 417 | #endif | |
| 5eb5a6bc | 418 | |
| 88c4d2f6 | 419 | /* |
| 5eb5a6bc MD |
420 | * Calculate the new basetime index. We are in a critical section |
| 421 | * on cpu #0 and can safely play with basetime_index. Start | |
| 422 | * with the current basetime and then make adjustments. | |
| 423 | */ | |
| 424 | ni = (basetime_index + 1) & BASETIME_ARYMASK; | |
| 425 | nbt = &basetime[ni]; | |
| 426 | *nbt = basetime[basetime_index]; | |
| 427 | ||
| 428 | /* | |
| 429 | * Apply adjtime corrections. (adjtime() API) | |
| 430 | * | |
| 431 | * adjtime() only runs on cpu #0 so our critical section is | |
| 432 | * sufficient to access these variables. | |
| 88c4d2f6 | 433 | */ |
| 4026c000 | 434 | if (ntp_delta != 0) { |
| 5eb5a6bc | 435 | nbt->tv_nsec += ntp_tick_delta; |
| 4026c000 JS |
436 | ntp_delta -= ntp_tick_delta; |
| 437 | if ((ntp_delta > 0 && ntp_delta < ntp_tick_delta) || | |
| 438 | (ntp_delta < 0 && ntp_delta > ntp_tick_delta)) { | |
| 5eb5a6bc | 439 | ntp_tick_delta = ntp_delta; |
| 4026c000 JS |
440 | } |
| 441 | } | |
| 442 | ||
| 5eb5a6bc MD |
443 | /* |
| 444 | * Apply permanent frequency corrections. (sysctl API) | |
| 445 | */ | |
| 4026c000 JS |
446 | if (ntp_tick_permanent != 0) { |
| 447 | ntp_tick_acc += ntp_tick_permanent; | |
| 448 | if (ntp_tick_acc >= (1LL << 32)) { | |
| 5eb5a6bc | 449 | nbt->tv_nsec += ntp_tick_acc >> 32; |
| 331bc6f8 | 450 | ntp_tick_acc -= (ntp_tick_acc >> 32) << 32; |
| 4026c000 | 451 | } else if (ntp_tick_acc <= -(1LL << 32)) { |
| 331bc6f8 | 452 | /* Negate ntp_tick_acc to avoid shifting the sign bit. */ |
| 5eb5a6bc | 453 | nbt->tv_nsec -= (-ntp_tick_acc) >> 32; |
| 331bc6f8 | 454 | ntp_tick_acc += ((-ntp_tick_acc) >> 32) << 32; |
| 4026c000 JS |
455 | } |
| 456 | } | |
| 457 | ||
| 5eb5a6bc MD |
458 | if (nbt->tv_nsec >= 1000000000) { |
| 459 | nbt->tv_sec++; | |
| 460 | nbt->tv_nsec -= 1000000000; | |
| 461 | } else if (nbt->tv_nsec < 0) { | |
| 462 | nbt->tv_sec--; | |
| 463 | nbt->tv_nsec += 1000000000; | |
| 88c4d2f6 MD |
464 | } |
| 465 | ||
| 466 | /* | |
| 5eb5a6bc | 467 | * Another per-tick compensation. (for ntp_adjtime() API) |
| 88c4d2f6 | 468 | */ |
| 5eb5a6bc | 469 | if (nsec_adj != 0) { |
| 88c4d2f6 MD |
470 | nsec_acc += nsec_adj; |
| 471 | if (nsec_acc >= 0x100000000LL) { | |
| 5eb5a6bc | 472 | nbt->tv_nsec += nsec_acc >> 32; |
| 88c4d2f6 MD |
473 | nsec_acc = (nsec_acc & 0xFFFFFFFFLL); |
| 474 | } else if (nsec_acc <= -0x100000000LL) { | |
| 5eb5a6bc | 475 | nbt->tv_nsec -= -nsec_acc >> 32; |
| 88c4d2f6 MD |
476 | nsec_acc = -(-nsec_acc & 0xFFFFFFFFLL); |
| 477 | } | |
| 5eb5a6bc MD |
478 | if (nbt->tv_nsec >= 1000000000) { |
| 479 | nbt->tv_nsec -= 1000000000; | |
| 480 | ++nbt->tv_sec; | |
| 481 | } else if (nbt->tv_nsec < 0) { | |
| 482 | nbt->tv_nsec += 1000000000; | |
| 483 | --nbt->tv_sec; | |
| 484 | } | |
| 485 | } | |
| 486 | ||
| 487 | /************************************************************ | |
| 488 | * LEAP SECOND CORRECTION * | |
| 489 | ************************************************************ | |
| 490 | * | |
| 491 | * Taking into account all the corrections made above, figure | |
| 492 | * out the new real time. If the seconds field has changed | |
| 493 | * then apply any pending leap-second corrections. | |
| 494 | */ | |
| 495 | getnanotime_nbt(nbt, &nts); | |
| 496 | ||
| 32040d57 MD |
497 | if (time_second != nts.tv_sec) { |
| 498 | /* | |
| 499 | * Apply leap second (sysctl API). Adjust nts for changes | |
| 500 | * so we do not have to call getnanotime_nbt again. | |
| 501 | */ | |
| 502 | if (ntp_leap_second) { | |
| 503 | if (ntp_leap_second == nts.tv_sec) { | |
| 504 | if (ntp_leap_insert) { | |
| 505 | nbt->tv_sec++; | |
| 506 | nts.tv_sec++; | |
| 507 | } else { | |
| 508 | nbt->tv_sec--; | |
| 509 | nts.tv_sec--; | |
| 510 | } | |
| 5eb5a6bc | 511 | ntp_leap_second--; |
| 32040d57 | 512 | } |
| 88c4d2f6 | 513 | } |
| 88c4d2f6 | 514 | |
| 32040d57 MD |
515 | /* |
| 516 | * Apply leap second (ntp_adjtime() API), calculate a new | |
| 517 | * nsec_adj field. ntp_update_second() returns nsec_adj | |
| 518 | * as a per-second value but we need it as a per-tick value. | |
| 519 | */ | |
| 88c4d2f6 | 520 | leap = ntp_update_second(time_second, &nsec_adj); |
| 88c4d2f6 | 521 | nsec_adj /= hz; |
| 32040d57 MD |
522 | nbt->tv_sec += leap; |
| 523 | nts.tv_sec += leap; | |
| 524 | ||
| 525 | /* | |
| 526 | * Update the time_second 'approximate time' global. | |
| 527 | */ | |
| 528 | time_second = nts.tv_sec; | |
| 88c4d2f6 | 529 | } |
| 5eb5a6bc MD |
530 | |
| 531 | /* | |
| 532 | * Finally, our new basetime is ready to go live! | |
| 533 | */ | |
| 35238fa5 | 534 | cpu_sfence(); |
| 5eb5a6bc | 535 | basetime_index = ni; |
| 88c4d2f6 MD |
536 | } |
| 537 | ||
| 538 | /* | |
| f9235b6d MD |
539 | * lwkt thread scheduler fair queueing |
| 540 | */ | |
| 85946b6c | 541 | lwkt_schedulerclock(curthread); |
| f9235b6d MD |
542 | |
| 543 | /* | |
| 92b561b7 MD |
544 | * softticks are handled for all cpus |
| 545 | */ | |
| 546 | hardclock_softtick(gd); | |
| 547 | ||
| 548 | /* | |
| 8582ec21 MD |
549 | * ITimer handling is per-tick, per-cpu. |
| 550 | * | |
| 551 | * We must acquire the per-process token in order for ksignal() | |
| 898e34b3 MD |
552 | * to be non-blocking. For the moment this requires an AST fault, |
| 553 | * the ksignal() cannot be safely issued from this hard interrupt. | |
| 554 | * | |
| 555 | * XXX Even the trytoken here isn't right, and itimer operation in | |
| 556 | * a multi threaded environment is going to be weird at the | |
| 557 | * very least. | |
| 88c4d2f6 | 558 | */ |
| 8582ec21 | 559 | if ((p = curproc) != NULL && lwkt_trytoken(&p->p_token)) { |
| 3dbbd6dd | 560 | crit_enter_hard(); |
| 88c4d2f6 | 561 | if (frame && CLKF_USERMODE(frame) && |
| 93328593 | 562 | timevalisset(&p->p_timer[ITIMER_VIRTUAL].it_value) && |
| 898e34b3 | 563 | itimerdecr(&p->p_timer[ITIMER_VIRTUAL], ustick) == 0) { |
| 4643740a | 564 | p->p_flags |= P_SIGVTALRM; |
| 898e34b3 MD |
565 | need_user_resched(); |
| 566 | } | |
| 93328593 | 567 | if (timevalisset(&p->p_timer[ITIMER_PROF].it_value) && |
| 898e34b3 | 568 | itimerdecr(&p->p_timer[ITIMER_PROF], ustick) == 0) { |
| 4643740a | 569 | p->p_flags |= P_SIGPROF; |
| 898e34b3 MD |
570 | need_user_resched(); |
| 571 | } | |
| 3dbbd6dd | 572 | crit_exit_hard(); |
| 8582ec21 | 573 | lwkt_reltoken(&p->p_token); |
| 984263bc | 574 | } |
| 604e1e09 | 575 | setdelayed(); |
| 88c4d2f6 | 576 | } |
| 984263bc | 577 | |
| 88c4d2f6 MD |
578 | /* |
| 579 | * The statistics clock typically runs at a 125Hz rate, and is intended | |
| 580 | * to be frequency offset from the hardclock (typ 100Hz). It is per-cpu. | |
| 581 | * | |
| 582 | * NOTE! systimer! the MP lock might not be held here. We can only safely | |
| 583 | * manipulate objects owned by the current cpu. | |
| 584 | * | |
| 585 | * The stats clock is responsible for grabbing a profiling sample. | |
| 586 | * Most of the statistics are only used by user-level statistics programs. | |
| 587 | * The main exceptions are p->p_uticks, p->p_sticks, p->p_iticks, and | |
| 588 | * p->p_estcpu. | |
| 589 | * | |
| 590 | * Like the other clocks, the stat clock is called from what is effectively | |
| 591 | * a fast interrupt, so the context should be the thread/process that got | |
| 592 | * interrupted. | |
| 593 | */ | |
| 594 | static void | |
| 96d52ac8 | 595 | statclock(systimer_t info, int in_ipi, struct intrframe *frame) |
| 88c4d2f6 MD |
596 | { |
| 597 | #ifdef GPROF | |
| 598 | struct gmonparam *g; | |
| 599 | int i; | |
| 984263bc | 600 | #endif |
| 88c4d2f6 MD |
601 | thread_t td; |
| 602 | struct proc *p; | |
| 603 | int bump; | |
| 604 | struct timeval tv; | |
| 605 | struct timeval *stv; | |
| 984263bc MD |
606 | |
| 607 | /* | |
| 88c4d2f6 | 608 | * How big was our timeslice relative to the last time? |
| 984263bc | 609 | */ |
| 88c4d2f6 MD |
610 | microuptime(&tv); /* mpsafe */ |
| 611 | stv = &mycpu->gd_stattv; | |
| 612 | if (stv->tv_sec == 0) { | |
| 613 | bump = 1; | |
| 614 | } else { | |
| 615 | bump = tv.tv_usec - stv->tv_usec + | |
| 616 | (tv.tv_sec - stv->tv_sec) * 1000000; | |
| 617 | if (bump < 0) | |
| 618 | bump = 0; | |
| 619 | if (bump > 1000000) | |
| 620 | bump = 1000000; | |
| 621 | } | |
| 622 | *stv = tv; | |
| 984263bc | 623 | |
| 88c4d2f6 MD |
624 | td = curthread; |
| 625 | p = td->td_proc; | |
| 984263bc | 626 | |
| 88c4d2f6 MD |
627 | if (frame && CLKF_USERMODE(frame)) { |
| 628 | /* | |
| 629 | * Came from userland, handle user time and deal with | |
| 630 | * possible process. | |
| 631 | */ | |
| 4643740a | 632 | if (p && (p->p_flags & P_PROFIL)) |
| 88c4d2f6 MD |
633 | addupc_intr(p, CLKF_PC(frame), 1); |
| 634 | td->td_uticks += bump; | |
| 984263bc | 635 | |
| 88c4d2f6 MD |
636 | /* |
| 637 | * Charge the time as appropriate | |
| 638 | */ | |
| 639 | if (p && p->p_nice > NZERO) | |
| 9eea7f0c | 640 | cpu_time.cp_nice += bump; |
| 88c4d2f6 | 641 | else |
| 9eea7f0c | 642 | cpu_time.cp_user += bump; |
| 88c4d2f6 | 643 | } else { |
| 96d52ac8 SZ |
644 | int intr_nest = mycpu->gd_intr_nesting_level; |
| 645 | ||
| 646 | if (in_ipi) { | |
| 647 | /* | |
| 648 | * IPI processing code will bump gd_intr_nesting_level | |
| 649 | * up by one, which breaks following CLKF_INTR testing, | |
| 650 | * so we substract it by one here. | |
| 651 | */ | |
| 652 | --intr_nest; | |
| 653 | } | |
| 88c4d2f6 MD |
654 | #ifdef GPROF |
| 655 | /* | |
| 656 | * Kernel statistics are just like addupc_intr, only easier. | |
| 657 | */ | |
| 658 | g = &_gmonparam; | |
| 659 | if (g->state == GMON_PROF_ON && frame) { | |
| 660 | i = CLKF_PC(frame) - g->lowpc; | |
| 661 | if (i < g->textsize) { | |
| 662 | i /= HISTFRACTION * sizeof(*g->kcount); | |
| 663 | g->kcount[i]++; | |
| 664 | } | |
| 665 | } | |
| 666 | #endif | |
| 667 | /* | |
| 668 | * Came from kernel mode, so we were: | |
| 669 | * - handling an interrupt, | |
| 670 | * - doing syscall or trap work on behalf of the current | |
| 671 | * user process, or | |
| 672 | * - spinning in the idle loop. | |
| 673 | * Whichever it is, charge the time as appropriate. | |
| 674 | * Note that we charge interrupts to the current process, | |
| 675 | * regardless of whether they are ``for'' that process, | |
| 676 | * so that we know how much of its real time was spent | |
| 677 | * in ``non-process'' (i.e., interrupt) work. | |
| 678 | * | |
| 679 | * XXX assume system if frame is NULL. A NULL frame | |
| e43a034f | 680 | * can occur if ipi processing is done from a crit_exit(). |
| 88c4d2f6 | 681 | */ |
| 96d52ac8 | 682 | if (frame && CLKF_INTR(intr_nest)) |
| 88c4d2f6 MD |
683 | td->td_iticks += bump; |
| 684 | else | |
| 685 | td->td_sticks += bump; | |
| 686 | ||
| 96d52ac8 | 687 | if (frame && CLKF_INTR(intr_nest)) { |
| 07522099 MD |
688 | #ifdef DEBUG_PCTRACK |
| 689 | do_pctrack(frame, PCTRACK_INT); | |
| 690 | #endif | |
| 9eea7f0c | 691 | cpu_time.cp_intr += bump; |
| 88c4d2f6 | 692 | } else { |
| 07522099 | 693 | if (td == &mycpu->gd_idlethread) { |
| 9eea7f0c | 694 | cpu_time.cp_idle += bump; |
| 07522099 MD |
695 | } else { |
| 696 | #ifdef DEBUG_PCTRACK | |
| 697 | if (frame) | |
| 698 | do_pctrack(frame, PCTRACK_SYS); | |
| 699 | #endif | |
| 9eea7f0c | 700 | cpu_time.cp_sys += bump; |
| 07522099 | 701 | } |
| 88c4d2f6 MD |
702 | } |
| 703 | } | |
| 704 | } | |
| 705 | ||
| 07522099 MD |
706 | #ifdef DEBUG_PCTRACK |
| 707 | /* | |
| 708 | * Sample the PC when in the kernel or in an interrupt. User code can | |
| 709 | * retrieve the information and generate a histogram or other output. | |
| 710 | */ | |
| 711 | ||
| 712 | static void | |
| 713 | do_pctrack(struct intrframe *frame, int which) | |
| 714 | { | |
| 715 | struct kinfo_pctrack *pctrack; | |
| 716 | ||
| 717 | pctrack = &cputime_pctrack[mycpu->gd_cpuid][which]; | |
| 718 | pctrack->pc_array[pctrack->pc_index & PCTRACK_ARYMASK] = | |
| 719 | (void *)CLKF_PC(frame); | |
| 720 | ++pctrack->pc_index; | |
| 721 | } | |
| 722 | ||
| 723 | static int | |
| 724 | sysctl_pctrack(SYSCTL_HANDLER_ARGS) | |
| 725 | { | |
| 726 | struct kinfo_pcheader head; | |
| 727 | int error; | |
| 728 | int cpu; | |
| 729 | int ntrack; | |
| 730 | ||
| 731 | head.pc_ntrack = PCTRACK_SIZE; | |
| 732 | head.pc_arysize = PCTRACK_ARYSIZE; | |
| 733 | ||
| 734 | if ((error = SYSCTL_OUT(req, &head, sizeof(head))) != 0) | |
| 735 | return (error); | |
| 736 | ||
| 737 | for (cpu = 0; cpu < ncpus; ++cpu) { | |
| 738 | for (ntrack = 0; ntrack < PCTRACK_SIZE; ++ntrack) { | |
| 739 | error = SYSCTL_OUT(req, &cputime_pctrack[cpu][ntrack], | |
| 740 | sizeof(struct kinfo_pctrack)); | |
| 741 | if (error) | |
| 742 | break; | |
| 743 | } | |
| 744 | if (error) | |
| 745 | break; | |
| 746 | } | |
| 747 | return (error); | |
| 748 | } | |
| 749 | SYSCTL_PROC(_kern, OID_AUTO, pctrack, (CTLTYPE_OPAQUE|CTLFLAG_RD), 0, 0, | |
| 750 | sysctl_pctrack, "S,kinfo_pcheader", "CPU PC tracking"); | |
| 751 | ||
| 752 | #endif | |
| 753 | ||
| 88c4d2f6 | 754 | /* |
| dcc99b62 | 755 | * The scheduler clock typically runs at a 50Hz rate. NOTE! systimer, |
| 88c4d2f6 MD |
756 | * the MP lock might not be held. We can safely manipulate parts of curproc |
| 757 | * but that's about it. | |
| dcc99b62 MD |
758 | * |
| 759 | * Each cpu has its own scheduler clock. | |
| 88c4d2f6 MD |
760 | */ |
| 761 | static void | |
| 96d52ac8 | 762 | schedclock(systimer_t info, int in_ipi __unused, struct intrframe *frame) |
| 88c4d2f6 | 763 | { |
| 553ea3c8 | 764 | struct lwp *lp; |
| 88c4d2f6 MD |
765 | struct rusage *ru; |
| 766 | struct vmspace *vm; | |
| 767 | long rss; | |
| 768 | ||
| 553ea3c8 | 769 | if ((lp = lwkt_preempted_proc()) != NULL) { |
| dcc99b62 MD |
770 | /* |
| 771 | * Account for cpu time used and hit the scheduler. Note | |
| 772 | * that this call MUST BE MP SAFE, and the BGL IS NOT HELD | |
| 773 | * HERE. | |
| 774 | */ | |
| 553ea3c8 | 775 | ++lp->lwp_cpticks; |
| 5681a38a MD |
776 | lp->lwp_proc->p_usched->schedulerclock(lp, info->periodic, |
| 777 | info->time); | |
| dcc99b62 | 778 | } |
| 553ea3c8 | 779 | if ((lp = curthread->td_lwp) != NULL) { |
| dcc99b62 MD |
780 | /* |
| 781 | * Update resource usage integrals and maximums. | |
| 782 | */ | |
| fde7ac71 | 783 | if ((ru = &lp->lwp_proc->p_ru) && |
| 553ea3c8 | 784 | (vm = lp->lwp_proc->p_vmspace) != NULL) { |
| 88c4d2f6 MD |
785 | ru->ru_ixrss += pgtok(vm->vm_tsize); |
| 786 | ru->ru_idrss += pgtok(vm->vm_dsize); | |
| 787 | ru->ru_isrss += pgtok(vm->vm_ssize); | |
| b12defdc MD |
788 | if (lwkt_trytoken(&vm->vm_map.token)) { |
| 789 | rss = pgtok(vmspace_resident_count(vm)); | |
| 790 | if (ru->ru_maxrss < rss) | |
| 791 | ru->ru_maxrss = rss; | |
| 792 | lwkt_reltoken(&vm->vm_map.token); | |
| 793 | } | |
| 88c4d2f6 | 794 | } |
| b68b7282 | 795 | } |
| 984263bc MD |
796 | } |
| 797 | ||
| 798 | /* | |
| a94976ad MD |
799 | * Compute number of ticks for the specified amount of time. The |
| 800 | * return value is intended to be used in a clock interrupt timed | |
| 801 | * operation and guarenteed to meet or exceed the requested time. | |
| 802 | * If the representation overflows, return INT_MAX. The minimum return | |
| 803 | * value is 1 ticks and the function will average the calculation up. | |
| 804 | * If any value greater then 0 microseconds is supplied, a value | |
| 805 | * of at least 2 will be returned to ensure that a near-term clock | |
| 806 | * interrupt does not cause the timeout to occur (degenerately) early. | |
| 807 | * | |
| 808 | * Note that limit checks must take into account microseconds, which is | |
| 809 | * done simply by using the smaller signed long maximum instead of | |
| 810 | * the unsigned long maximum. | |
| 811 | * | |
| 812 | * If ints have 32 bits, then the maximum value for any timeout in | |
| 813 | * 10ms ticks is 248 days. | |
| 984263bc MD |
814 | */ |
| 815 | int | |
| a94976ad | 816 | tvtohz_high(struct timeval *tv) |
| 984263bc | 817 | { |
| a94976ad | 818 | int ticks; |
| 1fd87d54 | 819 | long sec, usec; |
| 984263bc | 820 | |
| 984263bc MD |
821 | sec = tv->tv_sec; |
| 822 | usec = tv->tv_usec; | |
| 823 | if (usec < 0) { | |
| 824 | sec--; | |
| 825 | usec += 1000000; | |
| 826 | } | |
| 827 | if (sec < 0) { | |
| 828 | #ifdef DIAGNOSTIC | |
| 829 | if (usec > 0) { | |
| 830 | sec++; | |
| 831 | usec -= 1000000; | |
| 832 | } | |
| a591f597 MD |
833 | kprintf("tvtohz_high: negative time difference " |
| 834 | "%ld sec %ld usec\n", | |
| 835 | sec, usec); | |
| 984263bc MD |
836 | #endif |
| 837 | ticks = 1; | |
| a94976ad MD |
838 | } else if (sec <= INT_MAX / hz) { |
| 839 | ticks = (int)(sec * hz + | |
| a591f597 | 840 | ((u_long)usec + (ustick - 1)) / ustick) + 1; |
| a94976ad MD |
841 | } else { |
| 842 | ticks = INT_MAX; | |
| 843 | } | |
| 844 | return (ticks); | |
| 845 | } | |
| 846 | ||
| a591f597 MD |
847 | int |
| 848 | tstohz_high(struct timespec *ts) | |
| 849 | { | |
| 850 | int ticks; | |
| 851 | long sec, nsec; | |
| 852 | ||
| 853 | sec = ts->tv_sec; | |
| 854 | nsec = ts->tv_nsec; | |
| 855 | if (nsec < 0) { | |
| 856 | sec--; | |
| 857 | nsec += 1000000000; | |
| 858 | } | |
| 859 | if (sec < 0) { | |
| 860 | #ifdef DIAGNOSTIC | |
| 861 | if (nsec > 0) { | |
| 862 | sec++; | |
| 863 | nsec -= 1000000000; | |
| 864 | } | |
| 865 | kprintf("tstohz_high: negative time difference " | |
| 866 | "%ld sec %ld nsec\n", | |
| 867 | sec, nsec); | |
| 868 | #endif | |
| 869 | ticks = 1; | |
| 870 | } else if (sec <= INT_MAX / hz) { | |
| 871 | ticks = (int)(sec * hz + | |
| 872 | ((u_long)nsec + (nstick - 1)) / nstick) + 1; | |
| 873 | } else { | |
| 874 | ticks = INT_MAX; | |
| 875 | } | |
| 876 | return (ticks); | |
| 877 | } | |
| 878 | ||
| 879 | ||
| a94976ad MD |
880 | /* |
| 881 | * Compute number of ticks for the specified amount of time, erroring on | |
| 882 | * the side of it being too low to ensure that sleeping the returned number | |
| 883 | * of ticks will not result in a late return. | |
| 884 | * | |
| 885 | * The supplied timeval may not be negative and should be normalized. A | |
| 886 | * return value of 0 is possible if the timeval converts to less then | |
| 887 | * 1 tick. | |
| 888 | * | |
| 889 | * If ints have 32 bits, then the maximum value for any timeout in | |
| 890 | * 10ms ticks is 248 days. | |
| 891 | */ | |
| 892 | int | |
| 893 | tvtohz_low(struct timeval *tv) | |
| 894 | { | |
| 895 | int ticks; | |
| 896 | long sec; | |
| 897 | ||
| 898 | sec = tv->tv_sec; | |
| 899 | if (sec <= INT_MAX / hz) | |
| a591f597 | 900 | ticks = (int)(sec * hz + (u_long)tv->tv_usec / ustick); |
| 984263bc | 901 | else |
| 984263bc | 902 | ticks = INT_MAX; |
| a94976ad | 903 | return (ticks); |
| 984263bc MD |
904 | } |
| 905 | ||
| a591f597 MD |
906 | int |
| 907 | tstohz_low(struct timespec *ts) | |
| 908 | { | |
| 909 | int ticks; | |
| 910 | long sec; | |
| 911 | ||
| 912 | sec = ts->tv_sec; | |
| 913 | if (sec <= INT_MAX / hz) | |
| 914 | ticks = (int)(sec * hz + (u_long)ts->tv_nsec / nstick); | |
| 915 | else | |
| 916 | ticks = INT_MAX; | |
| 917 | return (ticks); | |
| 918 | } | |
| a94976ad | 919 | |
| 984263bc MD |
920 | /* |
| 921 | * Start profiling on a process. | |
| 922 | * | |
| 923 | * Kernel profiling passes proc0 which never exits and hence | |
| 924 | * keeps the profile clock running constantly. | |
| 925 | */ | |
| 926 | void | |
| 88c4d2f6 | 927 | startprofclock(struct proc *p) |
| 984263bc | 928 | { |
| 4643740a MD |
929 | if ((p->p_flags & P_PROFIL) == 0) { |
| 930 | p->p_flags |= P_PROFIL; | |
| 88c4d2f6 | 931 | #if 0 /* XXX */ |
| 984263bc | 932 | if (++profprocs == 1 && stathz != 0) { |
| e43a034f | 933 | crit_enter(); |
| 6ad39cae | 934 | psdiv = psratio; |
| 984263bc | 935 | setstatclockrate(profhz); |
| e43a034f | 936 | crit_exit(); |
| 984263bc | 937 | } |
| 88c4d2f6 | 938 | #endif |
| 984263bc MD |
939 | } |
| 940 | } | |
| 941 | ||
| 942 | /* | |
| 943 | * Stop profiling on a process. | |
| 616516c8 MD |
944 | * |
| 945 | * caller must hold p->p_token | |
| 984263bc MD |
946 | */ |
| 947 | void | |
| 88c4d2f6 | 948 | stopprofclock(struct proc *p) |
| 984263bc | 949 | { |
| 4643740a MD |
950 | if (p->p_flags & P_PROFIL) { |
| 951 | p->p_flags &= ~P_PROFIL; | |
| 88c4d2f6 | 952 | #if 0 /* XXX */ |
| 984263bc | 953 | if (--profprocs == 0 && stathz != 0) { |
| e43a034f | 954 | crit_enter(); |
| 6ad39cae | 955 | psdiv = 1; |
| 984263bc | 956 | setstatclockrate(stathz); |
| e43a034f | 957 | crit_exit(); |
| 984263bc | 958 | } |
| 984263bc | 959 | #endif |
| 984263bc MD |
960 | } |
| 961 | } | |
| 962 | ||
| 963 | /* | |
| 964 | * Return information about system clocks. | |
| 965 | */ | |
| 966 | static int | |
| 967 | sysctl_kern_clockrate(SYSCTL_HANDLER_ARGS) | |
| 968 | { | |
| f5d21610 | 969 | struct kinfo_clockinfo clkinfo; |
| 984263bc MD |
970 | /* |
| 971 | * Construct clockinfo structure. | |
| 972 | */ | |
| f5d21610 | 973 | clkinfo.ci_hz = hz; |
| a591f597 | 974 | clkinfo.ci_tick = ustick; |
| 4026c000 | 975 | clkinfo.ci_tickadj = ntp_default_tick_delta / 1000; |
| f5d21610 JS |
976 | clkinfo.ci_profhz = profhz; |
| 977 | clkinfo.ci_stathz = stathz ? stathz : hz; | |
| 984263bc MD |
978 | return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); |
| 979 | } | |
| 980 | ||
| 981 | SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD, | |
| 982 | 0, 0, sysctl_kern_clockrate, "S,clockinfo",""); | |
| 983 | ||
| 984263bc MD |
984 | /* |
| 985 | * We have eight functions for looking at the clock, four for | |
| 986 | * microseconds and four for nanoseconds. For each there is fast | |
| 987 | * but less precise version "get{nano|micro}[up]time" which will | |
| 988 | * return a time which is up to 1/HZ previous to the call, whereas | |
| 989 | * the raw version "{nano|micro}[up]time" will return a timestamp | |
| 990 | * which is as precise as possible. The "up" variants return the | |
| 991 | * time relative to system boot, these are well suited for time | |
| 992 | * interval measurements. | |
| 88c4d2f6 MD |
993 | * |
| 994 | * Each cpu independantly maintains the current time of day, so all | |
| 995 | * we need to do to protect ourselves from changes is to do a loop | |
| 996 | * check on the seconds field changing out from under us. | |
| fad57d0e MD |
997 | * |
| 998 | * The system timer maintains a 32 bit count and due to various issues | |
| 999 | * it is possible for the calculated delta to occassionally exceed | |
| 044ee7c4 MD |
1000 | * sys_cputimer->freq. If this occurs the sys_cputimer->freq64_nsec |
| 1001 | * multiplication can easily overflow, so we deal with the case. For | |
| 1002 | * uniformity we deal with the case in the usec case too. | |
| 627531fa MD |
1003 | * |
| 1004 | * All the [get][micro,nano][time,uptime]() routines are MPSAFE. | |
| 984263bc | 1005 | */ |
| 984263bc MD |
1006 | void |
| 1007 | getmicrouptime(struct timeval *tvp) | |
| 1008 | { | |
| 88c4d2f6 MD |
1009 | struct globaldata *gd = mycpu; |
| 1010 | sysclock_t delta; | |
| 1011 | ||
| 1012 | do { | |
| 1013 | tvp->tv_sec = gd->gd_time_seconds; | |
| 1014 | delta = gd->gd_hardclock.time - gd->gd_cpuclock_base; | |
| 1015 | } while (tvp->tv_sec != gd->gd_time_seconds); | |
| fad57d0e | 1016 | |
| 044ee7c4 MD |
1017 | if (delta >= sys_cputimer->freq) { |
| 1018 | tvp->tv_sec += delta / sys_cputimer->freq; | |
| 1019 | delta %= sys_cputimer->freq; | |
| fad57d0e | 1020 | } |
| 044ee7c4 | 1021 | tvp->tv_usec = (sys_cputimer->freq64_usec * delta) >> 32; |
| 88c4d2f6 MD |
1022 | if (tvp->tv_usec >= 1000000) { |
| 1023 | tvp->tv_usec -= 1000000; | |
| 1024 | ++tvp->tv_sec; | |
| 984263bc MD |
1025 | } |
| 1026 | } | |
| 1027 | ||
| 1028 | void | |
| 1029 | getnanouptime(struct timespec *tsp) | |
| 1030 | { | |
| 88c4d2f6 MD |
1031 | struct globaldata *gd = mycpu; |
| 1032 | sysclock_t delta; | |
| 1033 | ||
| 1034 | do { | |
| 1035 | tsp->tv_sec = gd->gd_time_seconds; | |
| 1036 | delta = gd->gd_hardclock.time - gd->gd_cpuclock_base; | |
| 1037 | } while (tsp->tv_sec != gd->gd_time_seconds); | |
| fad57d0e | 1038 | |
| 044ee7c4 MD |
1039 | if (delta >= sys_cputimer->freq) { |
| 1040 | tsp->tv_sec += delta / sys_cputimer->freq; | |
| 1041 | delta %= sys_cputimer->freq; | |
| 984263bc | 1042 | } |
| 044ee7c4 | 1043 | tsp->tv_nsec = (sys_cputimer->freq64_nsec * delta) >> 32; |
| 984263bc MD |
1044 | } |
| 1045 | ||
| 1046 | void | |
| 88c4d2f6 | 1047 | microuptime(struct timeval *tvp) |
| 984263bc | 1048 | { |
| 88c4d2f6 MD |
1049 | struct globaldata *gd = mycpu; |
| 1050 | sysclock_t delta; | |
| 1051 | ||
| 1052 | do { | |
| 1053 | tvp->tv_sec = gd->gd_time_seconds; | |
| 044ee7c4 | 1054 | delta = sys_cputimer->count() - gd->gd_cpuclock_base; |
| 88c4d2f6 | 1055 | } while (tvp->tv_sec != gd->gd_time_seconds); |
| fad57d0e | 1056 | |
| 044ee7c4 MD |
1057 | if (delta >= sys_cputimer->freq) { |
| 1058 | tvp->tv_sec += delta / sys_cputimer->freq; | |
| 1059 | delta %= sys_cputimer->freq; | |
| 984263bc | 1060 | } |
| 044ee7c4 | 1061 | tvp->tv_usec = (sys_cputimer->freq64_usec * delta) >> 32; |
| 984263bc MD |
1062 | } |
| 1063 | ||
| 1064 | void | |
| 88c4d2f6 | 1065 | nanouptime(struct timespec *tsp) |
| 984263bc | 1066 | { |
| 88c4d2f6 MD |
1067 | struct globaldata *gd = mycpu; |
| 1068 | sysclock_t delta; | |
| 1069 | ||
| 1070 | do { | |
| 1071 | tsp->tv_sec = gd->gd_time_seconds; | |
| 044ee7c4 | 1072 | delta = sys_cputimer->count() - gd->gd_cpuclock_base; |
| 88c4d2f6 | 1073 | } while (tsp->tv_sec != gd->gd_time_seconds); |
| fad57d0e | 1074 | |
| 044ee7c4 MD |
1075 | if (delta >= sys_cputimer->freq) { |
| 1076 | tsp->tv_sec += delta / sys_cputimer->freq; | |
| 1077 | delta %= sys_cputimer->freq; | |
| 984263bc | 1078 | } |
| 044ee7c4 | 1079 | tsp->tv_nsec = (sys_cputimer->freq64_nsec * delta) >> 32; |
| 984263bc MD |
1080 | } |
| 1081 | ||
| 88c4d2f6 MD |
1082 | /* |
| 1083 | * realtime routines | |
| 1084 | */ | |
| 984263bc | 1085 | void |
| 88c4d2f6 | 1086 | getmicrotime(struct timeval *tvp) |
| 984263bc | 1087 | { |
| 88c4d2f6 | 1088 | struct globaldata *gd = mycpu; |
| 5eb5a6bc | 1089 | struct timespec *bt; |
| 88c4d2f6 | 1090 | sysclock_t delta; |
| 984263bc | 1091 | |
| 88c4d2f6 MD |
1092 | do { |
| 1093 | tvp->tv_sec = gd->gd_time_seconds; | |
| 1094 | delta = gd->gd_hardclock.time - gd->gd_cpuclock_base; | |
| 1095 | } while (tvp->tv_sec != gd->gd_time_seconds); | |
| fad57d0e | 1096 | |
| 044ee7c4 MD |
1097 | if (delta >= sys_cputimer->freq) { |
| 1098 | tvp->tv_sec += delta / sys_cputimer->freq; | |
| 1099 | delta %= sys_cputimer->freq; | |
| fad57d0e | 1100 | } |
| 044ee7c4 | 1101 | tvp->tv_usec = (sys_cputimer->freq64_usec * delta) >> 32; |
| 984263bc | 1102 | |
| 5eb5a6bc MD |
1103 | bt = &basetime[basetime_index]; |
| 1104 | tvp->tv_sec += bt->tv_sec; | |
| 1105 | tvp->tv_usec += bt->tv_nsec / 1000; | |
| 88c4d2f6 MD |
1106 | while (tvp->tv_usec >= 1000000) { |
| 1107 | tvp->tv_usec -= 1000000; | |
| 1108 | ++tvp->tv_sec; | |
| 984263bc | 1109 | } |
| 984263bc MD |
1110 | } |
| 1111 | ||
| 1112 | void | |
| 88c4d2f6 | 1113 | getnanotime(struct timespec *tsp) |
| 984263bc | 1114 | { |
| 88c4d2f6 | 1115 | struct globaldata *gd = mycpu; |
| 5eb5a6bc | 1116 | struct timespec *bt; |
| 88c4d2f6 | 1117 | sysclock_t delta; |
| 984263bc | 1118 | |
| 88c4d2f6 MD |
1119 | do { |
| 1120 | tsp->tv_sec = gd->gd_time_seconds; | |
| 1121 | delta = gd->gd_hardclock.time - gd->gd_cpuclock_base; | |
| 1122 | } while (tsp->tv_sec != gd->gd_time_seconds); | |
| fad57d0e | 1123 | |
| 044ee7c4 MD |
1124 | if (delta >= sys_cputimer->freq) { |
| 1125 | tsp->tv_sec += delta / sys_cputimer->freq; | |
| 1126 | delta %= sys_cputimer->freq; | |
| fad57d0e | 1127 | } |
| 044ee7c4 | 1128 | tsp->tv_nsec = (sys_cputimer->freq64_nsec * delta) >> 32; |
| 984263bc | 1129 | |
| 5eb5a6bc MD |
1130 | bt = &basetime[basetime_index]; |
| 1131 | tsp->tv_sec += bt->tv_sec; | |
| 1132 | tsp->tv_nsec += bt->tv_nsec; | |
| 88c4d2f6 MD |
1133 | while (tsp->tv_nsec >= 1000000000) { |
| 1134 | tsp->tv_nsec -= 1000000000; | |
| 1135 | ++tsp->tv_sec; | |
| 984263bc | 1136 | } |
| 984263bc MD |
1137 | } |
| 1138 | ||
| 5eb5a6bc MD |
1139 | static void |
| 1140 | getnanotime_nbt(struct timespec *nbt, struct timespec *tsp) | |
| 1141 | { | |
| 1142 | struct globaldata *gd = mycpu; | |
| 1143 | sysclock_t delta; | |
| 1144 | ||
| 1145 | do { | |
| 1146 | tsp->tv_sec = gd->gd_time_seconds; | |
| 1147 | delta = gd->gd_hardclock.time - gd->gd_cpuclock_base; | |
| 1148 | } while (tsp->tv_sec != gd->gd_time_seconds); | |
| 1149 | ||
| 044ee7c4 MD |
1150 | if (delta >= sys_cputimer->freq) { |
| 1151 | tsp->tv_sec += delta / sys_cputimer->freq; | |
| 1152 | delta %= sys_cputimer->freq; | |
| 5eb5a6bc | 1153 | } |
| 044ee7c4 | 1154 | tsp->tv_nsec = (sys_cputimer->freq64_nsec * delta) >> 32; |
| 5eb5a6bc MD |
1155 | |
| 1156 | tsp->tv_sec += nbt->tv_sec; | |
| 1157 | tsp->tv_nsec += nbt->tv_nsec; | |
| 1158 | while (tsp->tv_nsec >= 1000000000) { | |
| 1159 | tsp->tv_nsec -= 1000000000; | |
| 1160 | ++tsp->tv_sec; | |
| 1161 | } | |
| 1162 | } | |
| 1163 | ||
| 1164 | ||
| 88c4d2f6 MD |
1165 | void |
| 1166 | microtime(struct timeval *tvp) | |
| 984263bc | 1167 | { |
| 88c4d2f6 | 1168 | struct globaldata *gd = mycpu; |
| 5eb5a6bc | 1169 | struct timespec *bt; |
| 88c4d2f6 | 1170 | sysclock_t delta; |
| 984263bc | 1171 | |
| 88c4d2f6 MD |
1172 | do { |
| 1173 | tvp->tv_sec = gd->gd_time_seconds; | |
| 044ee7c4 | 1174 | delta = sys_cputimer->count() - gd->gd_cpuclock_base; |
| 88c4d2f6 | 1175 | } while (tvp->tv_sec != gd->gd_time_seconds); |
| fad57d0e | 1176 | |
| 044ee7c4 MD |
1177 | if (delta >= sys_cputimer->freq) { |
| 1178 | tvp->tv_sec += delta / sys_cputimer->freq; | |
| 1179 | delta %= sys_cputimer->freq; | |
| fad57d0e | 1180 | } |
| 044ee7c4 | 1181 | tvp->tv_usec = (sys_cputimer->freq64_usec * delta) >> 32; |
| 984263bc | 1182 | |
| 5eb5a6bc MD |
1183 | bt = &basetime[basetime_index]; |
| 1184 | tvp->tv_sec += bt->tv_sec; | |
| 1185 | tvp->tv_usec += bt->tv_nsec / 1000; | |
| 88c4d2f6 MD |
1186 | while (tvp->tv_usec >= 1000000) { |
| 1187 | tvp->tv_usec -= 1000000; | |
| 1188 | ++tvp->tv_sec; | |
| 984263bc | 1189 | } |
| 984263bc MD |
1190 | } |
| 1191 | ||
| 88c4d2f6 MD |
1192 | void |
| 1193 | nanotime(struct timespec *tsp) | |
| 1194 | { | |
| 1195 | struct globaldata *gd = mycpu; | |
| 5eb5a6bc | 1196 | struct timespec *bt; |
| 88c4d2f6 | 1197 | sysclock_t delta; |
| 984263bc | 1198 | |
| 88c4d2f6 MD |
1199 | do { |
| 1200 | tsp->tv_sec = gd->gd_time_seconds; | |
| 044ee7c4 | 1201 | delta = sys_cputimer->count() - gd->gd_cpuclock_base; |
| 88c4d2f6 | 1202 | } while (tsp->tv_sec != gd->gd_time_seconds); |
| fad57d0e | 1203 | |
| 044ee7c4 MD |
1204 | if (delta >= sys_cputimer->freq) { |
| 1205 | tsp->tv_sec += delta / sys_cputimer->freq; | |
| 1206 | delta %= sys_cputimer->freq; | |
| fad57d0e | 1207 | } |
| 044ee7c4 | 1208 | tsp->tv_nsec = (sys_cputimer->freq64_nsec * delta) >> 32; |
| 984263bc | 1209 | |
| 5eb5a6bc MD |
1210 | bt = &basetime[basetime_index]; |
| 1211 | tsp->tv_sec += bt->tv_sec; | |
| 1212 | tsp->tv_nsec += bt->tv_nsec; | |
| 88c4d2f6 MD |
1213 | while (tsp->tv_nsec >= 1000000000) { |
| 1214 | tsp->tv_nsec -= 1000000000; | |
| 1215 | ++tsp->tv_sec; | |
| 984263bc | 1216 | } |
| 984263bc MD |
1217 | } |
| 1218 | ||
| 25b804e7 MD |
1219 | /* |
| 1220 | * note: this is not exactly synchronized with real time. To do that we | |
| 1221 | * would have to do what microtime does and check for a nanoseconds overflow. | |
| 1222 | */ | |
| 1223 | time_t | |
| 1224 | get_approximate_time_t(void) | |
| 1225 | { | |
| 1226 | struct globaldata *gd = mycpu; | |
| 5eb5a6bc MD |
1227 | struct timespec *bt; |
| 1228 | ||
| 1229 | bt = &basetime[basetime_index]; | |
| 1230 | return(gd->gd_time_seconds + bt->tv_sec); | |
| 25b804e7 MD |
1231 | } |
| 1232 | ||
| 984263bc MD |
1233 | int |
| 1234 | pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) | |
| 1235 | { | |
| 1236 | pps_params_t *app; | |
| 1237 | struct pps_fetch_args *fapi; | |
| 1238 | #ifdef PPS_SYNC | |
| 1239 | struct pps_kcbind_args *kapi; | |
| 1240 | #endif | |
| 1241 | ||
| 1242 | switch (cmd) { | |
| 1243 | case PPS_IOC_CREATE: | |
| 1244 | return (0); | |
| 1245 | case PPS_IOC_DESTROY: | |
| 1246 | return (0); | |
| 1247 | case PPS_IOC_SETPARAMS: | |
| 1248 | app = (pps_params_t *)data; | |
| 1249 | if (app->mode & ~pps->ppscap) | |
| 1250 | return (EINVAL); | |
| 1251 | pps->ppsparam = *app; | |
| 1252 | return (0); | |
| 1253 | case PPS_IOC_GETPARAMS: | |
| 1254 | app = (pps_params_t *)data; | |
| 1255 | *app = pps->ppsparam; | |
| 1256 | app->api_version = PPS_API_VERS_1; | |
| 1257 | return (0); | |
| 1258 | case PPS_IOC_GETCAP: | |
| 1259 | *(int*)data = pps->ppscap; | |
| 1260 | return (0); | |
| 1261 | case PPS_IOC_FETCH: | |
| 1262 | fapi = (struct pps_fetch_args *)data; | |
| 1263 | if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) | |
| 1264 | return (EINVAL); | |
| 1265 | if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) | |
| 1266 | return (EOPNOTSUPP); | |
| 1267 | pps->ppsinfo.current_mode = pps->ppsparam.mode; | |
| 1268 | fapi->pps_info_buf = pps->ppsinfo; | |
| 1269 | return (0); | |
| 1270 | case PPS_IOC_KCBIND: | |
| 1271 | #ifdef PPS_SYNC | |
| 1272 | kapi = (struct pps_kcbind_args *)data; | |
| 1273 | /* XXX Only root should be able to do this */ | |
| 1274 | if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC) | |
| 1275 | return (EINVAL); | |
| 1276 | if (kapi->kernel_consumer != PPS_KC_HARDPPS) | |
| 1277 | return (EINVAL); | |
| 1278 | if (kapi->edge & ~pps->ppscap) | |
| 1279 | return (EINVAL); | |
| 1280 | pps->kcmode = kapi->edge; | |
| 1281 | return (0); | |
| 1282 | #else | |
| 1283 | return (EOPNOTSUPP); | |
| 1284 | #endif | |
| 1285 | default: | |
| 1286 | return (ENOTTY); | |
| 1287 | } | |
| 1288 | } | |
| 1289 | ||
| 1290 | void | |
| 1291 | pps_init(struct pps_state *pps) | |
| 1292 | { | |
| 1293 | pps->ppscap |= PPS_TSFMT_TSPEC; | |
| 1294 | if (pps->ppscap & PPS_CAPTUREASSERT) | |
| 1295 | pps->ppscap |= PPS_OFFSETASSERT; | |
| 1296 | if (pps->ppscap & PPS_CAPTURECLEAR) | |
| 1297 | pps->ppscap |= PPS_OFFSETCLEAR; | |
| 1298 | } | |
| 1299 | ||
| 1300 | void | |
| 88c4d2f6 | 1301 | pps_event(struct pps_state *pps, sysclock_t count, int event) |
| 984263bc | 1302 | { |
| 88c4d2f6 MD |
1303 | struct globaldata *gd; |
| 1304 | struct timespec *tsp; | |
| 1305 | struct timespec *osp; | |
| 5eb5a6bc | 1306 | struct timespec *bt; |
| 88c4d2f6 MD |
1307 | struct timespec ts; |
| 1308 | sysclock_t *pcount; | |
| 1309 | #ifdef PPS_SYNC | |
| 1310 | sysclock_t tcount; | |
| 1311 | #endif | |
| 1312 | sysclock_t delta; | |
| 1313 | pps_seq_t *pseq; | |
| 1314 | int foff; | |
| 1315 | int fhard; | |
| 1316 | ||
| 1317 | gd = mycpu; | |
| 984263bc MD |
1318 | |
| 1319 | /* Things would be easier with arrays... */ | |
| 1320 | if (event == PPS_CAPTUREASSERT) { | |
| 1321 | tsp = &pps->ppsinfo.assert_timestamp; | |
| 1322 | osp = &pps->ppsparam.assert_offset; | |
| 1323 | foff = pps->ppsparam.mode & PPS_OFFSETASSERT; | |
| 1324 | fhard = pps->kcmode & PPS_CAPTUREASSERT; | |
| 1325 | pcount = &pps->ppscount[0]; | |
| 1326 | pseq = &pps->ppsinfo.assert_sequence; | |
| 1327 | } else { | |
| 1328 | tsp = &pps->ppsinfo.clear_timestamp; | |
| 1329 | osp = &pps->ppsparam.clear_offset; | |
| 1330 | foff = pps->ppsparam.mode & PPS_OFFSETCLEAR; | |
| 1331 | fhard = pps->kcmode & PPS_CAPTURECLEAR; | |
| 1332 | pcount = &pps->ppscount[1]; | |
| 1333 | pseq = &pps->ppsinfo.clear_sequence; | |
| 1334 | } | |
| 1335 | ||
| 984263bc MD |
1336 | /* Nothing really happened */ |
| 1337 | if (*pcount == count) | |
| 1338 | return; | |
| 1339 | ||
| 1340 | *pcount = count; | |
| 1341 | ||
| 88c4d2f6 MD |
1342 | do { |
| 1343 | ts.tv_sec = gd->gd_time_seconds; | |
| 1344 | delta = count - gd->gd_cpuclock_base; | |
| 1345 | } while (ts.tv_sec != gd->gd_time_seconds); | |
| fad57d0e | 1346 | |
| 044ee7c4 MD |
1347 | if (delta >= sys_cputimer->freq) { |
| 1348 | ts.tv_sec += delta / sys_cputimer->freq; | |
| 1349 | delta %= sys_cputimer->freq; | |
| 88c4d2f6 | 1350 | } |
| 044ee7c4 | 1351 | ts.tv_nsec = (sys_cputimer->freq64_nsec * delta) >> 32; |
| 5eb5a6bc MD |
1352 | bt = &basetime[basetime_index]; |
| 1353 | ts.tv_sec += bt->tv_sec; | |
| 1354 | ts.tv_nsec += bt->tv_nsec; | |
| 88c4d2f6 MD |
1355 | while (ts.tv_nsec >= 1000000000) { |
| 1356 | ts.tv_nsec -= 1000000000; | |
| 1357 | ++ts.tv_sec; | |
| 984263bc | 1358 | } |
| 984263bc MD |
1359 | |
| 1360 | (*pseq)++; | |
| 1361 | *tsp = ts; | |
| 1362 | ||
| 1363 | if (foff) { | |
| 1364 | timespecadd(tsp, osp); | |
| 1365 | if (tsp->tv_nsec < 0) { | |
| 1366 | tsp->tv_nsec += 1000000000; | |
| 1367 | tsp->tv_sec -= 1; | |
| 1368 | } | |
| 1369 | } | |
| 1370 | #ifdef PPS_SYNC | |
| 1371 | if (fhard) { | |
| 1372 | /* magic, at its best... */ | |
| 1373 | tcount = count - pps->ppscount[2]; | |
| 1374 | pps->ppscount[2] = count; | |
| 044ee7c4 MD |
1375 | if (tcount >= sys_cputimer->freq) { |
| 1376 | delta = (1000000000 * (tcount / sys_cputimer->freq) + | |
| 1377 | sys_cputimer->freq64_nsec * | |
| 1378 | (tcount % sys_cputimer->freq)) >> 32; | |
| fad57d0e | 1379 | } else { |
| 044ee7c4 | 1380 | delta = (sys_cputimer->freq64_nsec * tcount) >> 32; |
| fad57d0e | 1381 | } |
| 984263bc MD |
1382 | hardpps(tsp, delta); |
| 1383 | } | |
| 1384 | #endif | |
| 1385 | } | |
| 88c4d2f6 | 1386 | |
| d2412a2e MD |
1387 | /* |
| 1388 | * Return the tsc target value for a delay of (ns). | |
| 1389 | * | |
| 1390 | * Returns -1 if the TSC is not supported. | |
| 1391 | */ | |
| 1392 | int64_t | |
| 1393 | tsc_get_target(int ns) | |
| 1394 | { | |
| 1395 | #if defined(_RDTSC_SUPPORTED_) | |
| 1396 | if (cpu_feature & CPUID_TSC) { | |
| 1397 | return (rdtsc() + tsc_frequency * ns / (int64_t)1000000000); | |
| 1398 | } | |
| 1399 | #endif | |
| 1400 | return(-1); | |
| 1401 | } | |
| 1402 | ||
| 1403 | /* | |
| 1404 | * Compare the tsc against the passed target | |
| 1405 | * | |
| 1406 | * Returns +1 if the target has been reached | |
| 1407 | * Returns 0 if the target has not yet been reached | |
| 1408 | * Returns -1 if the TSC is not supported. | |
| 1409 | * | |
| 1410 | * Typical use: while (tsc_test_target(target) == 0) { ...poll... } | |
| 1411 | */ | |
| 1412 | int | |
| 1413 | tsc_test_target(int64_t target) | |
| 1414 | { | |
| 1415 | #if defined(_RDTSC_SUPPORTED_) | |
| 1416 | if (cpu_feature & CPUID_TSC) { | |
| 1417 | if ((int64_t)(target - rdtsc()) <= 0) | |
| 1418 | return(1); | |
| 1419 | return(0); | |
| 1420 | } | |
| d2412a2e | 1421 | #endif |
| 2e537993 | 1422 | return(-1); |
| d2412a2e | 1423 | } |
| b12defdc MD |
1424 | |
| 1425 | /* | |
| 1426 | * Delay the specified number of nanoseconds using the tsc. This function | |
| 1427 | * returns immediately if the TSC is not supported. At least one cpu_pause() | |
| 1428 | * will be issued. | |
| 1429 | */ | |
| 1430 | void | |
| 1431 | tsc_delay(int ns) | |
| 1432 | { | |
| 1433 | int64_t clk; | |
| 1434 | ||
| 1435 | clk = tsc_get_target(ns); | |
| 1436 | cpu_pause(); | |
| 1437 | while (tsc_test_target(clk) == 0) | |
| 1438 | cpu_pause(); | |
| 1439 | } |