Skip to content

Commit d8ff3d5

Browse files
raskyianlancetaylor
authored andcommitted
runtime: fix wall time computation in macOS High Sierra
Latest macOS High Sierra changed how the wall time information is exported into the commpage. Backward compatibility was partly preserved, that is previous Go versions are basically forced to go through a syscall which is much slower and is not able to get nanosecond precision. Implement the new commpage layout and wall time computation, using a version check to fallback to the previous code on older operating systems. Fixes #22037 Change-Id: I8c2176eaca83a5d7be23443946a6b4c653ec7f68 Reviewed-on: https://go-review.googlesource.com/67332 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent b78bce0 commit d8ff3d5

File tree

1 file changed

+82
-4
lines changed

1 file changed

+82
-4
lines changed

src/runtime/sys_darwin_amd64.s

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,24 @@ TEXT runtime·madvise(SB), NOSPLIT, $0
107107
RET
108108

109109
// OS X comm page time offsets
110-
// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
110+
// https://opensource.apple.com/source/xnu/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h
111+
112+
#define commpage_version 0x1e
113+
111114
#define v12_nt_tsc_base 0x50
112115
#define v12_nt_scale 0x58
113116
#define v12_nt_shift 0x5c
114117
#define v12_nt_ns_base 0x60
115118
#define v12_nt_generation 0x68
116-
#define v12_gtod_generation 0x6c
117-
#define v12_gtod_ns_base 0x70
118-
#define v12_gtod_sec_base 0x78
119+
#define v12_gtod_generation 0x6c // obsolete since High Sierra (v13)
120+
#define v12_gtod_ns_base 0x70 // obsolete since High Sierra (v13)
121+
#define v12_gtod_sec_base 0x78 // obsolete since High Sierra (v13)
122+
123+
#define v13_gtod_ns_base 0xd0
124+
#define v13_gtod_sec_ofs 0xd8
125+
#define v13_gtod_frac_ofs 0xe0
126+
#define v13_gtod_scale 0xe8
127+
#define v13_gtod_tkspersec 0xf0
119128

120129
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
121130
MOVQ $0x7fffffe00000, BP /* comm page base */
@@ -151,6 +160,75 @@ TEXT time·now(SB), NOSPLIT, $32-24
151160
// are used in the systime fallback, as the timeval address
152161
// filled in by the system call.
153162
MOVQ $0x7fffffe00000, BP /* comm page base */
163+
CMPW commpage_version(BP), $13
164+
JB v12 /* sierra and older */
165+
166+
// This is the new code, for macOS High Sierra (v13) and newer.
167+
v13:
168+
// Loop trying to take a consistent snapshot
169+
// of the time parameters.
170+
timeloop13:
171+
MOVQ v13_gtod_ns_base(BP), R12
172+
173+
MOVL v12_nt_generation(BP), CX
174+
TESTL CX, CX
175+
JZ timeloop13
176+
RDTSC
177+
MOVQ v12_nt_tsc_base(BP), SI
178+
MOVL v12_nt_scale(BP), DI
179+
MOVQ v12_nt_ns_base(BP), BX
180+
CMPL v12_nt_generation(BP), CX
181+
JNE timeloop13
182+
183+
MOVQ v13_gtod_sec_ofs(BP), R8
184+
MOVQ v13_gtod_frac_ofs(BP), R9
185+
MOVQ v13_gtod_scale(BP), R10
186+
MOVQ v13_gtod_tkspersec(BP), R11
187+
CMPQ v13_gtod_ns_base(BP), R12
188+
JNE timeloop13
189+
190+
// Compute monotonic time
191+
// mono = ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base
192+
// The multiply and shift extracts the top 64 bits of the 96-bit product.
193+
SHLQ $32, DX
194+
ADDQ DX, AX
195+
SUBQ SI, AX
196+
MULQ DI
197+
SHRQ $32, AX:DX
198+
ADDQ BX, AX
199+
200+
// Subtract startNano base to return the monotonic runtime timer
201+
// which is an offset from process boot.
202+
MOVQ AX, BX
203+
MOVQ runtime·startNano(SB), CX
204+
SUBQ CX, BX
205+
MOVQ BX, monotonic+16(FP)
206+
207+
// Now compute the 128-bit wall time:
208+
// wall = ((mono - gtod_ns_base) * gtod_scale) + gtod_offs
209+
// The parameters are updated every second, so if we found them
210+
// outdated (that is, more than one second is passed from the ns base),
211+
// fallback to the syscall.
212+
TESTQ R12, R12
213+
JZ systime
214+
SUBQ R12, AX
215+
CMPQ R11, AX
216+
JB systime
217+
MULQ R10
218+
ADDQ R9, AX
219+
ADCQ R8, DX
220+
221+
// Convert the 128-bit wall time into (sec,nsec).
222+
// High part (seconds) is already good to go, while low part
223+
// (fraction of seconds) must be converted to nanoseconds.
224+
MOVQ DX, sec+0(FP)
225+
MOVQ $1000000000, CX
226+
MULQ CX
227+
MOVQ DX, nsec+8(FP)
228+
RET
229+
230+
// This is the legacy code needed for macOS Sierra (v12) and older.
231+
v12:
154232
// Loop trying to take a consistent snapshot
155233
// of the time parameters.
156234
timeloop:

0 commit comments

Comments
 (0)