diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 05fa47158a..e81852f607 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -181,8 +181,14 @@ func cgocall(fn, arg unsafe.Pointer) int32 { osPreemptExtExit(mp) + // Save current syscall parameters, so m.winsyscall can be + // used again if callback decide to make syscall. + winsyscall := mp.winsyscall + exitsyscall() + getg().m.winsyscall = winsyscall + // Note that raceacquire must be called only after exitsyscall has // wired this M to a P. if raceenabled { @@ -297,9 +303,9 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { checkm := gp.m - // Save current syscall parameters, so m.syscall can be + // Save current syscall parameters, so m.winsyscall can be // used again if callback decide to make syscall. - syscall := gp.m.syscall + winsyscall := gp.m.winsyscall // entersyscall saves the caller's SP to allow the GC to trace the Go // stack. However, since we're returning to an earlier stack frame and @@ -340,7 +346,7 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { // going back to cgo call reentersyscall(savedpc, uintptr(savedsp)) - gp.m.syscall = syscall + gp.m.winsyscall = winsyscall } func cgocallbackg1(fn, frame unsafe.Pointer, ctxt uintptr) { diff --git a/src/runtime/nonwindows_stub.go b/src/runtime/nonwindows_stub.go index e420acf185..859ae48004 100644 --- a/src/runtime/nonwindows_stub.go +++ b/src/runtime/nonwindows_stub.go @@ -21,3 +21,8 @@ func osRelax(relax bool) {} // enableWER is called by setTraceback("wer"). // Windows Error Reporting (WER) is only supported on Windows. func enableWER() {} + +// winlibcall is not implemented on non-Windows systems, +// but it is used in non-OS-specific parts of the runtime. +// Define it as an empty struct to avoid wasting stack space. +type winlibcall struct{} diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go index 0074b9358a..d65e0c91f4 100644 --- a/src/runtime/os_windows.go +++ b/src/runtime/os_windows.go @@ -214,6 +214,8 @@ func asmstdcall(fn unsafe.Pointer) var asmstdcallAddr unsafe.Pointer +type winlibcall libcall + func windowsFindfunc(lib uintptr, name []byte) stdFunction { if name[len(name)-1] != 0 { throw("usage") diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 4a7ad27172..c335f8c9d0 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -612,11 +612,11 @@ type m struct { // these are here because they are too large to be on the stack // of low-level NOSPLIT functions. - libcall libcall - libcallpc uintptr // for cpu profiler - libcallsp uintptr - libcallg guintptr - syscall libcall // stores syscall parameters on windows + libcall libcall + libcallpc uintptr // for cpu profiler + libcallsp uintptr + libcallg guintptr + winsyscall winlibcall // stores syscall parameters on windows vdsoSP uintptr // SP for traceback while in VDSO call (0 if not in call) vdsoPC uintptr // PC for traceback while in VDSO call diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 0b08583563..09762aed51 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -500,16 +500,18 @@ func syscall_SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) { } // The cgocall parameters are stored in m instead of in - // the stack because the stack can move during if fn + // the stack because the stack can move during fn if it // calls back into Go. - lockOSThread() - defer unlockOSThread() - c := &getg().m.syscall + c := &getg().m.winsyscall c.fn = fn c.n = uintptr(len(args)) if c.n != 0 { c.args = uintptr(noescape(unsafe.Pointer(&args[0]))) } cgocall(asmstdcallAddr, unsafe.Pointer(c)) + // cgocall may reschedule us on to a different M, + // but it copies the return values into the new M's + // so we can read them from there. + c = &getg().m.winsyscall return c.r1, c.r2, c.err }