mirror of
https://github.com/golang/go
synced 2024-11-27 04:41:33 -07:00
Revert "runtime: remove slow time compatibility hacks for wine"
This reverts CL 191759. Reason for revert: broke most Go programs using the time package on Wine, including on 4.15, the latest stable version. Only wine-staging (with experimental patches) contains an upstream fix we could rely on. Change-Id: Ic8ba126022e54f412174042fbb9abed82d5eb318 Reviewed-on: https://go-review.googlesource.com/c/go/+/192622 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
parent
ea2fb678c0
commit
b36a7a502a
@ -76,10 +76,12 @@ var (
|
|||||||
_GetStdHandle,
|
_GetStdHandle,
|
||||||
_GetSystemDirectoryA,
|
_GetSystemDirectoryA,
|
||||||
_GetSystemInfo,
|
_GetSystemInfo,
|
||||||
|
_GetSystemTimeAsFileTime,
|
||||||
_GetThreadContext,
|
_GetThreadContext,
|
||||||
_LoadLibraryW,
|
_LoadLibraryW,
|
||||||
_LoadLibraryA,
|
_LoadLibraryA,
|
||||||
_QueryPerformanceCounter,
|
_QueryPerformanceCounter,
|
||||||
|
_QueryPerformanceFrequency,
|
||||||
_ResumeThread,
|
_ResumeThread,
|
||||||
_SetConsoleCtrlHandler,
|
_SetConsoleCtrlHandler,
|
||||||
_SetErrorMode,
|
_SetErrorMode,
|
||||||
@ -252,6 +254,11 @@ func loadOptionalSyscalls() {
|
|||||||
if _WSAGetOverlappedResult == nil {
|
if _WSAGetOverlappedResult == nil {
|
||||||
throw("WSAGetOverlappedResult not found")
|
throw("WSAGetOverlappedResult not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if windowsFindfunc(n32, []byte("wine_get_version\000")) != nil {
|
||||||
|
// running on Wine
|
||||||
|
initWine(k32)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func monitorSuspendResume() {
|
func monitorSuspendResume() {
|
||||||
@ -411,6 +418,77 @@ func osinit() {
|
|||||||
|
|
||||||
func nanotime() int64
|
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
|
//go:nosplit
|
||||||
func getRandomData(r []byte) {
|
func getRandomData(r []byte) {
|
||||||
n := 0
|
n := 0
|
||||||
|
@ -445,6 +445,8 @@ TEXT runtime·switchtothread(SB),NOSPLIT,$0
|
|||||||
#define time_hi2 8
|
#define time_hi2 8
|
||||||
|
|
||||||
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
|
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
|
||||||
|
CMPB runtime·useQPCTime(SB), $0
|
||||||
|
JNE useQPC
|
||||||
loop:
|
loop:
|
||||||
MOVL (_INTERRUPT_TIME+time_hi1), AX
|
MOVL (_INTERRUPT_TIME+time_hi1), AX
|
||||||
MOVL (_INTERRUPT_TIME+time_lo), CX
|
MOVL (_INTERRUPT_TIME+time_lo), CX
|
||||||
@ -461,8 +463,13 @@ loop:
|
|||||||
MOVL AX, ret_lo+0(FP)
|
MOVL AX, ret_lo+0(FP)
|
||||||
MOVL DX, ret_hi+4(FP)
|
MOVL DX, ret_hi+4(FP)
|
||||||
RET
|
RET
|
||||||
|
useQPC:
|
||||||
|
JMP runtime·nanotimeQPC(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT time·now(SB),NOSPLIT,$0-20
|
TEXT time·now(SB),NOSPLIT,$0-20
|
||||||
|
CMPB runtime·useQPCTime(SB), $0
|
||||||
|
JNE useQPC
|
||||||
loop:
|
loop:
|
||||||
MOVL (_INTERRUPT_TIME+time_hi1), AX
|
MOVL (_INTERRUPT_TIME+time_hi1), AX
|
||||||
MOVL (_INTERRUPT_TIME+time_lo), CX
|
MOVL (_INTERRUPT_TIME+time_lo), CX
|
||||||
@ -531,3 +538,6 @@ wall:
|
|||||||
MOVL AX, sec+0(FP)
|
MOVL AX, sec+0(FP)
|
||||||
MOVL DX, sec+4(FP)
|
MOVL DX, sec+4(FP)
|
||||||
RET
|
RET
|
||||||
|
useQPC:
|
||||||
|
JMP runtime·nowQPC(SB)
|
||||||
|
RET
|
||||||
|
@ -474,6 +474,8 @@ TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
|
|||||||
#define time_hi2 8
|
#define time_hi2 8
|
||||||
|
|
||||||
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
|
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
|
||||||
|
CMPB runtime·useQPCTime(SB), $0
|
||||||
|
JNE useQPC
|
||||||
MOVQ $_INTERRUPT_TIME, DI
|
MOVQ $_INTERRUPT_TIME, DI
|
||||||
loop:
|
loop:
|
||||||
MOVL time_hi1(DI), AX
|
MOVL time_hi1(DI), AX
|
||||||
@ -486,8 +488,13 @@ loop:
|
|||||||
IMULQ $100, CX
|
IMULQ $100, CX
|
||||||
MOVQ CX, ret+0(FP)
|
MOVQ CX, ret+0(FP)
|
||||||
RET
|
RET
|
||||||
|
useQPC:
|
||||||
|
JMP runtime·nanotimeQPC(SB)
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT time·now(SB),NOSPLIT,$0-24
|
TEXT time·now(SB),NOSPLIT,$0-24
|
||||||
|
CMPB runtime·useQPCTime(SB), $0
|
||||||
|
JNE useQPC
|
||||||
MOVQ $_INTERRUPT_TIME, DI
|
MOVQ $_INTERRUPT_TIME, DI
|
||||||
loop:
|
loop:
|
||||||
MOVL time_hi1(DI), AX
|
MOVL time_hi1(DI), AX
|
||||||
@ -527,3 +534,6 @@ wall:
|
|||||||
SUBQ DX, CX
|
SUBQ DX, CX
|
||||||
MOVL CX, nsec+8(FP)
|
MOVL CX, nsec+8(FP)
|
||||||
RET
|
RET
|
||||||
|
useQPC:
|
||||||
|
JMP runtime·nowQPC(SB)
|
||||||
|
RET
|
||||||
|
@ -496,6 +496,10 @@ TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
|
|||||||
#define time_hi2 8
|
#define time_hi2 8
|
||||||
|
|
||||||
TEXT runtime·nanotime(SB),NOSPLIT,$0-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
|
MOVW $_INTERRUPT_TIME, R3
|
||||||
loop:
|
loop:
|
||||||
MOVW time_hi1(R3), R1
|
MOVW time_hi1(R3), R1
|
||||||
@ -513,8 +517,15 @@ loop:
|
|||||||
MOVW R3, ret_lo+0(FP)
|
MOVW R3, ret_lo+0(FP)
|
||||||
MOVW R4, ret_hi+4(FP)
|
MOVW R4, ret_hi+4(FP)
|
||||||
RET
|
RET
|
||||||
|
useQPC:
|
||||||
|
B runtime·nanotimeQPC(SB) // tail call
|
||||||
|
RET
|
||||||
|
|
||||||
TEXT time·now(SB),NOSPLIT,$0-20
|
TEXT time·now(SB),NOSPLIT,$0-20
|
||||||
|
MOVW $0, R0
|
||||||
|
MOVB runtime·useQPCTime(SB), R0
|
||||||
|
CMP $0, R0
|
||||||
|
BNE useQPC
|
||||||
MOVW $_INTERRUPT_TIME, R3
|
MOVW $_INTERRUPT_TIME, R3
|
||||||
loop:
|
loop:
|
||||||
MOVW time_hi1(R3), R1
|
MOVW time_hi1(R3), R1
|
||||||
@ -583,6 +594,9 @@ wall:
|
|||||||
MOVW R7,sec_hi+4(FP)
|
MOVW R7,sec_hi+4(FP)
|
||||||
MOVW R1,nsec+8(FP)
|
MOVW R1,nsec+8(FP)
|
||||||
RET
|
RET
|
||||||
|
useQPC:
|
||||||
|
B runtime·nanotimeQPC(SB) // tail call
|
||||||
|
RET
|
||||||
|
|
||||||
// save_g saves the g register (R10) into thread local memory
|
// save_g saves the g register (R10) into thread local memory
|
||||||
// so that we can call externally compiled
|
// so that we can call externally compiled
|
||||||
|
Loading…
Reference in New Issue
Block a user