diff options
Diffstat (limited to 'golang-runtime-resume-timers.patch')
-rw-r--r-- | golang-runtime-resume-timers.patch | 203 |
1 files changed, 0 insertions, 203 deletions
diff --git a/golang-runtime-resume-timers.patch b/golang-runtime-resume-timers.patch deleted file mode 100644 index d2a78406..00000000 --- a/golang-runtime-resume-timers.patch +++ /dev/null @@ -1,203 +0,0 @@ -From 84b070f6fab474f9e278d9e85b198e1382499b48 Mon Sep 17 00:00:00 2001 -From: "Jason A. Donenfeld" <Jason@zx2c4.com> -Date: Tue, 27 Aug 2019 06:46:16 -0600 -Subject: [PATCH] [release-branch.go1.13] runtime: monitor for suspend/resume - to kick timeouts - -Starting in Windows 8, the wait functions don't take into account -suspend time, even though the monotonic counters do. This results in -timer buckets stalling on resume. Therefore, this commit makes it so -that on resume, we return from the wait functions and recalculate the -amount of time left to wait. - -This is a cherry pick of CL 191957 and its cleanup, CL 198417. - -Updates #31528 -Fixes #34130 - -Change-Id: I0db02cc72188cb620954e87a0180e0a3c83f4a56 -Reviewed-on: https://go-review.googlesource.com/c/go/+/193607 -Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> -TryBot-Result: Gobot Gobot <gobot@golang.org> -Reviewed-by: Austin Clements <austin@google.com> ---- - src/runtime/os_windows.go | 81 ++++++++++++++++++++++++++++++---- - src/runtime/syscall_windows.go | 12 +++-- - 2 files changed, 80 insertions(+), 13 deletions(-) - -diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go -index 074ae0f40de..1cd0932eaed 100644 ---- a/src/runtime/os_windows.go -+++ b/src/runtime/os_windows.go -@@ -49,6 +49,7 @@ const ( - //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll" - //go:cgo_import_dynamic runtime._VirtualQuery VirtualQuery%3 "kernel32.dll" - //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll" -+//go:cgo_import_dynamic runtime._WaitForMultipleObjects WaitForMultipleObjects%4 "kernel32.dll" - //go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll" - //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll" - -@@ -96,6 +97,7 @@ var ( - _VirtualFree, - _VirtualQuery, - _WaitForSingleObject, -+ _WaitForMultipleObjects, - _WriteConsoleW, - _WriteFile, - _ stdFunction -@@ -139,7 +141,8 @@ func tstart_stdcall(newm *m) - func ctrlhandler() - - type mOS struct { -- waitsema uintptr // semaphore for parking on locks -+ waitsema uintptr // semaphore for parking on locks -+ resumesema uintptr // semaphore to indicate suspend/resume - } - - //go:linkname os_sigpipe os.sigpipe -@@ -258,6 +261,40 @@ func loadOptionalSyscalls() { - } - } - -+func monitorSuspendResume() { -+ const _DEVICE_NOTIFY_CALLBACK = 2 -+ type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct { -+ callback uintptr -+ context uintptr -+ } -+ -+ powrprof := windowsLoadSystemLib([]byte("powrprof.dll\000")) -+ if powrprof == 0 { -+ return // Running on Windows 7, where we don't need it anyway. -+ } -+ powerRegisterSuspendResumeNotification := windowsFindfunc(powrprof, []byte("PowerRegisterSuspendResumeNotification\000")) -+ if powerRegisterSuspendResumeNotification == nil { -+ return // Running on Windows 7, where we don't need it anyway. -+ } -+ var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr { -+ for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink { -+ if mp.resumesema != 0 { -+ stdcall1(_SetEvent, mp.resumesema) -+ } -+ } -+ return 0 -+ } -+ params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{ -+ callback: compileCallback(*efaceOf(&fn), true), -+ } -+ handle := uintptr(0) -+ if stdcall3(powerRegisterSuspendResumeNotification, _DEVICE_NOTIFY_CALLBACK, -+ uintptr(unsafe.Pointer(¶ms)), -+ uintptr(unsafe.Pointer(&handle))) != 0 { -+ throw("PowerRegisterSuspendResumeNotification failure") -+ } -+} -+ - //go:nosplit - func getLoadLibrary() uintptr { - return uintptr(unsafe.Pointer(_LoadLibraryW)) -@@ -488,6 +525,10 @@ func goenvs() { - } - - stdcall1(_FreeEnvironmentStringsW, uintptr(strings)) -+ -+ // We call this all the way here, late in init, so that malloc works -+ // for the callback function this generates. -+ monitorSuspendResume() - } - - // exiting is set to non-zero when the process is exiting. -@@ -606,19 +647,32 @@ func semasleep(ns int64) int32 { - _WAIT_FAILED = 0xFFFFFFFF - ) - -- // store ms in ns to save stack space -+ var result uintptr - if ns < 0 { -- ns = _INFINITE -+ result = stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(_INFINITE)) - } else { -- ns = int64(timediv(ns, 1000000, nil)) -- if ns == 0 { -- ns = 1 -+ start := nanotime() -+ elapsed := int64(0) -+ for { -+ ms := int64(timediv(ns-elapsed, 1000000, nil)) -+ if ms == 0 { -+ ms = 1 -+ } -+ result = stdcall4(_WaitForMultipleObjects, 2, -+ uintptr(unsafe.Pointer(&[2]uintptr{getg().m.waitsema, getg().m.resumesema})), -+ 0, uintptr(ms)) -+ if result != _WAIT_OBJECT_0+1 { -+ // Not a suspend/resume event -+ break -+ } -+ elapsed = nanotime() - start -+ if elapsed >= ns { -+ return -1 -+ } - } - } -- -- result := stdcall2(_WaitForSingleObject, getg().m.waitsema, uintptr(ns)) - switch result { -- case _WAIT_OBJECT_0: //signaled -+ case _WAIT_OBJECT_0: // Signaled - return 0 - - case _WAIT_TIMEOUT: -@@ -667,6 +721,15 @@ func semacreate(mp *m) { - throw("runtime.semacreate") - }) - } -+ mp.resumesema = stdcall4(_CreateEventA, 0, 0, 0, 0) -+ if mp.resumesema == 0 { -+ systemstack(func() { -+ print("runtime: createevent failed; errno=", getlasterror(), "\n") -+ throw("runtime.semacreate") -+ }) -+ stdcall1(_CloseHandle, mp.waitsema) -+ mp.waitsema = 0 -+ } - } - - // May run with m.p==nil, so write barriers are not allowed. This -diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go -index 722a73d108e..0e2fcfb02da 100644 ---- a/src/runtime/syscall_windows.go -+++ b/src/runtime/syscall_windows.go -@@ -74,16 +74,18 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) { - argsize += uintptrSize - } - -- lock(&cbs.lock) -- defer unlock(&cbs.lock) -+ lock(&cbs.lock) // We don't unlock this in a defer because this is used from the system stack. - - n := cbs.n - for i := 0; i < n; i++ { - if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack { -- return callbackasmAddr(i) -+ r := callbackasmAddr(i) -+ unlock(&cbs.lock) -+ return r - } - } - if n >= cb_max { -+ unlock(&cbs.lock) - throw("too many callback functions") - } - -@@ -99,7 +101,9 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) { - cbs.ctxt[n] = c - cbs.n++ - -- return callbackasmAddr(n) -+ r := callbackasmAddr(n) -+ unlock(&cbs.lock) -+ return r - } - - const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 |