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: (theoretically) redundant package check in isAsyncSafePoint #72031

Open
prattmic opened this issue Feb 28, 2025 · 1 comment
Open

runtime: (theoretically) redundant package check in isAsyncSafePoint #72031

prattmic opened this issue Feb 28, 2025 · 1 comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. Implementation Issues describing a semantics-preserving change to the Go implementation. NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@prattmic
Copy link
Member

runtime.isAsyncSafePoint determines if it safe to preempt a PC.

We always consider the runtime unsafe since it contains a bunch of different unsafe areas (long term we'd like to be more precise).

isAsyncSafePoint has a check if the PC is from a runtime package. This check is a bit odd for a few reasons:

  1. It doesn't actually contains all runtime packages (as defined by objabi), notably it is missing internal/runtime/.... This is what first brought this code to my attention.
  2. The compiler marks "all points" in runtime functions as unsafe, so why do we need this check at all?

Given (2), I tried removing the check entirely, which caused spectacular crashes, so it is definitely necessary.

There are a few problems in the way of removing this check:

The check looks at the innermost function of a PC because a runtime function may be inlined into a non-runtime function (Originally added in https://go.dev/cl/211978 for runtime.UnlockOSThread). But the compiler only marks functions as unsafe when compiling a runtime package, which is not the case at the inlining site. The compiler should check if it inlined a runtime function (or simply not inline runtime functions).

Additionally, it's not strictly an issue, but looking at the inline tree to determine safety is rather fragile. After inlining and optimizations it wouldn't be difficult to land on a PC that is reported as part of the outer function but it still technically within an unsafe region. More robust would be for the entire outer function to get marked as unsafe (or, again, don't inline runtime functions).

Second, despite the compiling runtime check, runtime functions still end up with safe points. e.g., I got crashes after preemption of runtime.typePointers.next. Looking at "preempt safety" from @randall77's github.com/randall77/dumpgc:

function: runtime.typePointers.next
        entry: 41a460
        argbytes: 40
        frame size: 40
                [41a460:41a460]: 0
                [41a461:41a467]: 8
                [41a468:41a581]: 40
                [41a582:41a582]: 8
                [41a583:41a583]: 0
                [41a584:41a594]: 40
                [41a595:41a595]: 8
                [41a596:41a596]: 0
                [41a597:41a5a6]: 40
                [41a5a7:41a5a7]: 8
                [41a5a8:41a5a8]: 0
        preempt safety:
                [41a460:41a46c]: safe
                [41a46d:41a5a8]: unsafe
        entry args@sp+0x8: 0001
        live pointer maps, args@sp+0x30 locals@sp+0x18:
                [41a460:41a4da]: args:0001 locals:0
                [41a4db:41a5a8]: args:0000 locals:1

Despite being in the runtime (and //go:nosplit!), the function prologue is still marked as unsafe. I think this because the compiler's safety decision is in SSA, but the prologue is in cmd/internal/obj, which is fairly far removed. obj should probably apply the same policy as SSA.

cc @cherrymui @mknyszek @golang/runtime

@prattmic prattmic added the NeedsFix The path to resolution is known, but the work has not been done. label Feb 28, 2025
@prattmic prattmic added this to the Backlog milestone Feb 28, 2025
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Feb 28, 2025
@gabyhelp gabyhelp added the Implementation Issues describing a semantics-preserving change to the Go implementation. label Feb 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. Implementation Issues describing a semantics-preserving change to the Go implementation. NeedsFix The path to resolution is known, but the work has not been done.
Projects
Development

No branches or pull requests

3 participants