aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/proc.go21
-rw-r--r--src/runtime/syscall_windows_test.go2
2 files changed, 18 insertions, 5 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 9f4feebfd7..9908951544 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -1293,7 +1293,9 @@ func mstart1() {
//go:yeswritebarrierrec
func mstartm0() {
// Create an extra M for callbacks on threads not created by Go.
- if iscgo && !cgoHasExtraM {
+ // An extra M is also needed on Windows for callbacks created by
+ // syscall.NewCallback. See issue #6751 for details.
+ if (iscgo || GOOS == "windows") && !cgoHasExtraM {
cgoHasExtraM = true
newextram()
}
@@ -1618,8 +1620,12 @@ func allocm(_p_ *p, fn func()) *m {
// put the m back on the list.
//go:nosplit
func needm(x byte) {
- if iscgo && !cgoHasExtraM {
+ if (iscgo || GOOS == "windows") && !cgoHasExtraM {
// Can happen if C/C++ code calls Go from a global ctor.
+ // Can also happen on Windows if a global ctor uses a
+ // callback created by syscall.NewCallback. See issue #6751
+ // for details.
+ //
// Can not throw, because scheduler is not initialized yet.
write(2, unsafe.Pointer(&earlycgocallback[0]), int32(len(earlycgocallback)))
exit(1)
@@ -4215,8 +4221,17 @@ func checkdead() {
return
}
+ // If we are not running under cgo, but we have an extra M then account
+ // for it. (It is possible to have an extra M on Windows without cgo to
+ // accommodate callbacks created by syscall.NewCallback. See issue #6751
+ // for details.)
+ var run0 int32
+ if !iscgo && cgoHasExtraM {
+ run0 = 1
+ }
+
run := mcount() - sched.nmidle - sched.nmidlelocked - sched.nmsys
- if run > 0 {
+ if run > run0 {
return
}
if run < 0 {
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index 2b057213f2..0f5e13f97e 100644
--- a/src/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -251,8 +251,6 @@ func TestBlockingCallback(t *testing.T) {
}
func TestCallbackInAnotherThread(t *testing.T) {
- t.Skip("Skipping failing test (see golang.org/issue/6751 for details)")
-
d := GetDLL(t, "kernel32.dll")
f := func(p uintptr) uintptr {