]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: don't async preempt NO_LOCAL_POINTERS assembly functions
authorCherry Zhang <cherryyz@google.com>
Sun, 20 Oct 2019 21:23:02 +0000 (17:23 -0400)
committerAustin Clements <austin@google.com>
Sat, 2 Nov 2019 22:02:43 +0000 (22:02 +0000)
We don't async preempt assembly functions. We do that by checking
whether the function has a local pointer map, and assume it is
an assembly (or, non-Go) function if there isn't one. However,
assembly functions marked with NO_LOCAL_POINTERS still have local
pointer maps, and we wouldn't identify them. For them, check for
the special pointer map runtime.no_pointers_stackmap as well, and
treat them as not async preemptible.

Change-Id: I1301e3b4d35893c31c4c5a5147a0d775987bd6f4
Reviewed-on: https://go-review.googlesource.com/c/go/+/202337
Reviewed-by: Austin Clements <austin@google.com>
src/runtime/preempt.go

index 71c30898307a0fdc8037d4d9d77112768cf99849..544c251a9fe0ed456066935af7bb04bf6d34a1fb 100644 (file)
@@ -55,6 +55,7 @@ package runtime
 import (
        "runtime/internal/atomic"
        "runtime/internal/sys"
+       "unsafe"
 )
 
 type suspendGState struct {
@@ -369,9 +370,12 @@ func isAsyncSafePoint(gp *g, pc, sp uintptr) bool {
                // functions (except at calls).
                return false
        }
-       if funcdata(f, _FUNCDATA_LocalsPointerMaps) == nil {
+       if fd := funcdata(f, _FUNCDATA_LocalsPointerMaps); fd == nil || fd == unsafe.Pointer(&no_pointers_stackmap) {
                // This is assembly code. Don't assume it's
-               // well-formed.
+               // well-formed. We identify assembly code by
+               // checking that it has either no stack map, or
+               // no_pointers_stackmap, which is the stack map
+               // for ones marked as NO_LOCAL_POINTERS.
                //
                // TODO: Are there cases that are safe but don't have a
                // locals pointer map, like empty frame functions?
@@ -395,3 +399,5 @@ func isAsyncSafePoint(gp *g, pc, sp uintptr) bool {
 
        return true
 }
+
+var no_pointers_stackmap uint64 // defined in assembly, for NO_LOCAL_POINTERS macro