From 0435e88a119fd057aa7209591ba3dff122c9f24c Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 18 Mar 2016 10:56:23 +0100 Subject: [PATCH] runtime: revert "do not call timeBeginPeriod on windows" This reverts commit ab4c9298b8185a056ff1152f2c7bd9b38d3d06f3. Sysmon critically depends on system timer resolution for retaking of Ps blocked in system calls. See #14790 for an example of a program where execution time goes from 2ms to 30ms if timeBeginPeriod(1) is not used. We can remove timeBeginPeriod(1) when we support UMS (#7876). Update #14790 Change-Id: I362b56154359b2c52d47f9f2468fe012b481cf6d Reviewed-on: https://go-review.googlesource.com/20834 Reviewed-by: Austin Clements Run-TryBot: Dmitry Vyukov TryBot-Result: Gobot Gobot Reviewed-by: Alex Brainman --- misc/cgo/testcarchive/carchive_test.go | 2 +- src/runtime/export_windows_test.go | 7 ++- src/runtime/os_windows.go | 9 +++- src/runtime/syscall_windows_test.go | 66 +++++--------------------- 4 files changed, 25 insertions(+), 59 deletions(-) diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go index 47e0ceb5c9..72e9ef1d59 100644 --- a/misc/cgo/testcarchive/carchive_test.go +++ b/misc/cgo/testcarchive/carchive_test.go @@ -120,7 +120,7 @@ func goEnv(key string) string { func compilemain(t *testing.T, libgo string) { ccArgs := append(cc, "-o", "testp"+exeSuffix, "main.c") if GOOS == "windows" { - ccArgs = append(ccArgs, "main_windows.c", libgo, "-lntdll", "-lws2_32") + ccArgs = append(ccArgs, "main_windows.c", libgo, "-lntdll", "-lws2_32", "-lwinmm") } else { ccArgs = append(ccArgs, "main_unix.c", libgo) } diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go index 66c103709c..536b398fd7 100644 --- a/src/runtime/export_windows_test.go +++ b/src/runtime/export_windows_test.go @@ -8,8 +8,11 @@ package runtime import "unsafe" -var TestingWER = &testingWER -var OsYield = osyield +var ( + TestingWER = &testingWER + OsYield = osyield + TimeBeginPeriodRetValue = &timeBeginPeriodRetValue +) func NumberOfProcessors() int32 { var info systeminfo diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 7244706b92..9147091a49 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -53,6 +53,7 @@ const ( //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll" //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll" //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll" +//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod%1 "winmm.dll" type stdFunction unsafe.Pointer @@ -98,7 +99,9 @@ var ( _WSAGetOverlappedResult, _WaitForSingleObject, _WriteConsoleW, - _WriteFile stdFunction + _WriteFile, + _timeBeginPeriod, + _ stdFunction // Following syscalls are only available on some Windows PCs. // We will load syscalls, if available, before using them. @@ -228,6 +231,8 @@ func setlasterror(err uint32) // flags can be used with LoadLibraryEx." var useLoadLibraryEx bool +var timeBeginPeriodRetValue uint32 + func osinit() { asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) usleep2Addr = unsafe.Pointer(funcPC(usleep2)) @@ -247,6 +252,8 @@ func osinit() { stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) + timeBeginPeriodRetValue = uint32(stdcall1(_timeBeginPeriod, 1)) + ncpu = getproccount() // Windows dynamic priority boosting assumes that a process has different types diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index ff045338c1..4a10749682 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -622,6 +622,13 @@ uintptr_t cfunc(callback f, uintptr_t n) { } } +func TestTimeBeginPeriod(t *testing.T) { + const TIMERR_NOERROR = 0 + if *runtime.TimeBeginPeriodRetValue != TIMERR_NOERROR { + t.Fatalf("timeBeginPeriod failed: it returned %d", *runtime.TimeBeginPeriodRetValue) + } +} + // removeOneCPU removes one (any) cpu from affinity mask. // It returns new affinity mask. func removeOneCPU(mask uintptr) (uintptr, error) { @@ -874,21 +881,10 @@ var ( modwinmm = syscall.NewLazyDLL("winmm.dll") modkernel32 = syscall.NewLazyDLL("kernel32.dll") - proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod") - proctimeEndPeriod = modwinmm.NewProc("timeEndPeriod") - procCreateEvent = modkernel32.NewProc("CreateEventW") procSetEvent = modkernel32.NewProc("SetEvent") ) -func timeBeginPeriod(period uint32) { - syscall.Syscall(proctimeBeginPeriod.Addr(), 1, uintptr(period), 0, 0) -} - -func timeEndPeriod(period uint32) { - syscall.Syscall(proctimeEndPeriod.Addr(), 1, uintptr(period), 0, 0) -} - func createEvent() (syscall.Handle, error) { r0, _, e0 := syscall.Syscall6(procCreateEvent.Addr(), 4, 0, 0, 0, 0, 0, 0) if r0 == 0 { @@ -905,7 +901,7 @@ func setEvent(h syscall.Handle) error { return nil } -func benchChanToSyscallPing(b *testing.B) { +func BenchmarkChanToSyscallPing(b *testing.B) { n := b.N ch := make(chan int) event, err := createEvent() @@ -927,17 +923,7 @@ func benchChanToSyscallPing(b *testing.B) { } } -func BenchmarkChanToSyscallPing1ms(b *testing.B) { - timeBeginPeriod(1) - benchChanToSyscallPing(b) - timeEndPeriod(1) -} - -func BenchmarkChanToSyscallPing15ms(b *testing.B) { - benchChanToSyscallPing(b) -} - -func benchSyscallToSyscallPing(b *testing.B) { +func BenchmarkSyscallToSyscallPing(b *testing.B) { n := b.N event1, err := createEvent() if err != nil { @@ -965,17 +951,7 @@ func benchSyscallToSyscallPing(b *testing.B) { } } -func BenchmarkSyscallToSyscallPing1ms(b *testing.B) { - timeBeginPeriod(1) - benchSyscallToSyscallPing(b) - timeEndPeriod(1) -} - -func BenchmarkSyscallToSyscallPing15ms(b *testing.B) { - benchSyscallToSyscallPing(b) -} - -func benchChanToChanPing(b *testing.B) { +func BenchmarkChanToChanPing(b *testing.B) { n := b.N ch1 := make(chan int) ch2 := make(chan int) @@ -991,28 +967,8 @@ func benchChanToChanPing(b *testing.B) { } } -func BenchmarkChanToChanPing1ms(b *testing.B) { - timeBeginPeriod(1) - benchChanToChanPing(b) - timeEndPeriod(1) -} - -func BenchmarkChanToChanPing15ms(b *testing.B) { - benchChanToChanPing(b) -} - -func benchOsYield(b *testing.B) { +func BenchmarkOsYield(b *testing.B) { for i := 0; i < b.N; i++ { runtime.OsYield() } } - -func BenchmarkOsYield1ms(b *testing.B) { - timeBeginPeriod(1) - benchOsYield(b) - timeEndPeriod(1) -} - -func BenchmarkOsYield15ms(b *testing.B) { - benchOsYield(b) -}