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:
parent
8f79ca1d1a
commit
b4ad49f9f7
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user