1
0
mirror of https://github.com/golang/go synced 2024-11-17 02:14:42 -07:00

runtime: remove slow time compatibility hacks for wine

A few years ago, Wine-specific detection was added as an ugly hack to
work around shortcomings in the emulation layer. Probably it's best to
not special case this emulator versus that emulator versus the real
deal, but there were two arguments presented in the hack's favor:

  1. Wine is useful and developers will appreciate being able to debug
     stuff with it.

  2. The existing KUSER_SHARED_DATA technique for gathering time is
     undocumented, and we shouldn't be relying on it anyway, since
     Microsoft might remove it without notice.

As it turns out, neither one of these are, at the time of writing, true.
(1) has been handled for some time by Wine with the introduction of the
commit entitled "ntdll: Create thread to update user_shared_data time
values when necessary". And (2) is in fact documented:
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/ns-ntddk-kuser_shared_data
https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-kuser
It's in use so widely by both third-party software (such as games, a
massive market segment) and by Microsoft binaries that removing it from
the operating system will basically never happen.

So with both issues taken care of, this commit simply gets rid of the
old hack.

Change-Id: I80093f50e0d10d53648128d0f9dd76b1b92a119e
Reviewed-on: https://go-review.googlesource.com/c/go/+/191759
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Jason A. Donenfeld 2019-08-24 17:13:33 +02:00
parent 8f79ca1d1a
commit b4ad49f9f7
4 changed files with 0 additions and 112 deletions

View File

@ -75,12 +75,10 @@ var (
_GetStdHandle,
_GetSystemDirectoryA,
_GetSystemInfo,
_GetSystemTimeAsFileTime,
_GetThreadContext,
_LoadLibraryW,
_LoadLibraryA,
_QueryPerformanceCounter,
_QueryPerformanceFrequency,
_ResumeThread,
_SetConsoleCtrlHandler,
_SetErrorMode,
@ -251,11 +249,6 @@ func loadOptionalSyscalls() {
if _WSAGetOverlappedResult == nil {
throw("WSAGetOverlappedResult not found")
}
if windowsFindfunc(n32, []byte("wine_get_version\000")) != nil {
// running on Wine
initWine(k32)
}
}
//go:nosplit
@ -379,77 +372,6 @@ func osinit() {
func nanotime() int64
// useQPCTime controls whether time.now and nanotime use QueryPerformanceCounter.
// This is only set to 1 when running under Wine.
var useQPCTime uint8
var qpcStartCounter int64
var qpcMultiplier int64
//go:nosplit
func nanotimeQPC() int64 {
var counter int64 = 0
stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&counter)))
// returns number of nanoseconds
return (counter - qpcStartCounter) * qpcMultiplier
}
//go:nosplit
func nowQPC() (sec int64, nsec int32, mono int64) {
var ft int64
stdcall1(_GetSystemTimeAsFileTime, uintptr(unsafe.Pointer(&ft)))
t := (ft - 116444736000000000) * 100
sec = t / 1000000000
nsec = int32(t - sec*1000000000)
mono = nanotimeQPC()
return
}
func initWine(k32 uintptr) {
_GetSystemTimeAsFileTime = windowsFindfunc(k32, []byte("GetSystemTimeAsFileTime\000"))
if _GetSystemTimeAsFileTime == nil {
throw("could not find GetSystemTimeAsFileTime() syscall")
}
_QueryPerformanceCounter = windowsFindfunc(k32, []byte("QueryPerformanceCounter\000"))
_QueryPerformanceFrequency = windowsFindfunc(k32, []byte("QueryPerformanceFrequency\000"))
if _QueryPerformanceCounter == nil || _QueryPerformanceFrequency == nil {
throw("could not find QPC syscalls")
}
// We can not simply fallback to GetSystemTimeAsFileTime() syscall, since its time is not monotonic,
// instead we use QueryPerformanceCounter family of syscalls to implement monotonic timer
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
var tmp int64
stdcall1(_QueryPerformanceFrequency, uintptr(unsafe.Pointer(&tmp)))
if tmp == 0 {
throw("QueryPerformanceFrequency syscall returned zero, running on unsupported hardware")
}
// This should not overflow, it is a number of ticks of the performance counter per second,
// its resolution is at most 10 per usecond (on Wine, even smaller on real hardware), so it will be at most 10 millions here,
// panic if overflows.
if tmp > (1<<31 - 1) {
throw("QueryPerformanceFrequency overflow 32 bit divider, check nosplit discussion to proceed")
}
qpcFrequency := int32(tmp)
stdcall1(_QueryPerformanceCounter, uintptr(unsafe.Pointer(&qpcStartCounter)))
// Since we are supposed to run this time calls only on Wine, it does not lose precision,
// since Wine's timer is kind of emulated at 10 Mhz, so it will be a nice round multiplier of 100
// but for general purpose system (like 3.3 Mhz timer on i7) it will not be very precise.
// We have to do it this way (or similar), since multiplying QPC counter by 100 millions overflows
// int64 and resulted time will always be invalid.
qpcMultiplier = int64(timediv(1000000000, qpcFrequency, nil))
useQPCTime = 1
}
//go:nosplit
func getRandomData(r []byte) {
n := 0

View File

@ -445,8 +445,6 @@ TEXT runtime·switchtothread(SB),NOSPLIT,$0
#define time_hi2 8
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
CMPB runtime·useQPCTime(SB), $0
JNE useQPC
loop:
MOVL (_INTERRUPT_TIME+time_hi1), AX
MOVL (_INTERRUPT_TIME+time_lo), CX
@ -463,13 +461,8 @@ loop:
MOVL AX, ret_lo+0(FP)
MOVL DX, ret_hi+4(FP)
RET
useQPC:
JMP runtime·nanotimeQPC(SB)
RET
TEXT time·now(SB),NOSPLIT,$0-20
CMPB runtime·useQPCTime(SB), $0
JNE useQPC
loop:
MOVL (_INTERRUPT_TIME+time_hi1), AX
MOVL (_INTERRUPT_TIME+time_lo), CX
@ -538,6 +531,3 @@ wall:
MOVL AX, sec+0(FP)
MOVL DX, sec+4(FP)
RET
useQPC:
JMP runtime·nowQPC(SB)
RET

View File

@ -474,8 +474,6 @@ TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
#define time_hi2 8
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
CMPB runtime·useQPCTime(SB), $0
JNE useQPC
MOVQ $_INTERRUPT_TIME, DI
loop:
MOVL time_hi1(DI), AX
@ -488,13 +486,8 @@ loop:
IMULQ $100, CX
MOVQ CX, ret+0(FP)
RET
useQPC:
JMP runtime·nanotimeQPC(SB)
RET
TEXT time·now(SB),NOSPLIT,$0-24
CMPB runtime·useQPCTime(SB), $0
JNE useQPC
MOVQ $_INTERRUPT_TIME, DI
loop:
MOVL time_hi1(DI), AX
@ -534,6 +527,3 @@ wall:
SUBQ DX, CX
MOVL CX, nsec+8(FP)
RET
useQPC:
JMP runtime·nowQPC(SB)
RET

View File

@ -496,10 +496,6 @@ TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
#define time_hi2 8
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
MOVW $0, R0
MOVB runtime·useQPCTime(SB), R0
CMP $0, R0
BNE useQPC
MOVW $_INTERRUPT_TIME, R3
loop:
MOVW time_hi1(R3), R1
@ -517,15 +513,8 @@ loop:
MOVW R3, ret_lo+0(FP)
MOVW R4, ret_hi+4(FP)
RET
useQPC:
B runtime·nanotimeQPC(SB) // tail call
RET
TEXT time·now(SB),NOSPLIT,$0-20
MOVW $0, R0
MOVB runtime·useQPCTime(SB), R0
CMP $0, R0
BNE useQPC
MOVW $_INTERRUPT_TIME, R3
loop:
MOVW time_hi1(R3), R1
@ -594,9 +583,6 @@ wall:
MOVW R7,sec_hi+4(FP)
MOVW R1,nsec+8(FP)
RET
useQPC:
B runtime·nanotimeQPC(SB) // tail call
RET
// save_g saves the g register (R10) into thread local memory
// so that we can call externally compiled