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

Open
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

This comment has been minimized.

Copy link
Contributor

@cespare cespare commented Dec 2, 2019

@choleraehyq

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Dec 3, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.