Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: async preemption still fail for pure tight loop #35923

Closed
changkun opened this issue Dec 2, 2019 · 7 comments
Closed

runtime: async preemption still fail for pure tight loop #35923

changkun opened this issue Dec 2, 2019 · 7 comments

Comments

@changkun
Copy link
Contributor

@changkun changkun commented Dec 2, 2019

What version of Go are you using (go version)?

$ go version
go version devel +8054b13536 Thu Nov 28 15:16:27 2019 +0000 darwin/amd64

and 

go version devel +8054b13536 Thu Nov 28 15:16:27 2019 +0000 linux/amd64

Does this issue reproduce with the latest release?

Yes, current tip

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/changkun/Library/Caches/go-build"
GOENV="/Users/changkun/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/changkun/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/changkun/dev/golang-go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/changkun/dev/golang-go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/jd/vym7tt9s2_379d4ccjcj1xrw0000gn/T/go-build916704906=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

I tested the current tip, and the async preemption remains to fail in a very simple case:

package main

import (
	"runtime"
	"time"
)

func main() {
	runtime.GOMAXPROCS(1)
	go func() {
		for {
		}
	}()
	for {
		time.Sleep(time.Millisecond)
		println("OK")
	}
}

I debugged a little and the issue is caused by the following check

if smi == -2 {

Deleting this if the check seems can fix the preemption for the example and pass all tests as well.

What did you expect to see?

Many OK

What did you see instead?

Nothing appears.

@cespare
Copy link
Contributor

@cespare cespare commented Dec 2, 2019

@choleraehyq
Copy link
Contributor

@choleraehyq choleraehyq commented Dec 2, 2019

Maybe it's because that anonymous function is nosplit here?

"".main.func1 STEXT nosplit size=3 args=0x0 locals=0x0
  0x0000 00000 (main.go:17) TEXT  "".main.func1(SB), NOSPLIT|ABIInternal, $0-0
  0x0000 00000 (main.go:17) PCDATA  $0, $-2
  0x0000 00000 (main.go:17) PCDATA  $1, $-2
  0x0000 00000 (main.go:17) FUNCDATA  $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (main.go:17) FUNCDATA  $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (main.go:17) FUNCDATA  $2, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
  0x0000 00000 (main.go:18) XCHGL AX, AX
  0x0001 00001 (main.go:1048575)  JMP 0
  0x0000 90 eb fd
@choleraehyq
Copy link
Contributor

@choleraehyq choleraehyq commented Dec 2, 2019

It seems that all leaf functions with small stack will be treated as nosplit function.
https://github.com/golang/go/blob/master/src/cmd/internal/obj/x86/obj6.go#L635

@cherrymui
Copy link
Contributor

@cherrymui cherrymui commented Dec 2, 2019

Deleting this if the check seems can fix the preemption for the example and pass all tests as well.

This is definitely incorrect. There are various non-preemptible regions, which are marked with -2.

There is a known issue that the very last instruction in a function is marked non-preemptible. For this particular function, that is the loop back-edge, making the empty loop hardly preemptible (which we should fix). However, it should be more preemptible in real code with non-empty loops.

@cherrymui cherrymui added this to the Unplanned milestone Dec 2, 2019
@changkun
Copy link
Contributor Author

@changkun changkun commented Dec 2, 2019

@cherrymui
I understand it is absolutely incorrect. Just curious: how could all tests be passed with this change in terms of so many non-preemptible regions?

@cherrymui
Copy link
Contributor

@cherrymui cherrymui commented Dec 2, 2019

@changkun The failure would be sporadic, not deterministic. You may need to run multiple times to see a failure. Also, it may be more likely to fail on some architectures than others.

@gopherbot
Copy link

@gopherbot gopherbot commented Dec 3, 2019

Change https://golang.org/cl/209659 mentions this issue: cmd/compile: mark empty block preemptible

@gopherbot gopherbot closed this in a037582 Dec 6, 2019
@golang golang locked and limited conversation to collaborators Dec 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants