2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <mach/mach_time.h>
26 #include <machine/cpu_capabilities.h>
28 int __commpage_gettimeofday(struct timeval
*);
30 __attribute__((visibility("hidden")))
31 int __commpage_gettimeofday_internal(struct timeval
*tp
, uint64_t *tbr_out
);
33 #if defined(__x86_64__) || defined(__i386__)
35 // XXX: must be kept in sync with __commpage_gettimeofday.s
37 __commpage_gettimeofday_internal(struct timeval
*tp
, uint64_t *tbr_out
)
39 volatile uint32_t *gtod_generation_p
= _COMM_PAGE_GTOD_GENERATION
;
40 volatile uint64_t *gtod_sec_base_p
= _COMM_PAGE_GTOD_SEC_BASE
;
41 volatile uint64_t *gtod_ns_base_p
= _COMM_PAGE_GTOD_NS_BASE
;
43 uint64_t tbr
, gen
, tod_secs
, tod_nsecs
, elapsed
;
45 gen
= *gtod_generation_p
;
46 tbr
= mach_absolute_time();
47 tod_secs
= *gtod_sec_base_p
;
48 tod_nsecs
= *gtod_ns_base_p
;
49 uint64_t gen2
= *gtod_generation_p
;
50 if(__builtin_expect(gen
, gen2
) == gen2
)
53 if (gen
== 0) return KERN_FAILURE
;
54 elapsed
= tbr
- tod_nsecs
;
58 #if defined(__x86_64__)
59 secs
= elapsed
/NSEC_PER_SEC
;
60 nsec
= elapsed
% NSEC_PER_SEC
;
61 #elif defined(__i386__)
62 uint32_t secs1
, secs2
;
63 secs1
= elapsed
>> 32;
67 : "=a" (secs
), "=d" (nsec
)
68 : "0" (secs2
), "1" (secs1
), "rm" (NSEC_PER_SEC
)
70 #endif /* __i386 or __x86_64__ */
71 tp
->tv_sec
= tod_secs
+ secs
;
72 tp
->tv_usec
= nsec
/ NSEC_PER_USEC
;
74 if (tbr_out
) *tbr_out
= tbr
;