diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index ea21ffdd37..e8ae6fac4f 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -107,15 +107,24 @@ TEXT runtime·madvise(SB), NOSPLIT, $0 RET // OS X comm page time offsets -// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h +// https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h + +#define commpage_version 0x1e + #define v12_nt_tsc_base 0x50 #define v12_nt_scale 0x58 #define v12_nt_shift 0x5c #define v12_nt_ns_base 0x60 #define v12_nt_generation 0x68 -#define v12_gtod_generation 0x6c -#define v12_gtod_ns_base 0x70 -#define v12_gtod_sec_base 0x78 +#define v12_gtod_generation 0x6c // obsolete since High Sierra (v13) +#define v12_gtod_ns_base 0x70 // obsolete since High Sierra (v13) +#define v12_gtod_sec_base 0x78 // obsolete since High Sierra (v13) + +#define v13_gtod_ns_base 0xd0 +#define v13_gtod_sec_ofs 0xd8 +#define v13_gtod_frac_ofs 0xe0 +#define v13_gtod_scale 0xe8 +#define v13_gtod_tkspersec 0xf0 TEXT runtime·nanotime(SB),NOSPLIT,$0-8 MOVQ $0x7fffffe00000, BP /* comm page base */ @@ -151,6 +160,75 @@ TEXT time·now(SB), NOSPLIT, $32-24 // are used in the systime fallback, as the timeval address // filled in by the system call. MOVQ $0x7fffffe00000, BP /* comm page base */ + CMPW commpage_version(BP), $13 + JB v12 /* sierra and older */ + + // This is the new code, for macOS High Sierra (v13) and newer. +v13: + // Loop trying to take a consistent snapshot + // of the time parameters. +timeloop13: + MOVQ v13_gtod_ns_base(BP), R12 + + MOVL v12_nt_generation(BP), CX + TESTL CX, CX + JZ timeloop13 + RDTSC + MOVQ v12_nt_tsc_base(BP), SI + MOVL v12_nt_scale(BP), DI + MOVQ v12_nt_ns_base(BP), BX + CMPL v12_nt_generation(BP), CX + JNE timeloop13 + + MOVQ v13_gtod_sec_ofs(BP), R8 + MOVQ v13_gtod_frac_ofs(BP), R9 + MOVQ v13_gtod_scale(BP), R10 + MOVQ v13_gtod_tkspersec(BP), R11 + CMPQ v13_gtod_ns_base(BP), R12 + JNE timeloop13 + + // Compute monotonic time + // mono = ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base + // The multiply and shift extracts the top 64 bits of the 96-bit product. + SHLQ $32, DX + ADDQ DX, AX + SUBQ SI, AX + MULQ DI + SHRQ $32, AX:DX + ADDQ BX, AX + + // Subtract startNano base to return the monotonic runtime timer + // which is an offset from process boot. + MOVQ AX, BX + MOVQ runtime·startNano(SB), CX + SUBQ CX, BX + MOVQ BX, monotonic+16(FP) + + // Now compute the 128-bit wall time: + // wall = ((mono - gtod_ns_base) * gtod_scale) + gtod_offs + // The parameters are updated every second, so if we found them + // outdated (that is, more than one second is passed from the ns base), + // fallback to the syscall. + TESTQ R12, R12 + JZ systime + SUBQ R12, AX + CMPQ R11, AX + JB systime + MULQ R10 + ADDQ R9, AX + ADCQ R8, DX + + // Convert the 128-bit wall time into (sec,nsec). + // High part (seconds) is already good to go, while low part + // (fraction of seconds) must be converted to nanoseconds. + MOVQ DX, sec+0(FP) + MOVQ $1000000000, CX + MULQ CX + MOVQ DX, nsec+8(FP) + RET + + // This is the legacy code needed for macOS Sierra (v12) and older. +v12: // Loop trying to take a consistent snapshot // of the time parameters. timeloop: