]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ | |
23 | /* | |
24 | * Copyright (c) 1982, 1986, 1989, 1993 | |
25 | * The Regents of the University of California. All rights reserved. | |
26 | * | |
27 | * Redistribution and use in source and binary forms, with or without | |
28 | * modification, are permitted provided that the following conditions | |
29 | * are met: | |
30 | * 1. Redistributions of source code must retain the above copyright | |
31 | * notice, this list of conditions and the following disclaimer. | |
32 | * 2. Redistributions in binary form must reproduce the above copyright | |
33 | * notice, this list of conditions and the following disclaimer in the | |
34 | * documentation and/or other materials provided with the distribution. | |
35 | * 3. All advertising materials mentioning features or use of this software | |
36 | * must display the following acknowledgement: | |
37 | * This product includes software developed by the University of | |
38 | * California, Berkeley and its contributors. | |
39 | * 4. Neither the name of the University nor the names of its contributors | |
40 | * may be used to endorse or promote products derived from this software | |
41 | * without specific prior written permission. | |
42 | * | |
43 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
53 | * SUCH DAMAGE. | |
54 | * | |
55 | * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 | |
56 | */ | |
57 | ||
58 | #include <sys/param.h> | |
59 | #include <sys/resourcevar.h> | |
60 | #include <sys/kernel.h> | |
61 | #include <sys/systm.h> | |
62 | #include <sys/proc.h> | |
63 | #include <sys/vnode.h> | |
64 | ||
65 | #include <sys/mount.h> | |
66 | ||
1c79356b A |
67 | #include <kern/clock.h> |
68 | ||
69 | #define HZ 100 /* XXX */ | |
70 | ||
9bccf70c A |
71 | volatile struct timeval time; |
72 | /* simple lock used to access timezone, tz structure */ | |
73 | decl_simple_lock_data(, tz_slock); | |
1c79356b A |
74 | /* |
75 | * Time of day and interval timer support. | |
76 | * | |
77 | * These routines provide the kernel entry points to get and set | |
78 | * the time-of-day and per-process interval timers. Subroutines | |
79 | * here provide support for adding and subtracting timeval structures | |
80 | * and decrementing interval timers, optionally reloading the interval | |
81 | * timers when they expire. | |
82 | */ | |
83 | struct gettimeofday_args{ | |
84 | struct timeval *tp; | |
85 | struct timezone *tzp; | |
86 | }; | |
87 | /* ARGSUSED */ | |
88 | int | |
89 | gettimeofday(p, uap, retval) | |
90 | struct proc *p; | |
91 | register struct gettimeofday_args *uap; | |
92 | register_t *retval; | |
93 | { | |
94 | struct timeval atv; | |
95 | int error = 0; | |
9bccf70c A |
96 | extern simple_lock_data_t tz_slock; |
97 | struct timezone ltz; /* local copy */ | |
98 | ||
99 | /* NOTE THIS implementation is for non ppc architectures only */ | |
1c79356b A |
100 | |
101 | if (uap->tp) { | |
102 | microtime(&atv); | |
103 | if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp, | |
104 | sizeof (atv))) | |
105 | return(error); | |
106 | } | |
107 | ||
9bccf70c A |
108 | if (uap->tzp) { |
109 | usimple_lock(&tz_slock); | |
110 | ltz = tz; | |
111 | usimple_unlock(&tz_slock); | |
112 | error = copyout((caddr_t)<z, (caddr_t)uap->tzp, | |
1c79356b | 113 | sizeof (tz)); |
9bccf70c | 114 | } |
1c79356b A |
115 | |
116 | return(error); | |
117 | } | |
118 | ||
119 | struct settimeofday_args { | |
120 | struct timeval *tv; | |
121 | struct timezone *tzp; | |
122 | }; | |
123 | /* ARGSUSED */ | |
124 | int | |
125 | settimeofday(p, uap, retval) | |
126 | struct proc *p; | |
127 | struct settimeofday_args *uap; | |
128 | register_t *retval; | |
129 | { | |
130 | struct timeval atv; | |
131 | struct timezone atz; | |
132 | int error, s; | |
9bccf70c | 133 | extern simple_lock_data_t tz_slock; |
1c79356b A |
134 | |
135 | if (error = suser(p->p_ucred, &p->p_acflag)) | |
136 | return (error); | |
137 | /* Verify all parameters before changing time. */ | |
138 | if (uap->tv && (error = copyin((caddr_t)uap->tv, | |
139 | (caddr_t)&atv, sizeof(atv)))) | |
140 | return (error); | |
141 | if (uap->tzp && (error = copyin((caddr_t)uap->tzp, | |
142 | (caddr_t)&atz, sizeof(atz)))) | |
143 | return (error); | |
144 | if (uap->tv) | |
145 | setthetime(&atv); | |
9bccf70c A |
146 | if (uap->tzp) { |
147 | usimple_lock(&tz_slock); | |
1c79356b | 148 | tz = atz; |
9bccf70c A |
149 | usimple_unlock(&tz_slock); |
150 | } | |
1c79356b A |
151 | return (0); |
152 | } | |
153 | ||
154 | setthetime(tv) | |
155 | struct timeval *tv; | |
156 | { | |
9bccf70c | 157 | long delta = tv->tv_sec - time.tv_sec; |
1c79356b | 158 | mach_timespec_t now; |
1c79356b A |
159 | |
160 | now.tv_sec = tv->tv_sec; | |
161 | now.tv_nsec = tv->tv_usec * NSEC_PER_USEC; | |
162 | ||
163 | clock_set_calendar_value(now); | |
1c79356b A |
164 | boottime.tv_sec += delta; |
165 | #if NFSCLIENT || NFSSERVER | |
166 | lease_updatetime(delta); | |
167 | #endif | |
1c79356b A |
168 | } |
169 | ||
9bccf70c A |
170 | #define tickadj (40 * NSEC_PER_USEC) /* "standard" skew, ns / 10 ms */ |
171 | #define bigadj (1 * NSEC_PER_SEC) /* use 10x skew above bigadj ns */ | |
1c79356b A |
172 | |
173 | struct adjtime_args { | |
174 | struct timeval *delta; | |
175 | struct timeval *olddelta; | |
176 | }; | |
177 | /* ARGSUSED */ | |
178 | int | |
179 | adjtime(p, uap, retval) | |
180 | struct proc *p; | |
181 | register struct adjtime_args *uap; | |
182 | register_t *retval; | |
183 | { | |
9bccf70c A |
184 | struct timeval atv; |
185 | int64_t total; | |
186 | uint32_t delta; | |
187 | int error; | |
1c79356b A |
188 | |
189 | if (error = suser(p->p_ucred, &p->p_acflag)) | |
190 | return (error); | |
9bccf70c A |
191 | if (error = copyin((caddr_t)uap->delta, |
192 | (caddr_t)&atv, sizeof (struct timeval))) | |
193 | return (error); | |
1c79356b | 194 | |
9bccf70c A |
195 | /* |
196 | * Compute the total correction and the rate at which to apply it. | |
197 | */ | |
198 | total = (int64_t)atv.tv_sec * NSEC_PER_SEC + atv.tv_usec * NSEC_PER_USEC; | |
199 | if (total > bigadj || total < -bigadj) | |
200 | delta = 10 * tickadj; | |
201 | else | |
202 | delta = tickadj; | |
203 | ||
204 | total = clock_set_calendar_adjtime(total, delta); | |
1c79356b | 205 | |
1c79356b | 206 | if (uap->olddelta) { |
9bccf70c A |
207 | atv.tv_sec = total / NSEC_PER_SEC; |
208 | atv.tv_usec = (total / NSEC_PER_USEC) % USEC_PER_SEC; | |
209 | (void) copyout((caddr_t)&atv, | |
210 | (caddr_t)uap->olddelta, sizeof (struct timeval)); | |
1c79356b | 211 | } |
1c79356b | 212 | |
9bccf70c | 213 | return (0); |
1c79356b A |
214 | } |
215 | ||
1c79356b A |
216 | /* |
217 | * Initialze the time of day register. | |
218 | * Trust the RTC except for the case where it is set before | |
219 | * the UNIX epoch. In that case use the the UNIX epoch. | |
220 | * The argument passed in is ignored. | |
221 | */ | |
222 | void | |
223 | inittodr(base) | |
224 | time_t base; | |
225 | { | |
226 | /* | |
0b4e3aa0 A |
227 | * Assertion: |
228 | * The calendar has already been | |
229 | * set up from the battery clock. | |
230 | * | |
1c79356b A |
231 | * The value returned by microtime() |
232 | * is gotten from the calendar. | |
233 | */ | |
234 | microtime(&time); | |
235 | ||
236 | /* | |
237 | * This variable still exists to keep | |
238 | * 'w' happy. It should only be considered | |
239 | * an approximation. | |
240 | */ | |
241 | boottime.tv_sec = time.tv_sec; | |
242 | boottime.tv_usec = 0; | |
243 | ||
244 | /* | |
245 | * If the RTC does not have acceptable value, i.e. time before | |
246 | * the UNIX epoch, set it to the UNIX epoch | |
247 | */ | |
248 | if (time.tv_sec < 0) { | |
249 | printf ("WARNING: preposterous time in Real Time Clock"); | |
250 | time.tv_sec = 0; /* the UNIX epoch */ | |
251 | time.tv_usec = 0; | |
252 | setthetime(&time); | |
253 | boottime = time; | |
254 | printf(" -- CHECK AND RESET THE DATE!\n"); | |
255 | } | |
256 | ||
257 | return; | |
258 | } | |
259 | ||
9bccf70c A |
260 | void timevaladd( |
261 | struct timeval *t1, | |
262 | struct timeval *t2); | |
263 | void timevalsub( | |
264 | struct timeval *t1, | |
265 | struct timeval *t2); | |
266 | void timevalfix( | |
267 | struct timeval *t1); | |
268 | ||
269 | uint64_t | |
270 | tvtoabstime( | |
271 | struct timeval *tvp); | |
272 | ||
1c79356b A |
273 | /* |
274 | * Get value of an interval timer. The process virtual and | |
9bccf70c | 275 | * profiling virtual time timers are kept internally in the |
1c79356b A |
276 | * way they are specified externally: in time until they expire. |
277 | * | |
9bccf70c A |
278 | * The real time interval timer expiration time (p_rtime) |
279 | * is kept as an absolute time rather than as a delta, so that | |
280 | * it is easy to keep periodic real-time signals from drifting. | |
1c79356b A |
281 | * |
282 | * Virtual time timers are processed in the hardclock() routine of | |
9bccf70c A |
283 | * kern_clock.c. The real time timer is processed by a callout |
284 | * routine. Since a callout may be delayed in real time due to | |
285 | * other processing in the system, it is possible for the real | |
286 | * time callout routine (realitexpire, given below), to be delayed | |
287 | * in real time past when it is supposed to occur. It does not | |
288 | * suffice, therefore, to reload the real time .it_value from the | |
289 | * real time .it_interval. Rather, we compute the next time in | |
290 | * absolute time when the timer should go off. | |
1c79356b A |
291 | */ |
292 | ||
293 | struct getitimer_args { | |
294 | u_int which; | |
295 | struct itimerval *itv; | |
296 | }; | |
297 | /* ARGSUSED */ | |
298 | int | |
299 | getitimer(p, uap, retval) | |
300 | struct proc *p; | |
301 | register struct getitimer_args *uap; | |
302 | register_t *retval; | |
303 | { | |
304 | struct itimerval aitv; | |
1c79356b A |
305 | |
306 | if (uap->which > ITIMER_PROF) | |
307 | return(EINVAL); | |
1c79356b A |
308 | if (uap->which == ITIMER_REAL) { |
309 | /* | |
9bccf70c A |
310 | * If time for real time timer has passed return 0, |
311 | * else return difference between current time and | |
312 | * time for the timer to go off. | |
1c79356b A |
313 | */ |
314 | aitv = p->p_realtimer; | |
9bccf70c A |
315 | if (timerisset(&p->p_rtime)) { |
316 | struct timeval now; | |
317 | ||
318 | microuptime(&now); | |
319 | if (timercmp(&p->p_rtime, &now, <)) | |
1c79356b | 320 | timerclear(&aitv.it_value); |
9bccf70c A |
321 | else { |
322 | aitv.it_value = p->p_rtime; | |
323 | timevalsub(&aitv.it_value, &now); | |
324 | } | |
325 | } | |
326 | else | |
327 | timerclear(&aitv.it_value); | |
328 | } | |
329 | else | |
330 | aitv = p->p_stats->p_timer[uap->which]; | |
331 | ||
332 | return (copyout((caddr_t)&aitv, | |
333 | (caddr_t)uap->itv, sizeof (struct itimerval))); | |
1c79356b A |
334 | } |
335 | ||
336 | struct setitimer_args { | |
337 | u_int which; | |
338 | struct itimerval *itv; | |
339 | struct itimerval *oitv; | |
340 | }; | |
341 | /* ARGSUSED */ | |
342 | int | |
343 | setitimer(p, uap, retval) | |
344 | struct proc *p; | |
345 | register struct setitimer_args *uap; | |
346 | register_t *retval; | |
347 | { | |
348 | struct itimerval aitv; | |
349 | register struct itimerval *itvp; | |
9bccf70c | 350 | int error; |
1c79356b A |
351 | |
352 | if (uap->which > ITIMER_PROF) | |
9bccf70c A |
353 | return (EINVAL); |
354 | if ((itvp = uap->itv) && | |
355 | (error = copyin((caddr_t)itvp, | |
356 | (caddr_t)&aitv, sizeof (struct itimerval)))) | |
1c79356b | 357 | return (error); |
9bccf70c | 358 | if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval))) |
1c79356b A |
359 | return (error); |
360 | if (itvp == 0) | |
361 | return (0); | |
362 | if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) | |
363 | return (EINVAL); | |
1c79356b | 364 | if (uap->which == ITIMER_REAL) { |
9bccf70c | 365 | thread_call_func_cancel(realitexpire, (void *)p->p_pid, FALSE); |
1c79356b | 366 | if (timerisset(&aitv.it_value)) { |
9bccf70c A |
367 | microuptime(&p->p_rtime); |
368 | timevaladd(&p->p_rtime, &aitv.it_value); | |
369 | thread_call_func_delayed( | |
370 | realitexpire, (void *)p->p_pid, | |
371 | tvtoabstime(&p->p_rtime)); | |
1c79356b | 372 | } |
9bccf70c A |
373 | else |
374 | timerclear(&p->p_rtime); | |
375 | ||
1c79356b | 376 | p->p_realtimer = aitv; |
9bccf70c A |
377 | } |
378 | else | |
1c79356b | 379 | p->p_stats->p_timer[uap->which] = aitv; |
9bccf70c A |
380 | |
381 | return (0); | |
1c79356b A |
382 | } |
383 | ||
384 | /* | |
385 | * Real interval timer expired: | |
386 | * send process whose timer expired an alarm signal. | |
387 | * If time is not set up to reload, then just return. | |
388 | * Else compute next time timer should go off which is > current time. | |
389 | * This is where delay in processing this timeout causes multiple | |
390 | * SIGALRM calls to be compressed into one. | |
391 | */ | |
392 | void | |
9bccf70c A |
393 | realitexpire( |
394 | void *pid) | |
1c79356b A |
395 | { |
396 | register struct proc *p; | |
9bccf70c A |
397 | struct timeval now; |
398 | boolean_t funnel_state = thread_funnel_set(kernel_flock, TRUE); | |
1c79356b | 399 | |
9bccf70c A |
400 | p = pfind((pid_t)pid); |
401 | if (p == NULL) { | |
402 | (void) thread_funnel_set(kernel_flock, FALSE); | |
1c79356b A |
403 | return; |
404 | } | |
9bccf70c A |
405 | |
406 | if (!timerisset(&p->p_realtimer.it_interval)) { | |
407 | timerclear(&p->p_rtime); | |
408 | psignal(p, SIGALRM); | |
409 | ||
410 | (void) thread_funnel_set(kernel_flock, FALSE); | |
1c79356b | 411 | return; |
1c79356b | 412 | } |
9bccf70c A |
413 | |
414 | microuptime(&now); | |
415 | timevaladd(&p->p_rtime, &p->p_realtimer.it_interval); | |
416 | if (timercmp(&p->p_rtime, &now, <=)) { | |
417 | if ((p->p_rtime.tv_sec + 2) >= now.tv_sec) { | |
418 | for (;;) { | |
419 | timevaladd(&p->p_rtime, &p->p_realtimer.it_interval); | |
420 | if (timercmp(&p->p_rtime, &now, >)) | |
421 | break; | |
422 | } | |
423 | } | |
424 | else { | |
425 | p->p_rtime = p->p_realtimer.it_interval; | |
426 | timevaladd(&p->p_rtime, &now); | |
1c79356b | 427 | } |
1c79356b | 428 | } |
9bccf70c A |
429 | |
430 | thread_call_func_delayed(realitexpire, pid, tvtoabstime(&p->p_rtime)); | |
431 | ||
432 | psignal(p, SIGALRM); | |
433 | ||
1c79356b A |
434 | (void) thread_funnel_set(kernel_flock, FALSE); |
435 | } | |
436 | ||
437 | /* | |
438 | * Check that a proposed value to load into the .it_value or | |
439 | * .it_interval part of an interval timer is acceptable, and | |
440 | * fix it to have at least minimal value (i.e. if it is less | |
441 | * than the resolution of the clock, round it up.) | |
442 | */ | |
443 | int | |
444 | itimerfix(tv) | |
445 | struct timeval *tv; | |
446 | { | |
447 | ||
448 | if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || | |
449 | tv->tv_usec < 0 || tv->tv_usec >= 1000000) | |
450 | return (EINVAL); | |
451 | if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) | |
452 | tv->tv_usec = tick; | |
453 | return (0); | |
454 | } | |
455 | ||
456 | /* | |
457 | * Decrement an interval timer by a specified number | |
458 | * of microseconds, which must be less than a second, | |
459 | * i.e. < 1000000. If the timer expires, then reload | |
460 | * it. In this case, carry over (usec - old value) to | |
461 | * reducint the value reloaded into the timer so that | |
462 | * the timer does not drift. This routine assumes | |
463 | * that it is called in a context where the timers | |
464 | * on which it is operating cannot change in value. | |
465 | */ | |
466 | int | |
467 | itimerdecr(itp, usec) | |
468 | register struct itimerval *itp; | |
469 | int usec; | |
470 | { | |
471 | ||
472 | if (itp->it_value.tv_usec < usec) { | |
473 | if (itp->it_value.tv_sec == 0) { | |
474 | /* expired, and already in next interval */ | |
475 | usec -= itp->it_value.tv_usec; | |
476 | goto expire; | |
477 | } | |
478 | itp->it_value.tv_usec += 1000000; | |
479 | itp->it_value.tv_sec--; | |
480 | } | |
481 | itp->it_value.tv_usec -= usec; | |
482 | usec = 0; | |
483 | if (timerisset(&itp->it_value)) | |
484 | return (1); | |
485 | /* expired, exactly at end of interval */ | |
486 | expire: | |
487 | if (timerisset(&itp->it_interval)) { | |
488 | itp->it_value = itp->it_interval; | |
489 | itp->it_value.tv_usec -= usec; | |
490 | if (itp->it_value.tv_usec < 0) { | |
491 | itp->it_value.tv_usec += 1000000; | |
492 | itp->it_value.tv_sec--; | |
493 | } | |
494 | } else | |
495 | itp->it_value.tv_usec = 0; /* sec is already 0 */ | |
496 | return (0); | |
497 | } | |
498 | ||
499 | /* | |
500 | * Add and subtract routines for timevals. | |
501 | * N.B.: subtract routine doesn't deal with | |
502 | * results which are before the beginning, | |
503 | * it just gets very confused in this case. | |
504 | * Caveat emptor. | |
505 | */ | |
506 | void | |
9bccf70c A |
507 | timevaladd( |
508 | struct timeval *t1, | |
509 | struct timeval *t2) | |
1c79356b A |
510 | { |
511 | ||
512 | t1->tv_sec += t2->tv_sec; | |
513 | t1->tv_usec += t2->tv_usec; | |
514 | timevalfix(t1); | |
515 | } | |
516 | void | |
9bccf70c A |
517 | timevalsub( |
518 | struct timeval *t1, | |
519 | struct timeval *t2) | |
1c79356b A |
520 | { |
521 | ||
522 | t1->tv_sec -= t2->tv_sec; | |
523 | t1->tv_usec -= t2->tv_usec; | |
524 | timevalfix(t1); | |
525 | } | |
526 | void | |
9bccf70c A |
527 | timevalfix( |
528 | struct timeval *t1) | |
1c79356b A |
529 | { |
530 | ||
531 | if (t1->tv_usec < 0) { | |
532 | t1->tv_sec--; | |
533 | t1->tv_usec += 1000000; | |
534 | } | |
535 | if (t1->tv_usec >= 1000000) { | |
536 | t1->tv_sec++; | |
537 | t1->tv_usec -= 1000000; | |
538 | } | |
539 | } | |
540 | ||
541 | /* | |
542 | * Return the best possible estimate of the time in the timeval | |
543 | * to which tvp points. | |
544 | */ | |
545 | void | |
9bccf70c A |
546 | microtime( |
547 | struct timeval *tvp) | |
1c79356b A |
548 | { |
549 | mach_timespec_t now = clock_get_calendar_value(); | |
550 | ||
551 | tvp->tv_sec = now.tv_sec; | |
552 | tvp->tv_usec = now.tv_nsec / NSEC_PER_USEC; | |
553 | } | |
9bccf70c A |
554 | |
555 | void | |
556 | microuptime( | |
557 | struct timeval *tvp) | |
558 | { | |
559 | mach_timespec_t now = clock_get_system_value(); | |
560 | ||
561 | tvp->tv_sec = now.tv_sec; | |
562 | tvp->tv_usec = now.tv_nsec / NSEC_PER_USEC; | |
563 | } | |
564 | ||
565 | /* | |
566 | * Ditto for timespec. | |
567 | */ | |
568 | void | |
569 | nanotime( | |
570 | struct timespec *tsp) | |
571 | { | |
572 | mach_timespec_t now = clock_get_calendar_value(); | |
573 | ||
574 | tsp->tv_sec = now.tv_sec; | |
575 | tsp->tv_nsec = now.tv_nsec; | |
576 | } | |
577 | ||
578 | void | |
579 | nanouptime( | |
580 | struct timespec *tsp) | |
581 | { | |
582 | mach_timespec_t now = clock_get_system_value(); | |
583 | ||
584 | tsp->tv_sec = now.tv_sec; | |
585 | tsp->tv_nsec = now.tv_nsec; | |
586 | } | |
587 | ||
588 | uint64_t | |
589 | tvtoabstime( | |
590 | struct timeval *tvp) | |
591 | { | |
592 | uint64_t result, usresult; | |
593 | ||
594 | clock_interval_to_absolutetime_interval( | |
595 | tvp->tv_sec, NSEC_PER_SEC, &result); | |
596 | clock_interval_to_absolutetime_interval( | |
597 | tvp->tv_usec, NSEC_PER_USEC, &usresult); | |
598 | ||
599 | return (result + usresult); | |
600 | } | |
601 | void | |
602 | time_zone_slock_init(void) | |
603 | { | |
604 | extern simple_lock_data_t tz_slock; | |
605 | ||
606 | simple_lock_init(&tz_slock); | |
607 | ||
608 | ||
609 | } |