runtime: revert "do not call timeBeginPeriod on windows"

This reverts commit ab4c9298b8.

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 <austin@google.com>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Dmitry Vyukov 2016-03-18 10:56:23 +01:00
parent 9d4efdfd12
commit 0435e88a11
4 changed files with 25 additions and 59 deletions

View file

@ -120,7 +120,7 @@ func goEnv(key string) string {
func compilemain(t *testing.T, libgo string) { func compilemain(t *testing.T, libgo string) {
ccArgs := append(cc, "-o", "testp"+exeSuffix, "main.c") ccArgs := append(cc, "-o", "testp"+exeSuffix, "main.c")
if GOOS == "windows" { 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 { } else {
ccArgs = append(ccArgs, "main_unix.c", libgo) ccArgs = append(ccArgs, "main_unix.c", libgo)
} }

View file

@ -8,8 +8,11 @@ package runtime
import "unsafe" import "unsafe"
var TestingWER = &testingWER var (
var OsYield = osyield TestingWER = &testingWER
OsYield = osyield
TimeBeginPeriodRetValue = &timeBeginPeriodRetValue
)
func NumberOfProcessors() int32 { func NumberOfProcessors() int32 {
var info systeminfo var info systeminfo

View file

@ -53,6 +53,7 @@ const (
//go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll" //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._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
//go:cgo_import_dynamic runtime._WriteFile WriteFile%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 type stdFunction unsafe.Pointer
@ -98,7 +99,9 @@ var (
_WSAGetOverlappedResult, _WSAGetOverlappedResult,
_WaitForSingleObject, _WaitForSingleObject,
_WriteConsoleW, _WriteConsoleW,
_WriteFile stdFunction _WriteFile,
_timeBeginPeriod,
_ stdFunction
// Following syscalls are only available on some Windows PCs. // Following syscalls are only available on some Windows PCs.
// We will load syscalls, if available, before using them. // We will load syscalls, if available, before using them.
@ -228,6 +231,8 @@ func setlasterror(err uint32)
// flags can be used with LoadLibraryEx." // flags can be used with LoadLibraryEx."
var useLoadLibraryEx bool var useLoadLibraryEx bool
var timeBeginPeriodRetValue uint32
func osinit() { func osinit() {
asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall)) asmstdcallAddr = unsafe.Pointer(funcPC(asmstdcall))
usleep2Addr = unsafe.Pointer(funcPC(usleep2)) usleep2Addr = unsafe.Pointer(funcPC(usleep2))
@ -247,6 +252,8 @@ func osinit() {
stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1) stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
timeBeginPeriodRetValue = uint32(stdcall1(_timeBeginPeriod, 1))
ncpu = getproccount() ncpu = getproccount()
// Windows dynamic priority boosting assumes that a process has different types // Windows dynamic priority boosting assumes that a process has different types

View file

@ -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. // removeOneCPU removes one (any) cpu from affinity mask.
// It returns new affinity mask. // It returns new affinity mask.
func removeOneCPU(mask uintptr) (uintptr, error) { func removeOneCPU(mask uintptr) (uintptr, error) {
@ -874,21 +881,10 @@ var (
modwinmm = syscall.NewLazyDLL("winmm.dll") modwinmm = syscall.NewLazyDLL("winmm.dll")
modkernel32 = syscall.NewLazyDLL("kernel32.dll") modkernel32 = syscall.NewLazyDLL("kernel32.dll")
proctimeBeginPeriod = modwinmm.NewProc("timeBeginPeriod")
proctimeEndPeriod = modwinmm.NewProc("timeEndPeriod")
procCreateEvent = modkernel32.NewProc("CreateEventW") procCreateEvent = modkernel32.NewProc("CreateEventW")
procSetEvent = modkernel32.NewProc("SetEvent") 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) { func createEvent() (syscall.Handle, error) {
r0, _, e0 := syscall.Syscall6(procCreateEvent.Addr(), 4, 0, 0, 0, 0, 0, 0) r0, _, e0 := syscall.Syscall6(procCreateEvent.Addr(), 4, 0, 0, 0, 0, 0, 0)
if r0 == 0 { if r0 == 0 {
@ -905,7 +901,7 @@ func setEvent(h syscall.Handle) error {
return nil return nil
} }
func benchChanToSyscallPing(b *testing.B) { func BenchmarkChanToSyscallPing(b *testing.B) {
n := b.N n := b.N
ch := make(chan int) ch := make(chan int)
event, err := createEvent() event, err := createEvent()
@ -927,17 +923,7 @@ func benchChanToSyscallPing(b *testing.B) {
} }
} }
func BenchmarkChanToSyscallPing1ms(b *testing.B) { func BenchmarkSyscallToSyscallPing(b *testing.B) {
timeBeginPeriod(1)
benchChanToSyscallPing(b)
timeEndPeriod(1)
}
func BenchmarkChanToSyscallPing15ms(b *testing.B) {
benchChanToSyscallPing(b)
}
func benchSyscallToSyscallPing(b *testing.B) {
n := b.N n := b.N
event1, err := createEvent() event1, err := createEvent()
if err != nil { if err != nil {
@ -965,17 +951,7 @@ func benchSyscallToSyscallPing(b *testing.B) {
} }
} }
func BenchmarkSyscallToSyscallPing1ms(b *testing.B) { func BenchmarkChanToChanPing(b *testing.B) {
timeBeginPeriod(1)
benchSyscallToSyscallPing(b)
timeEndPeriod(1)
}
func BenchmarkSyscallToSyscallPing15ms(b *testing.B) {
benchSyscallToSyscallPing(b)
}
func benchChanToChanPing(b *testing.B) {
n := b.N n := b.N
ch1 := make(chan int) ch1 := make(chan int)
ch2 := make(chan int) ch2 := make(chan int)
@ -991,28 +967,8 @@ func benchChanToChanPing(b *testing.B) {
} }
} }
func BenchmarkChanToChanPing1ms(b *testing.B) { func BenchmarkOsYield(b *testing.B) {
timeBeginPeriod(1)
benchChanToChanPing(b)
timeEndPeriod(1)
}
func BenchmarkChanToChanPing15ms(b *testing.B) {
benchChanToChanPing(b)
}
func benchOsYield(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
runtime.OsYield() runtime.OsYield()
} }
} }
func BenchmarkOsYield1ms(b *testing.B) {
timeBeginPeriod(1)
benchOsYield(b)
timeEndPeriod(1)
}
func BenchmarkOsYield15ms(b *testing.B) {
benchOsYield(b)
}