go: runtime: time goes backwards on windows-arm64 (frequent TestGcLastTime failures)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 33 (25 by maintainers)

Commits related to this issue

Most upvoted comments

For the modulo?

image

In runtime·nanotime1, the high-low-high algorithm is used to read the current 64-bit interrupt time as three 32-bit values. This code was probably copied from the AMD64 version. However, ARM64 has a looser memory model than x86/AMD64, so you need some extra memory barriers to make the algorithm work. These are missing (as @aclements points out).

The data points above are consistent with a reordering of the loads, such that the low 32 bits is not correctly matched to the high 32 bits. This can cause the low 32 bits to move backward between measurements, or more generally be wrong when the high bits are changing. The one confusing entry was where it appeared that high value was moving backward too, but that’s because aclements’s values were multiplied by 100 after they were read.

The fix is not to add memory barriers but to do a single 64-bit read of the time in one instruction. That’s what we do in Windows (and I recommend changing the AMD64 code to match, even though there’s no race condition due to the stricter memory model).

Looks like on the remaining two platforms, the constant is fine and doesn’t match the comment. But on ARM64 the constant and comment are both wrong.

Sending a patch.

Haha! You’re right. The comment has the right constant but the code has the wrong one.

Wait, they both look wrong to me…

I believe that this did not actually fix the problem. On arm64 time still moves backwards. Looking at the assembler, it appears to me that it’s rather a typo - it calculates (x / 1000000000, x % 100000000) instead of (x / 1000000000, x % 1000000000) (one zero to few in the x % expression). That I think fits perfectly with the symptoms as well.

Or am I reading it completely wrong?