Last active
January 17, 2017 07:46
-
-
Save namsral/376d0f063f631593a52e3f5b439e289c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source from the xnu kernel used in macOS | |
// source https://opensource.apple.com/source/xnu/xnu-3248.60.10/libsyscall/wrappers/mach_absolute_time.s | |
.globl _mach_absolute_time | |
_mach_absolute_time: | |
pushq %rbp // set up a frame for backtraces | |
movq %rsp,%rbp | |
movq $(_COMM_PAGE_TIME_DATA_START),%rsi | |
1: | |
movl _NT_GENERATION(%rsi),%r8d // get generation | |
testl %r8d,%r8d // if 0, data is being changed... | |
jz 1b // ...so loop until stable | |
lfence | |
rdtsc // edx:eax := tsc | |
lfence | |
shlq $32,%rdx // rax := ((edx << 32) | eax), ie 64-bit tsc | |
orq %rdx,%rax | |
/* | |
* Prior to supporting "slow" processors, xnu always set _NT_SHIFT to 32. | |
* Now it defaults to 0, unless the processor is slow. In order to maintain | |
* compatibility with both old and new versions of xnu, we mask the shift | |
* down to 0x1F, which maps the old default (32) into the new default (0). | |
*/ | |
movl _NT_SHIFT(%rsi),%ecx | |
andl $0x1F,%ecx // *** remove this line once 10.9 is GM *** | |
subq _NT_TSC_BASE(%rsi), %rax // rax := (tsc - base_tsc) | |
shlq %cl,%rax // rax := (tsc - base_tsc) << NT_SHIFT | |
movl _NT_SCALE(%rsi),%ecx | |
mulq %rcx // rdx:rax := ((tsc - base_tsc)<<shift) * scale | |
shrdq $32,%rdx,%rax // divide by 2**32 | |
addq _NT_NS_BASE(%rsi),%rax // (((tsc - base_tsc) * scale) >> 32) + ns_base | |
cmpl _NT_GENERATION(%rsi),%r8d // did the data change during computation? | |
jne 1b | |
popq %rbp | |
ret |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <mach/mach_time.h> | |
int main() | |
{ | |
uint64_t t = mach_absolute_time(); | |
printf("%lld\n", (long long) t); | |
return (0); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TEXT ·mach_absolute_tim(SB), NOSPLIT, $32 | |
MOVQ $0x7fffffe00000, SI // comm page base | |
timeloop: | |
MOVL nt_generation(SI), R8 | |
TESTL R8, R8 | |
JZ timeloop | |
RDTSC | |
SHLQ $32, DX | |
ORQ DX, AX | |
MOVL nt_shift(SI), CX | |
SUBQ nt_tsc_base(SI), AX | |
SHLQ CX, AX | |
MOVL nt_scale(SI), CX | |
MULQ CX | |
SHRQ $32, AX:DX | |
ADDQ nt_ns_base(SI), AX | |
CMPL nt_generation(SI), R8 | |
JNE timeloop | |
MOVQ AX, ret+0(FP) | |
RET |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Implementation of mach_absolute_time in Go AST | |
// based on https://golang.org/src/runtime/sys_darwin_amd64.s | |
#include "textflag.h" | |
// OS X comm page time offsets | |
// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h | |
#define nt_tsc_base 0x50 | |
#define nt_scale 0x58 | |
#define nt_shift 0x5c | |
#define nt_ns_base 0x60 | |
#define nt_generation 0x68 | |
TEXT ·mach_absolute_time(SB),NOSPLIT,$0-8 | |
MOVQ $0x7fffffe00000, BP /* comm page base */ | |
timeloop: | |
MOVQ nt_generation(BP), R8 | |
TESTL R8, R8 | |
JZ timeloop | |
RDTSC | |
SHLQ $32, DX | |
ORQ DX, AX | |
MOVL nt_shift(BP), R9 | |
ANDL $0x1F, R9 | |
SUBQ nt_tsc_base(BP), AX | |
SHLQ CX, AX | |
MOVL nt_scale(BP), R9 | |
MULQ R10 | |
SHRQ $32, AX:DX | |
ADDQ nt_ns_base(BP), AX | |
CMPL nt_generation(BP), R8 | |
JNE timeloop | |
RET |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment