Merge tag 'upstream-go1.23.4'

* tag 'upstream-go1.23.4': (23 commits)
  [release-branch.go1.23] go1.23.4
  [release-branch.go1.23] cmd/trace: also show end stack traces
  [release-branch.go1.23] runtime: reserve 4kB for system stack on windows-386
  [release-branch.go1.23] runtime: explicitly keep handle alive during getOrAddWeakHandle
  [release-branch.go1.23] runtime: prevent weak->strong conversions during mark termination
  [release-branch.go1.23] syscall: mark SyscallN as noescape
  [release-branch.go1.23]time: accept "+01" in TestLoadFixed on OpenBSD
  [release-branch.go1.23] cmd/compile: use a non-fragile test for "does f contain closure c?"
  [release-branch.go1.23] go1.23.3
  [release-branch.go1.23] runtime: reduce syscall.SyscallX stack usage
  [release-branch.go1.23] runtime: fix MutexProfile missing root frames
  [release-branch.go1.23] internal/poll: handle the special case of sendfile(2) sending the full chunk
  [release-branch.go1.23] internal/poll: keep copying after successful Sendfile return on BSD
  [release-branch.go1.23] cmd/link: generate Mach-O UUID when -B flag is specified
  [release-branch.go1.23] runtime: uphold goroutine profile invariants in coroswitch
  [release-branch.go1.23] runtime,time: use atomic.Int32 for isSending
  [release-branch.go1.23] runtime: don't frob isSending for tickers
  [release-branch.go1.23] runtime: fix GoroutineProfile stacks not getting null terminated
  [release-branch.go1.23] syscall: use SYS_EXIT_GROUP in CLONE_PIDFD feature check child
  [release-branch.go1.23] os: add clone(CLONE_PIDFD) check to pidfd feature check
  ...

Change-Id: Ia23a76cc6a8a7e809e2d249c6e48a39c2ce37115
diff --git a/METADATA b/METADATA
index 7b70a93..18ca642 100644
--- a/METADATA
+++ b/METADATA
@@ -10,7 +10,7 @@
     type: GIT
     value: "https://github.com/golang/go"
   }
-  version: "go1.23.2"
-  last_upgrade_date { year: 2024 month: 10 day: 7 }
+  version: "go1.23.4"
+  last_upgrade_date { year: 2025 month: 1 day: 7 }
   license_type: NOTICE
 }
diff --git a/VERSION b/VERSION
index 7c5b409..139c590 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
-go1.23.2
-time 2024-09-28T01:34:15Z
+go1.23.4
+time 2024-11-27T20:27:20Z
diff --git a/src/cmd/compile/internal/escape/solve.go b/src/cmd/compile/internal/escape/solve.go
index ef17bc4..32f5a77 100644
--- a/src/cmd/compile/internal/escape/solve.go
+++ b/src/cmd/compile/internal/escape/solve.go
@@ -318,9 +318,10 @@
 		return false
 	}
 
-	// Closures within function Foo are named like "Foo.funcN..." or "Foo-rangeN".
-	// TODO(mdempsky): Better way to recognize this.
-	fn := f.Sym().Name
-	cn := c.Sym().Name
-	return len(cn) > len(fn) && cn[:len(fn)] == fn && (cn[len(fn)] == '.' || cn[len(fn)] == '-')
+	for p := c.ClosureParent; p != nil; p = p.ClosureParent {
+		if p == f {
+			return true
+		}
+	}
+	return false
 }
diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go
index d0c8ee3..4fa9055 100644
--- a/src/cmd/compile/internal/ir/func.go
+++ b/src/cmd/compile/internal/ir/func.go
@@ -51,6 +51,8 @@
 // the generated ODCLFUNC, but there is no
 // pointer from the Func back to the OMETHVALUE.
 type Func struct {
+	// if you add or remove a field, don't forget to update sizeof_test.go
+
 	miniNode
 	Body Nodes
 
@@ -76,6 +78,9 @@
 	// Populated during walk.
 	Closures []*Func
 
+	// Parent of a closure
+	ClosureParent *Func
+
 	// Parents records the parent scope of each scope within a
 	// function. The root scope (0) has no parent, so the i'th
 	// scope's parent is stored at Parents[i-1].
@@ -512,6 +517,7 @@
 
 	fn.Nname.Defn = fn
 	pkg.Funcs = append(pkg.Funcs, fn)
+	fn.ClosureParent = outerfn
 
 	return fn
 }
diff --git a/src/cmd/compile/internal/ir/sizeof_test.go b/src/cmd/compile/internal/ir/sizeof_test.go
index 68d2865..6331cce 100644
--- a/src/cmd/compile/internal/ir/sizeof_test.go
+++ b/src/cmd/compile/internal/ir/sizeof_test.go
@@ -20,7 +20,7 @@
 		_32bit uintptr     // size on 32bit platforms
 		_64bit uintptr     // size on 64bit platforms
 	}{
-		{Func{}, 176, 296},
+		{Func{}, 180, 304},
 		{Name{}, 96, 168},
 	}
 
diff --git a/src/cmd/compile/internal/rangefunc/rangefunc_test.go b/src/cmd/compile/internal/rangefunc/rangefunc_test.go
index 97ab254..e488c3c 100644
--- a/src/cmd/compile/internal/rangefunc/rangefunc_test.go
+++ b/src/cmd/compile/internal/rangefunc/rangefunc_test.go
@@ -2099,3 +2099,27 @@
 		t.Errorf("Expected y=3, got y=%d\n", y)
 	}
 }
+
+func Bug70035(s1, s2, s3 []string) string {
+	var c1 string
+	for v1 := range slices.Values(s1) {
+		var c2 string
+		for v2 := range slices.Values(s2) {
+			var c3 string
+			for v3 := range slices.Values(s3) {
+				c3 = c3 + v3
+			}
+			c2 = c2 + v2 + c3
+		}
+		c1 = c1 + v1 + c2
+	}
+	return c1
+}
+
+func Test70035(t *testing.T) {
+	got := Bug70035([]string{"1", "2", "3"}, []string{"a", "b", "c"}, []string{"A", "B", "C"})
+	want := "1aABCbABCcABC2aABCbABCcABC3aABCbABCcABC"
+	if got != want {
+		t.Errorf("got %v, want %v", got, want)
+	}
+}
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 0d8455d..bc484de 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -805,13 +805,19 @@
 	return int(sh.Size)
 }
 
-func addbuildinfo(val string) {
+func addbuildinfo(ctxt *Link) {
+	val := *flagHostBuildid
 	if val == "gobuildid" {
 		buildID := *flagBuildid
 		if buildID == "" {
 			Exitf("-B gobuildid requires a Go build ID supplied via -buildid")
 		}
 
+		if ctxt.IsDarwin() {
+			buildinfo = uuidFromGoBuildId(buildID)
+			return
+		}
+
 		hashedBuildID := notsha256.Sum256([]byte(buildID))
 		buildinfo = hashedBuildID[:20]
 
@@ -821,11 +827,13 @@
 	if !strings.HasPrefix(val, "0x") {
 		Exitf("-B argument must start with 0x: %s", val)
 	}
-
 	ov := val
 	val = val[2:]
 
-	const maxLen = 32
+	maxLen := 32
+	if ctxt.IsDarwin() {
+		maxLen = 16
+	}
 	if hex.DecodedLen(len(val)) > maxLen {
 		Exitf("-B option too long (max %d digits): %s", maxLen, ov)
 	}
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 34624c2..c5a85f0 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -297,6 +297,8 @@
 	return &machohdr
 }
 
+// Create a new Mach-O load command. ndata is the number of 32-bit words for
+// the data (not including the load command header).
 func newMachoLoad(arch *sys.Arch, type_ uint32, ndata uint32) *MachoLoad {
 	if arch.PtrSize == 8 && (ndata&1 != 0) {
 		ndata++
@@ -849,6 +851,20 @@
 			}
 		}
 
+		if ctxt.IsInternal() && len(buildinfo) > 0 {
+			ml := newMachoLoad(ctxt.Arch, LC_UUID, 4)
+			// Mach-O UUID is 16 bytes
+			if len(buildinfo) < 16 {
+				buildinfo = append(buildinfo, make([]byte, 16)...)
+			}
+			// By default, buildinfo is already in UUIDv3 format
+			// (see uuidFromGoBuildId).
+			ml.data[0] = ctxt.Arch.ByteOrder.Uint32(buildinfo)
+			ml.data[1] = ctxt.Arch.ByteOrder.Uint32(buildinfo[4:])
+			ml.data[2] = ctxt.Arch.ByteOrder.Uint32(buildinfo[8:])
+			ml.data[3] = ctxt.Arch.ByteOrder.Uint32(buildinfo[12:])
+		}
+
 		if ctxt.IsInternal() && ctxt.NeedCodeSign() {
 			ml := newMachoLoad(ctxt.Arch, LC_CODE_SIGNATURE, 2)
 			ml.data[0] = uint32(codesigOff)
diff --git a/src/cmd/link/internal/ld/macho_update_uuid.go b/src/cmd/link/internal/ld/macho_update_uuid.go
index de27e65..40e0c11 100644
--- a/src/cmd/link/internal/ld/macho_update_uuid.go
+++ b/src/cmd/link/internal/ld/macho_update_uuid.go
@@ -42,7 +42,7 @@
 	// to use this UUID flavor than any of the others. This is similar
 	// to how other linkers handle this (for example this code in lld:
 	// https://github.com/llvm/llvm-project/blob/2a3a79ce4c2149d7787d56f9841b66cacc9061d0/lld/MachO/Writer.cpp#L524).
-	rv[6] &= 0xcf
+	rv[6] &= 0x0f
 	rv[6] |= 0x30
 	rv[8] &= 0x3f
 	rv[8] |= 0xc0
diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go
index 56e865d..12bc896 100644
--- a/src/cmd/link/internal/ld/main.go
+++ b/src/cmd/link/internal/ld/main.go
@@ -95,6 +95,7 @@
 	flagN             = flag.Bool("n", false, "no-op (deprecated)")
 	FlagS             = flag.Bool("s", false, "disable symbol table")
 	flag8             bool // use 64-bit addresses in symbol table
+	flagHostBuildid   = flag.String("B", "", "set ELF NT_GNU_BUILD_ID `note` or Mach-O UUID; use \"gobuildid\" to generate it from the Go build ID")
 	flagInterpreter   = flag.String("I", "", "use `linker` as ELF dynamic linker")
 	flagCheckLinkname = flag.Bool("checklinkname", true, "check linkname symbol references")
 	FlagDebugTramp    = flag.Int("debugtramp", 0, "debug trampolines")
@@ -196,7 +197,6 @@
 	flag.Var(&ctxt.LinkMode, "linkmode", "set link `mode`")
 	flag.Var(&ctxt.BuildMode, "buildmode", "set build `mode`")
 	flag.BoolVar(&ctxt.compressDWARF, "compressdwarf", true, "compress DWARF if possible")
-	objabi.Flagfn1("B", "add an ELF NT_GNU_BUILD_ID `note` when using ELF; use \"gobuildid\" to generate it from the Go build ID", addbuildinfo)
 	objabi.Flagfn1("L", "add specified `directory` to library path", func(a string) { Lflag(ctxt, a) })
 	objabi.AddVersionFlag() // -V
 	objabi.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
@@ -294,6 +294,10 @@
 		*flagBuildid = "go-openbsd"
 	}
 
+	if *flagHostBuildid != "" {
+		addbuildinfo(ctxt)
+	}
+
 	// enable benchmarking
 	var bench *benchmark.Metrics
 	if len(*benchmarkFlag) != 0 {
diff --git a/src/cmd/trace/gstate.go b/src/cmd/trace/gstate.go
index 638d492..4b380db 100644
--- a/src/cmd/trace/gstate.go
+++ b/src/cmd/trace/gstate.go
@@ -257,6 +257,10 @@
 	if gs.lastStopStack != trace.NoStack {
 		stk = ctx.Stack(viewerFrames(gs.lastStopStack))
 	}
+	var endStk int
+	if stack != trace.NoStack {
+		endStk = ctx.Stack(viewerFrames(stack))
+	}
 	// Check invariants.
 	if gs.startRunningTime == 0 {
 		panic("silently broken trace or generator invariant (startRunningTime != 0) not held")
@@ -270,6 +274,7 @@
 		Dur:      ts.Sub(gs.startRunningTime),
 		Resource: uint64(gs.executing),
 		Stack:    stk,
+		EndStack: endStk,
 	})
 
 	// Flush completed ranges.
diff --git a/src/internal/poll/sendfile_bsd.go b/src/internal/poll/sendfile_bsd.go
index 669df94..341e07c 100644
--- a/src/internal/poll/sendfile_bsd.go
+++ b/src/internal/poll/sendfile_bsd.go
@@ -32,28 +32,46 @@
 		if int64(n) > remain {
 			n = int(remain)
 		}
+		m := n
 		pos1 := pos
 		n, err = syscall.Sendfile(dst, src, &pos1, n)
 		if n > 0 {
 			pos += int64(n)
 			written += int64(n)
 			remain -= int64(n)
+			// (n, nil) indicates that sendfile(2) has transferred
+			// the exact number of bytes we requested, or some unretryable
+			// error have occurred with partial bytes sent. Either way, we
+			// don't need to go through the following logic to check EINTR
+			// or fell into dstFD.pd.waitWrite, just continue to send the
+			// next chunk or break the loop.
+			if n == m {
+				continue
+			} else if err != syscall.EAGAIN &&
+				err != syscall.EINTR &&
+				err != syscall.EBUSY {
+				// Particularly, EPIPE. Errors like that would normally lead
+				// the subsequent sendfile(2) call to (-1, EBADF).
+				break
+			}
+		} else if err != syscall.EAGAIN && err != syscall.EINTR {
+			// This includes syscall.ENOSYS (no kernel
+			// support) and syscall.EINVAL (fd types which
+			// don't implement sendfile), and other errors.
+			// We should end the loop when there is no error
+			// returned from sendfile(2) or it is not a retryable error.
+			break
 		}
 		if err == syscall.EINTR {
 			continue
 		}
-		// This includes syscall.ENOSYS (no kernel
-		// support) and syscall.EINVAL (fd types which
-		// don't implement sendfile), and other errors.
-		// We should end the loop when there is no error
-		// returned from sendfile(2) or it is not a retryable error.
-		if err != syscall.EAGAIN {
-			break
-		}
 		if err = dstFD.pd.waitWrite(dstFD.isFile); err != nil {
 			break
 		}
 	}
+	if err == syscall.EAGAIN {
+		err = nil
+	}
 	handled = written != 0 || (err != syscall.ENOSYS && err != syscall.EINVAL)
 	return
 }
diff --git a/src/internal/poll/sendfile_linux.go b/src/internal/poll/sendfile_linux.go
index d1c4d5c..1c4130d 100644
--- a/src/internal/poll/sendfile_linux.go
+++ b/src/internal/poll/sendfile_linux.go
@@ -50,6 +50,9 @@
 			break
 		}
 	}
+	if err == syscall.EAGAIN {
+		err = nil
+	}
 	handled = written != 0 || (err != syscall.ENOSYS && err != syscall.EINVAL)
 	return
 }
diff --git a/src/internal/poll/sendfile_solaris.go b/src/internal/poll/sendfile_solaris.go
index ec67583..b7c3f81 100644
--- a/src/internal/poll/sendfile_solaris.go
+++ b/src/internal/poll/sendfile_solaris.go
@@ -61,6 +61,9 @@
 			break
 		}
 	}
+	if err == syscall.EAGAIN {
+		err = nil
+	}
 	handled = written != 0 || (err != syscall.ENOSYS && err != syscall.EINVAL)
 	return
 }
diff --git a/src/os/copy_test.go b/src/os/copy_test.go
new file mode 100644
index 0000000..82346ca
--- /dev/null
+++ b/src/os/copy_test.go
@@ -0,0 +1,154 @@
+// Copyright 2024 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os_test
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"math/rand/v2"
+	"net"
+	"os"
+	"runtime"
+	"sync"
+	"testing"
+
+	"golang.org/x/net/nettest"
+)
+
+// Exercise sendfile/splice fast paths with a moderately large file.
+//
+// https://go.dev/issue/70000
+
+func TestLargeCopyViaNetwork(t *testing.T) {
+	const size = 10 * 1024 * 1024
+	dir := t.TempDir()
+
+	src, err := os.Create(dir + "/src")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer src.Close()
+	if _, err := io.CopyN(src, newRandReader(), size); err != nil {
+		t.Fatal(err)
+	}
+	if _, err := src.Seek(0, 0); err != nil {
+		t.Fatal(err)
+	}
+
+	dst, err := os.Create(dir + "/dst")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer dst.Close()
+
+	client, server := createSocketPair(t, "tcp")
+	var wg sync.WaitGroup
+	wg.Add(2)
+	go func() {
+		defer wg.Done()
+		if n, err := io.Copy(dst, server); n != size || err != nil {
+			t.Errorf("copy to destination = %v, %v; want %v, nil", n, err, size)
+		}
+	}()
+	go func() {
+		defer wg.Done()
+		defer client.Close()
+		if n, err := io.Copy(client, src); n != size || err != nil {
+			t.Errorf("copy from source = %v, %v; want %v, nil", n, err, size)
+		}
+	}()
+	wg.Wait()
+
+	if _, err := dst.Seek(0, 0); err != nil {
+		t.Fatal(err)
+	}
+	if err := compareReaders(dst, io.LimitReader(newRandReader(), size)); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func compareReaders(a, b io.Reader) error {
+	bufa := make([]byte, 4096)
+	bufb := make([]byte, 4096)
+	for {
+		na, erra := io.ReadFull(a, bufa)
+		if erra != nil && erra != io.EOF {
+			return erra
+		}
+		nb, errb := io.ReadFull(b, bufb)
+		if errb != nil && errb != io.EOF {
+			return errb
+		}
+		if !bytes.Equal(bufa[:na], bufb[:nb]) {
+			return errors.New("contents mismatch")
+		}
+		if erra == io.EOF && errb == io.EOF {
+			break
+		}
+	}
+	return nil
+}
+
+type randReader struct {
+	rand *rand.Rand
+}
+
+func newRandReader() *randReader {
+	return &randReader{rand.New(rand.NewPCG(0, 0))}
+}
+
+func (r *randReader) Read(p []byte) (int, error) {
+	var v uint64
+	var n int
+	for i := range p {
+		if n == 0 {
+			v = r.rand.Uint64()
+			n = 8
+		}
+		p[i] = byte(v & 0xff)
+		v >>= 8
+		n--
+	}
+	return len(p), nil
+}
+
+func createSocketPair(t *testing.T, proto string) (client, server net.Conn) {
+	t.Helper()
+	if !nettest.TestableNetwork(proto) {
+		t.Skipf("%s does not support %q", runtime.GOOS, proto)
+	}
+
+	ln, err := nettest.NewLocalListener(proto)
+	if err != nil {
+		t.Fatalf("NewLocalListener error: %v", err)
+	}
+	t.Cleanup(func() {
+		if ln != nil {
+			ln.Close()
+		}
+		if client != nil {
+			client.Close()
+		}
+		if server != nil {
+			server.Close()
+		}
+	})
+	ch := make(chan struct{})
+	go func() {
+		var err error
+		server, err = ln.Accept()
+		if err != nil {
+			t.Errorf("Accept new connection error: %v", err)
+		}
+		ch <- struct{}{}
+	}()
+	client, err = net.Dial(proto, ln.Addr().String())
+	<-ch
+	if err != nil {
+		t.Fatalf("Dial new connection error: %v", err)
+	}
+	return client, server
+}
diff --git a/src/os/pidfd_linux.go b/src/os/pidfd_linux.go
index 545cfe9..0bfef77 100644
--- a/src/os/pidfd_linux.go
+++ b/src/os/pidfd_linux.go
@@ -8,12 +8,17 @@
 //  v5.3: pidfd_open syscall, clone3 syscall;
 //  v5.4: P_PIDFD idtype support for waitid syscall;
 //  v5.6: pidfd_getfd syscall.
+//
+// N.B. Alternative Linux implementations may not follow this ordering. e.g.,
+// QEMU user mode 7.2 added pidfd_open, but CLONE_PIDFD was not added until
+// 8.0.
 
 package os
 
 import (
 	"errors"
 	"internal/syscall/unix"
+	"runtime"
 	"sync"
 	"syscall"
 	"unsafe"
@@ -139,14 +144,21 @@
 
 var checkPidfdOnce = sync.OnceValue(checkPidfd)
 
-// checkPidfd checks whether all required pidfd-related syscalls work.
-// This consists of pidfd_open and pidfd_send_signal syscalls, and waitid
-// syscall with idtype of P_PIDFD.
+// checkPidfd checks whether all required pidfd-related syscalls work. This
+// consists of pidfd_open and pidfd_send_signal syscalls, waitid syscall with
+// idtype of P_PIDFD, and clone(CLONE_PIDFD).
 //
 // Reasons for non-working pidfd syscalls include an older kernel and an
 // execution environment in which the above system calls are restricted by
 // seccomp or a similar technology.
 func checkPidfd() error {
+	// In Android version < 12, pidfd-related system calls are not allowed
+	// by seccomp and trigger the SIGSYS signal. See issue #69065.
+	if runtime.GOOS == "android" {
+		ignoreSIGSYS()
+		defer restoreSIGSYS()
+	}
+
 	// Get a pidfd of the current process (opening of "/proc/self" won't
 	// work for waitid).
 	fd, err := unix.PidFDOpen(syscall.Getpid(), 0)
@@ -172,5 +184,27 @@
 		return NewSyscallError("pidfd_send_signal", err)
 	}
 
+	// Verify that clone(CLONE_PIDFD) works.
+	//
+	// This shouldn't be necessary since pidfd_open was added in Linux 5.3,
+	// after CLONE_PIDFD in Linux 5.2, but some alternative Linux
+	// implementations may not adhere to this ordering.
+	if err := checkClonePidfd(); err != nil {
+		return err
+	}
+
 	return nil
 }
+
+// Provided by syscall.
+//
+//go:linkname checkClonePidfd
+func checkClonePidfd() error
+
+// Provided by runtime.
+//
+//go:linkname ignoreSIGSYS
+func ignoreSIGSYS()
+
+//go:linkname restoreSIGSYS
+func restoreSIGSYS()
diff --git a/src/os/readfrom_linux_test.go b/src/os/readfrom_linux_test.go
index 8dcb9cb..4586747 100644
--- a/src/os/readfrom_linux_test.go
+++ b/src/os/readfrom_linux_test.go
@@ -14,15 +14,12 @@
 	"net"
 	. "os"
 	"path/filepath"
-	"runtime"
 	"strconv"
 	"strings"
 	"sync"
 	"syscall"
 	"testing"
 	"time"
-
-	"golang.org/x/net/nettest"
 )
 
 func TestCopyFileRange(t *testing.T) {
@@ -784,41 +781,3 @@
 		t.Fatalf("server Control error: %v", err)
 	}
 }
-
-func createSocketPair(t *testing.T, proto string) (client, server net.Conn) {
-	t.Helper()
-	if !nettest.TestableNetwork(proto) {
-		t.Skipf("%s does not support %q", runtime.GOOS, proto)
-	}
-
-	ln, err := nettest.NewLocalListener(proto)
-	if err != nil {
-		t.Fatalf("NewLocalListener error: %v", err)
-	}
-	t.Cleanup(func() {
-		if ln != nil {
-			ln.Close()
-		}
-		if client != nil {
-			client.Close()
-		}
-		if server != nil {
-			server.Close()
-		}
-	})
-	ch := make(chan struct{})
-	go func() {
-		var err error
-		server, err = ln.Accept()
-		if err != nil {
-			t.Errorf("Accept new connection error: %v", err)
-		}
-		ch <- struct{}{}
-	}()
-	client, err = net.Dial(proto, ln.Addr().String())
-	<-ch
-	if err != nil {
-		t.Fatalf("Dial new connection error: %v", err)
-	}
-	return client, server
-}
diff --git a/src/runtime/coro.go b/src/runtime/coro.go
index 30ada45..d93817f 100644
--- a/src/runtime/coro.go
+++ b/src/runtime/coro.go
@@ -208,6 +208,18 @@
 	// directly if possible.
 	setGNoWB(&mp.curg, gnext)
 	setMNoWB(&gnext.m, mp)
+
+	// Synchronize with any out-standing goroutine profile. We're about to start
+	// executing, and an invariant of the profiler is that we tryRecordGoroutineProfile
+	// whenever a goroutine is about to start running.
+	//
+	// N.B. We must do this before transitioning to _Grunning but after installing gnext
+	// in curg, so that we have a valid curg for allocation (tryRecordGoroutineProfile
+	// may allocate).
+	if goroutineProfile.active {
+		tryRecordGoroutineProfile(gnext, nil, osyield)
+	}
+
 	if !gnext.atomicstatus.CompareAndSwap(_Gwaiting, _Grunning) {
 		// The CAS failed: use casgstatus, which will take care of
 		// coordinating with the garbage collector about the state change.
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index d55da10..4502fa7 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -1886,3 +1886,30 @@
 func (m *TraceMap) Reset() {
 	m.traceMap.reset()
 }
+
+func SetSpinInGCMarkDone(spin bool) {
+	gcDebugMarkDone.spinAfterRaggedBarrier.Store(spin)
+}
+
+func GCMarkDoneRestarted() bool {
+	// Only read this outside of the GC. If we're running during a GC, just report false.
+	mp := acquirem()
+	if gcphase != _GCoff {
+		releasem(mp)
+		return false
+	}
+	restarted := gcDebugMarkDone.restartedDueTo27993
+	releasem(mp)
+	return restarted
+}
+
+func GCMarkDoneResetRestartFlag() {
+	mp := acquirem()
+	for gcphase != _GCoff {
+		releasem(mp)
+		Gosched()
+		mp = acquirem()
+	}
+	gcDebugMarkDone.restartedDueTo27993 = false
+	releasem(mp)
+}
diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go
index 908f632..4b92b20 100644
--- a/src/runtime/gc_test.go
+++ b/src/runtime/gc_test.go
@@ -6,6 +6,8 @@
 
 import (
 	"fmt"
+	"internal/testenv"
+	"internal/weak"
 	"math/bits"
 	"math/rand"
 	"os"
@@ -787,3 +789,78 @@
 func TestMyGenericFunc(t *testing.T) {
 	runtime.MyGenericFunc[int]()
 }
+
+func TestWeakToStrongMarkTermination(t *testing.T) {
+	testenv.MustHaveParallelism(t)
+
+	type T struct {
+		a *int
+		b int
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+	defer debug.SetGCPercent(debug.SetGCPercent(-1))
+	w := make([]weak.Pointer[T], 2048)
+
+	// Make sure there's no out-standing GC from a previous test.
+	runtime.GC()
+
+	// Create many objects with a weak pointers to them.
+	for i := range w {
+		x := new(T)
+		x.a = new(int)
+		w[i] = weak.Make(x)
+	}
+
+	// Reset the restart flag.
+	runtime.GCMarkDoneResetRestartFlag()
+
+	// Prevent mark termination from completing.
+	runtime.SetSpinInGCMarkDone(true)
+
+	// Start a GC, and wait a little bit to get something spinning in mark termination.
+	// Simultaneously, fire off another goroutine to disable spinning. If everything's
+	// working correctly, then weak.Strong will block, so we need to make sure something
+	// prevents the GC from continuing to spin.
+	done := make(chan struct{})
+	go func() {
+		runtime.GC()
+		done <- struct{}{}
+	}()
+	go func() {
+		time.Sleep(100 * time.Millisecond)
+
+		// Let mark termination continue.
+		runtime.SetSpinInGCMarkDone(false)
+	}()
+	time.Sleep(10 * time.Millisecond)
+
+	// Perform many weak->strong conversions in the critical window.
+	var wg sync.WaitGroup
+	for _, wp := range w {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			wp.Strong()
+		}()
+	}
+
+	// Make sure the GC completes.
+	<-done
+
+	// Make sure all the weak->strong conversions finish.
+	wg.Wait()
+
+	// The bug is triggered if there's still mark work after gcMarkDone stops the world.
+	//
+	// This can manifest in one of two ways today:
+	// - An exceedingly rare crash in mark termination.
+	// - gcMarkDone restarts, as if issue #27993 is at play.
+	//
+	// Check for the latter. This is a fairly controlled environment, so #27993 is very
+	// unlikely to happen (it's already rare to begin with) but we'll always _appear_ to
+	// trigger the same bug if weak->strong conversions aren't properly coordinated with
+	// mark termination.
+	if runtime.GCMarkDoneRestarted() {
+		t.Errorf("gcMarkDone restarted")
+	}
+}
diff --git a/src/runtime/lockrank.go b/src/runtime/lockrank.go
index 432ace7..3738383 100644
--- a/src/runtime/lockrank.go
+++ b/src/runtime/lockrank.go
@@ -17,6 +17,7 @@
 	lockRankDefer
 	lockRankSweepWaiters
 	lockRankAssistQueue
+	lockRankStrongFromWeakQueue
 	lockRankSweep
 	lockRankTestR
 	lockRankTestW
@@ -84,64 +85,65 @@
 
 // lockNames gives the names associated with each of the above ranks.
 var lockNames = []string{
-	lockRankSysmon:          "sysmon",
-	lockRankScavenge:        "scavenge",
-	lockRankForcegc:         "forcegc",
-	lockRankDefer:           "defer",
-	lockRankSweepWaiters:    "sweepWaiters",
-	lockRankAssistQueue:     "assistQueue",
-	lockRankSweep:           "sweep",
-	lockRankTestR:           "testR",
-	lockRankTestW:           "testW",
-	lockRankTimerSend:       "timerSend",
-	lockRankAllocmW:         "allocmW",
-	lockRankExecW:           "execW",
-	lockRankCpuprof:         "cpuprof",
-	lockRankPollCache:       "pollCache",
-	lockRankPollDesc:        "pollDesc",
-	lockRankWakeableSleep:   "wakeableSleep",
-	lockRankHchan:           "hchan",
-	lockRankAllocmR:         "allocmR",
-	lockRankExecR:           "execR",
-	lockRankSched:           "sched",
-	lockRankAllg:            "allg",
-	lockRankAllp:            "allp",
-	lockRankNotifyList:      "notifyList",
-	lockRankSudog:           "sudog",
-	lockRankTimers:          "timers",
-	lockRankTimer:           "timer",
-	lockRankNetpollInit:     "netpollInit",
-	lockRankRoot:            "root",
-	lockRankItab:            "itab",
-	lockRankReflectOffs:     "reflectOffs",
-	lockRankUserArenaState:  "userArenaState",
-	lockRankTraceBuf:        "traceBuf",
-	lockRankTraceStrings:    "traceStrings",
-	lockRankFin:             "fin",
-	lockRankSpanSetSpine:    "spanSetSpine",
-	lockRankMspanSpecial:    "mspanSpecial",
-	lockRankTraceTypeTab:    "traceTypeTab",
-	lockRankGcBitsArenas:    "gcBitsArenas",
-	lockRankProfInsert:      "profInsert",
-	lockRankProfBlock:       "profBlock",
-	lockRankProfMemActive:   "profMemActive",
-	lockRankProfMemFuture:   "profMemFuture",
-	lockRankGscan:           "gscan",
-	lockRankStackpool:       "stackpool",
-	lockRankStackLarge:      "stackLarge",
-	lockRankHchanLeaf:       "hchanLeaf",
-	lockRankWbufSpans:       "wbufSpans",
-	lockRankMheap:           "mheap",
-	lockRankMheapSpecial:    "mheapSpecial",
-	lockRankGlobalAlloc:     "globalAlloc",
-	lockRankTrace:           "trace",
-	lockRankTraceStackTab:   "traceStackTab",
-	lockRankPanic:           "panic",
-	lockRankDeadlock:        "deadlock",
-	lockRankRaceFini:        "raceFini",
-	lockRankAllocmRInternal: "allocmRInternal",
-	lockRankExecRInternal:   "execRInternal",
-	lockRankTestRInternal:   "testRInternal",
+	lockRankSysmon:              "sysmon",
+	lockRankScavenge:            "scavenge",
+	lockRankForcegc:             "forcegc",
+	lockRankDefer:               "defer",
+	lockRankSweepWaiters:        "sweepWaiters",
+	lockRankAssistQueue:         "assistQueue",
+	lockRankStrongFromWeakQueue: "strongFromWeakQueue",
+	lockRankSweep:               "sweep",
+	lockRankTestR:               "testR",
+	lockRankTestW:               "testW",
+	lockRankTimerSend:           "timerSend",
+	lockRankAllocmW:             "allocmW",
+	lockRankExecW:               "execW",
+	lockRankCpuprof:             "cpuprof",
+	lockRankPollCache:           "pollCache",
+	lockRankPollDesc:            "pollDesc",
+	lockRankWakeableSleep:       "wakeableSleep",
+	lockRankHchan:               "hchan",
+	lockRankAllocmR:             "allocmR",
+	lockRankExecR:               "execR",
+	lockRankSched:               "sched",
+	lockRankAllg:                "allg",
+	lockRankAllp:                "allp",
+	lockRankNotifyList:          "notifyList",
+	lockRankSudog:               "sudog",
+	lockRankTimers:              "timers",
+	lockRankTimer:               "timer",
+	lockRankNetpollInit:         "netpollInit",
+	lockRankRoot:                "root",
+	lockRankItab:                "itab",
+	lockRankReflectOffs:         "reflectOffs",
+	lockRankUserArenaState:      "userArenaState",
+	lockRankTraceBuf:            "traceBuf",
+	lockRankTraceStrings:        "traceStrings",
+	lockRankFin:                 "fin",
+	lockRankSpanSetSpine:        "spanSetSpine",
+	lockRankMspanSpecial:        "mspanSpecial",
+	lockRankTraceTypeTab:        "traceTypeTab",
+	lockRankGcBitsArenas:        "gcBitsArenas",
+	lockRankProfInsert:          "profInsert",
+	lockRankProfBlock:           "profBlock",
+	lockRankProfMemActive:       "profMemActive",
+	lockRankProfMemFuture:       "profMemFuture",
+	lockRankGscan:               "gscan",
+	lockRankStackpool:           "stackpool",
+	lockRankStackLarge:          "stackLarge",
+	lockRankHchanLeaf:           "hchanLeaf",
+	lockRankWbufSpans:           "wbufSpans",
+	lockRankMheap:               "mheap",
+	lockRankMheapSpecial:        "mheapSpecial",
+	lockRankGlobalAlloc:         "globalAlloc",
+	lockRankTrace:               "trace",
+	lockRankTraceStackTab:       "traceStackTab",
+	lockRankPanic:               "panic",
+	lockRankDeadlock:            "deadlock",
+	lockRankRaceFini:            "raceFini",
+	lockRankAllocmRInternal:     "allocmRInternal",
+	lockRankExecRInternal:       "execRInternal",
+	lockRankTestRInternal:       "testRInternal",
 }
 
 func (rank lockRank) String() string {
@@ -163,62 +165,63 @@
 //
 // Lock ranks that allow self-cycles list themselves.
 var lockPartialOrder [][]lockRank = [][]lockRank{
-	lockRankSysmon:          {},
-	lockRankScavenge:        {lockRankSysmon},
-	lockRankForcegc:         {lockRankSysmon},
-	lockRankDefer:           {},
-	lockRankSweepWaiters:    {},
-	lockRankAssistQueue:     {},
-	lockRankSweep:           {},
-	lockRankTestR:           {},
-	lockRankTestW:           {},
-	lockRankTimerSend:       {},
-	lockRankAllocmW:         {},
-	lockRankExecW:           {},
-	lockRankCpuprof:         {},
-	lockRankPollCache:       {},
-	lockRankPollDesc:        {},
-	lockRankWakeableSleep:   {},
-	lockRankHchan:           {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankWakeableSleep, lockRankHchan},
-	lockRankAllocmR:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
-	lockRankExecR:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
-	lockRankSched:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR},
-	lockRankAllg:            {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
-	lockRankAllp:            {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
-	lockRankNotifyList:      {},
-	lockRankSudog:           {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankWakeableSleep, lockRankHchan, lockRankNotifyList},
-	lockRankTimers:          {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankTimers},
-	lockRankTimer:           {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankTimers},
-	lockRankNetpollInit:     {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankTimers, lockRankTimer},
-	lockRankRoot:            {},
-	lockRankItab:            {},
-	lockRankReflectOffs:     {lockRankItab},
-	lockRankUserArenaState:  {},
-	lockRankTraceBuf:        {lockRankSysmon, lockRankScavenge},
-	lockRankTraceStrings:    {lockRankSysmon, lockRankScavenge, lockRankTraceBuf},
-	lockRankFin:             {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankSpanSetSpine:    {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankMspanSpecial:    {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankTraceTypeTab:    {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankGcBitsArenas:    {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial},
-	lockRankProfInsert:      {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankProfBlock:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankProfMemActive:   {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
-	lockRankProfMemFuture:   {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankProfMemActive},
-	lockRankGscan:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture},
-	lockRankStackpool:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
-	lockRankStackLarge:      {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
-	lockRankHchanLeaf:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankHchanLeaf},
-	lockRankWbufSpans:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
-	lockRankMheap:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans},
-	lockRankMheapSpecial:    {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
-	lockRankGlobalAlloc:     {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankMheapSpecial},
-	lockRankTrace:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
-	lockRankTraceStackTab:   {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankTrace},
-	lockRankPanic:           {},
-	lockRankDeadlock:        {lockRankPanic, lockRankDeadlock},
-	lockRankRaceFini:        {lockRankPanic},
-	lockRankAllocmRInternal: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankAllocmW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR},
-	lockRankExecRInternal:   {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankExecR},
-	lockRankTestRInternal:   {lockRankTestR, lockRankTestW},
+	lockRankSysmon:              {},
+	lockRankScavenge:            {lockRankSysmon},
+	lockRankForcegc:             {lockRankSysmon},
+	lockRankDefer:               {},
+	lockRankSweepWaiters:        {},
+	lockRankAssistQueue:         {},
+	lockRankStrongFromWeakQueue: {},
+	lockRankSweep:               {},
+	lockRankTestR:               {},
+	lockRankTestW:               {},
+	lockRankTimerSend:           {},
+	lockRankAllocmW:             {},
+	lockRankExecW:               {},
+	lockRankCpuprof:             {},
+	lockRankPollCache:           {},
+	lockRankPollDesc:            {},
+	lockRankWakeableSleep:       {},
+	lockRankHchan:               {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankWakeableSleep, lockRankHchan},
+	lockRankAllocmR:             {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
+	lockRankExecR:               {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
+	lockRankSched:               {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR},
+	lockRankAllg:                {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
+	lockRankAllp:                {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
+	lockRankNotifyList:          {},
+	lockRankSudog:               {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankWakeableSleep, lockRankHchan, lockRankNotifyList},
+	lockRankTimers:              {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankTimers},
+	lockRankTimer:               {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankTimers},
+	lockRankNetpollInit:         {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankTimers, lockRankTimer},
+	lockRankRoot:                {},
+	lockRankItab:                {},
+	lockRankReflectOffs:         {lockRankItab},
+	lockRankUserArenaState:      {},
+	lockRankTraceBuf:            {lockRankSysmon, lockRankScavenge},
+	lockRankTraceStrings:        {lockRankSysmon, lockRankScavenge, lockRankTraceBuf},
+	lockRankFin:                 {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankSpanSetSpine:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankMspanSpecial:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankTraceTypeTab:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankGcBitsArenas:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial},
+	lockRankProfInsert:          {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankProfBlock:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankProfMemActive:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+	lockRankProfMemFuture:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankProfMemActive},
+	lockRankGscan:               {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture},
+	lockRankStackpool:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
+	lockRankStackLarge:          {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
+	lockRankHchanLeaf:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankHchanLeaf},
+	lockRankWbufSpans:           {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
+	lockRankMheap:               {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans},
+	lockRankMheapSpecial:        {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
+	lockRankGlobalAlloc:         {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankMheapSpecial},
+	lockRankTrace:               {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
+	lockRankTraceStackTab:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankTrace},
+	lockRankPanic:               {},
+	lockRankDeadlock:            {lockRankPanic, lockRankDeadlock},
+	lockRankRaceFini:            {lockRankPanic},
+	lockRankAllocmRInternal:     {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankAllocmW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR},
+	lockRankExecRInternal:       {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankExecR},
+	lockRankTestRInternal:       {lockRankTestR, lockRankTestW},
 }
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 2654c69..f72edc2 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -190,6 +190,7 @@
 	work.markDoneSema = 1
 	lockInit(&work.sweepWaiters.lock, lockRankSweepWaiters)
 	lockInit(&work.assistQueue.lock, lockRankAssistQueue)
+	lockInit(&work.strongFromWeak.lock, lockRankStrongFromWeakQueue)
 	lockInit(&work.wbufSpans.lock, lockRankWbufSpans)
 }
 
@@ -418,6 +419,26 @@
 		list gList
 	}
 
+	// strongFromWeak controls how the GC interacts with weak->strong
+	// pointer conversions.
+	strongFromWeak struct {
+		// block is a flag set during mark termination that prevents
+		// new weak->strong conversions from executing by blocking the
+		// goroutine and enqueuing it onto q.
+		//
+		// Mutated only by one goroutine at a time in gcMarkDone,
+		// with globally-synchronizing events like forEachP and
+		// stopTheWorld.
+		block bool
+
+		// q is a queue of goroutines that attempted to perform a
+		// weak->strong conversion during mark termination.
+		//
+		// Protected by lock.
+		lock mutex
+		q    gQueue
+	}
+
 	// cycles is the number of completed GC cycles, where a GC
 	// cycle is sweep termination, mark, mark termination, and
 	// sweep. This differs from memstats.numgc, which is
@@ -800,6 +821,19 @@
 // This is protected by markDoneSema.
 var gcMarkDoneFlushed uint32
 
+// gcDebugMarkDone contains fields used to debug/test mark termination.
+var gcDebugMarkDone struct {
+	// spinAfterRaggedBarrier forces gcMarkDone to spin after it executes
+	// the ragged barrier.
+	spinAfterRaggedBarrier atomic.Bool
+
+	// restartedDueTo27993 indicates that we restarted mark termination
+	// due to the bug described in issue #27993.
+	//
+	// Protected by worldsema.
+	restartedDueTo27993 bool
+}
+
 // gcMarkDone transitions the GC from mark to mark termination if all
 // reachable objects have been marked (that is, there are no grey
 // objects and can be no more in the future). Otherwise, it flushes
@@ -842,6 +876,10 @@
 	// stop the world later, so acquire worldsema now.
 	semacquire(&worldsema)
 
+	// Prevent weak->strong conversions from generating additional
+	// GC work. forEachP will guarantee that it is observed globally.
+	work.strongFromWeak.block = true
+
 	// Flush all local buffers and collect flushedWork flags.
 	gcMarkDoneFlushed = 0
 	forEachP(waitReasonGCMarkTermination, func(pp *p) {
@@ -872,6 +910,10 @@
 		goto top
 	}
 
+	// For debugging/testing.
+	for gcDebugMarkDone.spinAfterRaggedBarrier.Load() {
+	}
+
 	// There was no global work, no local work, and no Ps
 	// communicated work since we took markDoneSema. Therefore
 	// there are no grey objects and no more objects can be
@@ -910,6 +952,8 @@
 		}
 	})
 	if restart {
+		gcDebugMarkDone.restartedDueTo27993 = true
+
 		getg().m.preemptoff = ""
 		systemstack(func() {
 			// Accumulate the time we were stopped before we had to start again.
@@ -936,6 +980,11 @@
 	// start the world again.
 	gcWakeAllAssists()
 
+	// Wake all blocked weak->strong conversions. These will run
+	// when we start the world again.
+	work.strongFromWeak.block = false
+	gcWakeAllStrongFromWeak()
+
 	// Likewise, release the transition lock. Blocked
 	// workers and assists will run when we start the
 	// world again.
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index a910553..bfca2d1 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -2049,8 +2049,19 @@
 func internal_weak_runtime_makeStrongFromWeak(u unsafe.Pointer) unsafe.Pointer {
 	handle := (*atomic.Uintptr)(u)
 
-	// Prevent preemption. We want to make sure that another GC cycle can't start.
+	// Prevent preemption. We want to make sure that another GC cycle can't start
+	// and that work.strongFromWeak.block can't change out from under us.
 	mp := acquirem()
+
+	// Yield to the GC if necessary.
+	if work.strongFromWeak.block {
+		releasem(mp)
+
+		// Try to park and wait for mark termination.
+		// N.B. gcParkStrongFromWeak calls acquirem before returning.
+		mp = gcParkStrongFromWeak()
+	}
+
 	p := handle.Load()
 	if p == 0 {
 		releasem(mp)
@@ -2092,6 +2103,41 @@
 	return ptr
 }
 
+// gcParkStrongFromWeak puts the current goroutine on the weak->strong queue and parks.
+func gcParkStrongFromWeak() *m {
+	// Prevent preemption as we check strongFromWeak, so it can't change out from under us.
+	mp := acquirem()
+
+	for work.strongFromWeak.block {
+		lock(&work.strongFromWeak.lock)
+		releasem(mp) // N.B. Holding the lock prevents preemption.
+
+		// Queue ourselves up.
+		work.strongFromWeak.q.pushBack(getg())
+
+		// Park.
+		goparkunlock(&work.strongFromWeak.lock, waitReasonGCWeakToStrongWait, traceBlockGCWeakToStrongWait, 2)
+
+		// Re-acquire the current M since we're going to check the condition again.
+		mp = acquirem()
+
+		// Re-check condition. We may have awoken in the next GC's mark termination phase.
+	}
+	return mp
+}
+
+// gcWakeAllStrongFromWeak wakes all currently blocked weak->strong
+// conversions. This is used at the end of a GC cycle.
+//
+// work.strongFromWeak.block must be false to prevent woken goroutines
+// from immediately going back to sleep.
+func gcWakeAllStrongFromWeak() {
+	lock(&work.strongFromWeak.lock)
+	list := work.strongFromWeak.q.popList()
+	injectglist(&list)
+	unlock(&work.strongFromWeak.lock)
+}
+
 // Retrieves or creates a weak pointer handle for the object p.
 func getOrAddWeakHandle(p unsafe.Pointer) *atomic.Uintptr {
 	// First try to retrieve without allocating.
@@ -2126,8 +2172,14 @@
 
 		// Keep p alive for the duration of the function to ensure
 		// that it cannot die while we're trying to do this.
+		//
+		// Same for handle, which is only stored in the special.
+		// There's a window where it might die if we don't keep it
+		// alive explicitly. Returning it here is probably good enough,
+		// but let's be defensive and explicit. See #70455.
 		KeepAlive(p)
-		return s.handle
+		KeepAlive(handle)
+		return handle
 	}
 
 	// There was an existing handle. Free the special
@@ -2147,7 +2199,10 @@
 
 	// Keep p alive for the duration of the function to ensure
 	// that it cannot die while we're trying to do this.
+	//
+	// Same for handle, just to be defensive.
 	KeepAlive(p)
+	KeepAlive(handle)
 	return handle
 }
 
diff --git a/src/runtime/mklockrank.go b/src/runtime/mklockrank.go
index 1239b4a..3391afc 100644
--- a/src/runtime/mklockrank.go
+++ b/src/runtime/mklockrank.go
@@ -50,6 +50,7 @@
 NONE <
   sweepWaiters,
   assistQueue,
+  strongFromWeakQueue,
   sweep;
 
 # Test only
@@ -66,6 +67,7 @@
   hchan,
   pollDesc, # pollDesc can interact with timers, which can lock sched.
   scavenge,
+  strongFromWeakQueue,
   sweep,
   sweepWaiters,
   testR,
diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go
index 0062747..ee3e59a 100644
--- a/src/runtime/mprof.go
+++ b/src/runtime/mprof.go
@@ -1136,11 +1136,12 @@
 	for i := range p {
 		cf := CallersFrames(p[i].Stack())
 		j := 0
-		for ; j < len(expandedStack); j++ {
+		for j < len(expandedStack) {
 			f, more := cf.Next()
 			// f.PC is a "call PC", but later consumers will expect
 			// "return PCs"
 			expandedStack[j] = f.PC + 1
+			j++
 			if !more {
 				break
 			}
@@ -1270,7 +1271,8 @@
 // of calling ThreadCreateProfile directly.
 func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
 	return threadCreateProfileInternal(len(p), func(r profilerecord.StackRecord) {
-		copy(p[0].Stack0[:], r.Stack)
+		i := copy(p[0].Stack0[:], r.Stack)
+		clear(p[0].Stack0[i:])
 		p = p[1:]
 	})
 }
@@ -1649,7 +1651,8 @@
 		return
 	}
 	for i, mr := range records[0:n] {
-		copy(p[i].Stack0[:], mr.Stack)
+		l := copy(p[i].Stack0[:], mr.Stack)
+		clear(p[i].Stack0[l:])
 	}
 	return
 }
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index 6ce656c..e80d390 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -879,8 +879,9 @@
 }
 
 const (
-	_SI_USER  = 0
-	_SI_TKILL = -6
+	_SI_USER     = 0
+	_SI_TKILL    = -6
+	_SYS_SECCOMP = 1
 )
 
 // sigFromUser reports whether the signal was sent because of a call
@@ -892,6 +893,14 @@
 	return code == _SI_USER || code == _SI_TKILL
 }
 
+// sigFromSeccomp reports whether the signal was sent from seccomp.
+//
+//go:nosplit
+func (c *sigctxt) sigFromSeccomp() bool {
+	code := int32(c.sigcode())
+	return code == _SYS_SECCOMP
+}
+
 //go:nosplit
 func mprotect(addr unsafe.Pointer, n uintptr, prot int32) (ret int32, errno int32) {
 	r, _, err := syscall.Syscall6(syscall.SYS_MPROTECT, uintptr(addr), n, uintptr(prot), 0, 0, 0)
diff --git a/src/runtime/os_unix_nonlinux.go b/src/runtime/os_unix_nonlinux.go
index b98753b..0e8b61c 100644
--- a/src/runtime/os_unix_nonlinux.go
+++ b/src/runtime/os_unix_nonlinux.go
@@ -13,3 +13,10 @@
 func (c *sigctxt) sigFromUser() bool {
 	return c.sigcode() == _SI_USER
 }
+
+// sigFromSeccomp reports whether the signal was sent from seccomp.
+//
+//go:nosplit
+func (c *sigctxt) sigFromSeccomp() bool {
+	return false
+}
diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go
index 391588d..ef373b3 100644
--- a/src/runtime/pprof/mprof_test.go
+++ b/src/runtime/pprof/mprof_test.go
@@ -145,7 +145,7 @@
 		}
 		t.Logf("Profile = %v", p)
 
-		stks := stacks(p)
+		stks := profileStacks(p)
 		for _, test := range tests {
 			if !containsStack(stks, test.stk) {
 				t.Fatalf("No matching stack entry for %q\n\nProfile:\n%v\n", test.stk, p)
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 30ef50b..da4ad17 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -15,6 +15,7 @@
 	"internal/syscall/unix"
 	"internal/testenv"
 	"io"
+	"iter"
 	"math"
 	"math/big"
 	"os"
@@ -981,7 +982,7 @@
 			t.Fatalf("invalid profile: %v", err)
 		}
 
-		stks := stacks(p)
+		stks := profileStacks(p)
 		for _, test := range tests {
 			if !containsStack(stks, test.stk) {
 				t.Errorf("No matching stack entry for %v, want %+v", test.name, test.stk)
@@ -991,7 +992,7 @@
 
 }
 
-func stacks(p *profile.Profile) (res [][]string) {
+func profileStacks(p *profile.Profile) (res [][]string) {
 	for _, s := range p.Sample {
 		var stk []string
 		for _, l := range s.Location {
@@ -1004,6 +1005,22 @@
 	return res
 }
 
+func blockRecordStacks(records []runtime.BlockProfileRecord) (res [][]string) {
+	for _, record := range records {
+		frames := runtime.CallersFrames(record.Stack())
+		var stk []string
+		for {
+			frame, more := frames.Next()
+			stk = append(stk, frame.Function)
+			if !more {
+				break
+			}
+		}
+		res = append(res, stk)
+	}
+	return res
+}
+
 func containsStack(got [][]string, want []string) bool {
 	for _, stk := range got {
 		if len(stk) < len(want) {
@@ -1288,7 +1305,7 @@
 			t.Fatalf("invalid profile: %v", err)
 		}
 
-		stks := stacks(p)
+		stks := profileStacks(p)
 		for _, want := range [][]string{
 			{"sync.(*Mutex).Unlock", "runtime/pprof.blockMutexN.func1"},
 		} {
@@ -1328,6 +1345,28 @@
 			t.Fatalf("profile samples total %v, want within range [%v, %v] (target: %v)", d, lo, hi, N*D)
 		}
 	})
+
+	t.Run("records", func(t *testing.T) {
+		// Record a mutex profile using the structured record API.
+		var records []runtime.BlockProfileRecord
+		for {
+			n, ok := runtime.MutexProfile(records)
+			if ok {
+				records = records[:n]
+				break
+			}
+			records = make([]runtime.BlockProfileRecord, n*2)
+		}
+
+		// Check that we see the same stack trace as the proto profile. For
+		// historical reason we expect a runtime.goexit root frame here that is
+		// omitted in the proto profile.
+		stks := blockRecordStacks(records)
+		want := []string{"sync.(*Mutex).Unlock", "runtime/pprof.blockMutexN.func1", "runtime.goexit"}
+		if !containsStack(stks, want) {
+			t.Errorf("No matching stack entry for %+v", want)
+		}
+	})
 }
 
 func TestMutexProfileRateAdjust(t *testing.T) {
@@ -1754,6 +1793,50 @@
 	}
 }
 
+// Regression test for #69998.
+func TestGoroutineProfileCoro(t *testing.T) {
+	testenv.MustHaveParallelism(t)
+
+	goroutineProf := Lookup("goroutine")
+
+	// Set up a goroutine to just create and run coroutine goroutines all day.
+	iterFunc := func() {
+		p, stop := iter.Pull2(
+			func(yield func(int, int) bool) {
+				for i := 0; i < 10000; i++ {
+					if !yield(i, i) {
+						return
+					}
+				}
+			},
+		)
+		defer stop()
+		for {
+			_, _, ok := p()
+			if !ok {
+				break
+			}
+		}
+	}
+	var wg sync.WaitGroup
+	done := make(chan struct{})
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		for {
+			iterFunc()
+			select {
+			case <-done:
+			default:
+			}
+		}
+	}()
+
+	// Take a goroutine profile. If the bug in #69998 is present, this will crash
+	// with high probability. We don't care about the output for this bug.
+	goroutineProf.WriteTo(io.Discard, 1)
+}
+
 func BenchmarkGoroutine(b *testing.B) {
 	withIdle := func(n int, fn func(b *testing.B)) func(b *testing.B) {
 		return func(b *testing.B) {
@@ -2441,16 +2524,7 @@
 }
 
 func TestProfilerStackDepth(t *testing.T) {
-	// Disable sampling, otherwise it's difficult to assert anything.
-	oldMemRate := runtime.MemProfileRate
-	runtime.MemProfileRate = 1
-	runtime.SetBlockProfileRate(1)
-	oldMutexRate := runtime.SetMutexProfileFraction(1)
-	t.Cleanup(func() {
-		runtime.MemProfileRate = oldMemRate
-		runtime.SetBlockProfileRate(0)
-		runtime.SetMutexProfileFraction(oldMutexRate)
-	})
+	t.Cleanup(disableSampling())
 
 	const depth = 128
 	go produceProfileEvents(t, depth)
@@ -2478,7 +2552,7 @@
 			}
 			t.Logf("Profile = %v", p)
 
-			stks := stacks(p)
+			stks := profileStacks(p)
 			var stk []string
 			for _, s := range stks {
 				if hasPrefix(s, test.prefix) {
@@ -2742,3 +2816,84 @@
 		})
 	}
 }
+
+func TestProfileRecordNullPadding(t *testing.T) {
+	// Produce events for the different profile types.
+	t.Cleanup(disableSampling())
+	memSink = make([]byte, 1)      // MemProfile
+	<-time.After(time.Millisecond) // BlockProfile
+	blockMutex(t)                  // MutexProfile
+	runtime.GC()
+
+	// Test that all profile records are null padded.
+	testProfileRecordNullPadding(t, "MutexProfile", runtime.MutexProfile)
+	testProfileRecordNullPadding(t, "GoroutineProfile", runtime.GoroutineProfile)
+	testProfileRecordNullPadding(t, "BlockProfile", runtime.BlockProfile)
+	testProfileRecordNullPadding(t, "MemProfile/inUseZero=true", func(p []runtime.MemProfileRecord) (int, bool) {
+		return runtime.MemProfile(p, true)
+	})
+	testProfileRecordNullPadding(t, "MemProfile/inUseZero=false", func(p []runtime.MemProfileRecord) (int, bool) {
+		return runtime.MemProfile(p, false)
+	})
+	// Not testing ThreadCreateProfile because it is broken, see issue 6104.
+}
+
+func testProfileRecordNullPadding[T runtime.StackRecord | runtime.MemProfileRecord | runtime.BlockProfileRecord](t *testing.T, name string, fn func([]T) (int, bool)) {
+	stack0 := func(sr *T) *[32]uintptr {
+		switch t := any(sr).(type) {
+		case *runtime.StackRecord:
+			return &t.Stack0
+		case *runtime.MemProfileRecord:
+			return &t.Stack0
+		case *runtime.BlockProfileRecord:
+			return &t.Stack0
+		default:
+			panic(fmt.Sprintf("unexpected type %T", sr))
+		}
+	}
+
+	t.Run(name, func(t *testing.T) {
+		var p []T
+		for {
+			n, ok := fn(p)
+			if ok {
+				p = p[:n]
+				break
+			}
+			p = make([]T, n*2)
+			for i := range p {
+				s0 := stack0(&p[i])
+				for j := range s0 {
+					// Poison the Stack0 array to identify lack of zero padding
+					s0[j] = ^uintptr(0)
+				}
+			}
+		}
+
+		if len(p) == 0 {
+			t.Fatal("no records found")
+		}
+
+		for _, sr := range p {
+			for i, v := range stack0(&sr) {
+				if v == ^uintptr(0) {
+					t.Fatalf("record p[%d].Stack0 is not null padded: %+v", i, sr)
+				}
+			}
+		}
+	})
+}
+
+// disableSampling configures the profilers to capture all events, otherwise
+// it's difficult to assert anything.
+func disableSampling() func() {
+	oldMemRate := runtime.MemProfileRate
+	runtime.MemProfileRate = 1
+	runtime.SetBlockProfileRate(1)
+	oldMutexRate := runtime.SetMutexProfileFraction(1)
+	return func() {
+		runtime.MemProfileRate = oldMemRate
+		runtime.SetBlockProfileRate(0)
+		runtime.SetMutexProfileFraction(oldMutexRate)
+	}
+}
diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go
index 5defe2f..1456133 100644
--- a/src/runtime/runtime-gdb_test.go
+++ b/src/runtime/runtime-gdb_test.go
@@ -575,15 +575,15 @@
 
 	// Check that the backtrace matches the source code.
 	types := []string{
-		"[]main.astruct;",
-		"bucket<string,main.astruct>;",
-		"hash<string,main.astruct>;",
-		"main.astruct;",
-		"hash<string,main.astruct> * map[string]main.astruct;",
+		"[]main.astruct",
+		"bucket<string,main.astruct>",
+		"hash<string,main.astruct>",
+		"main.astruct",
+		"hash<string,main.astruct> * map[string]main.astruct",
 	}
 	for _, name := range types {
 		if !strings.Contains(sgot, name) {
-			t.Fatalf("could not find %s in 'info typrs astruct' output", name)
+			t.Fatalf("could not find %q in 'info typrs astruct' output", name)
 		}
 	}
 }
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 4a78963..074ce5e 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -1095,6 +1095,7 @@
 	waitReasonTraceProcStatus                         // "trace proc status"
 	waitReasonPageTraceFlush                          // "page trace flush"
 	waitReasonCoroutine                               // "coroutine"
+	waitReasonGCWeakToStrongWait                      // "GC weak to strong wait"
 )
 
 var waitReasonStrings = [...]string{
@@ -1135,6 +1136,7 @@
 	waitReasonTraceProcStatus:       "trace proc status",
 	waitReasonPageTraceFlush:        "page trace flush",
 	waitReasonCoroutine:             "coroutine",
+	waitReasonGCWeakToStrongWait:    "GC weak to strong wait",
 }
 
 func (w waitReason) String() string {
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index 8ba498b..6f40f44 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -605,6 +605,19 @@
 var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool
 var testSigusr1 func(gp *g) bool
 
+// sigsysIgnored is non-zero if we are currently ignoring SIGSYS. See issue #69065.
+var sigsysIgnored uint32
+
+//go:linkname ignoreSIGSYS os.ignoreSIGSYS
+func ignoreSIGSYS() {
+	atomic.Store(&sigsysIgnored, 1)
+}
+
+//go:linkname restoreSIGSYS os.restoreSIGSYS
+func restoreSIGSYS() {
+	atomic.Store(&sigsysIgnored, 0)
+}
+
 // sighandler is invoked when a signal occurs. The global g will be
 // set to a gsignal goroutine and we will be running on the alternate
 // signal stack. The parameter gp will be the value of the global g
@@ -715,6 +728,10 @@
 		return
 	}
 
+	if sig == _SIGSYS && c.sigFromSeccomp() && atomic.Load(&sigsysIgnored) != 0 {
+		return
+	}
+
 	if flags&_SigKill != 0 {
 		dieFromSignal(sig)
 	}
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index cdf859a..d43c6ac 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -69,7 +69,7 @@
 	// to each stack below the usual guard area for OS-specific
 	// purposes like signal handling. Used on Windows, Plan 9,
 	// and iOS because they do not use a separate stack.
-	stackSystem = goos.IsWindows*512*goarch.PtrSize + goos.IsPlan9*512 + goos.IsIos*goarch.IsArm64*1024
+	stackSystem = goos.IsWindows*4096 + goos.IsPlan9*512 + goos.IsIos*goarch.IsArm64*1024
 
 	// The minimum size of stack used by Go code
 	stackMin = 2048
@@ -1330,7 +1330,7 @@
 }
 
 // startingStackSize is the amount of stack that new goroutines start with.
-// It is a power of 2, and between _FixedStack and maxstacksize, inclusive.
+// It is a power of 2, and between fixedStack and maxstacksize, inclusive.
 // startingStackSize is updated every GC by tracking the average size of
 // stacks scanned during the GC.
 var startingStackSize uint32 = fixedStack
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 69d720a..85b1b8c 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -454,43 +454,37 @@
 //go:linkname syscall_Syscall syscall.Syscall
 //go:nosplit
 func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
-	args := [...]uintptr{a1, a2, a3}
-	return syscall_SyscallN(fn, args[:nargs]...)
+	return syscall_syscalln(fn, nargs, a1, a2, a3)
 }
 
 //go:linkname syscall_Syscall6 syscall.Syscall6
 //go:nosplit
 func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
-	args := [...]uintptr{a1, a2, a3, a4, a5, a6}
-	return syscall_SyscallN(fn, args[:nargs]...)
+	return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6)
 }
 
 //go:linkname syscall_Syscall9 syscall.Syscall9
 //go:nosplit
 func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
-	args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9}
-	return syscall_SyscallN(fn, args[:nargs]...)
+	return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9)
 }
 
 //go:linkname syscall_Syscall12 syscall.Syscall12
 //go:nosplit
 func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
-	args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12}
-	return syscall_SyscallN(fn, args[:nargs]...)
+	return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
 }
 
 //go:linkname syscall_Syscall15 syscall.Syscall15
 //go:nosplit
 func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
-	args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15}
-	return syscall_SyscallN(fn, args[:nargs]...)
+	return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
 }
 
 //go:linkname syscall_Syscall18 syscall.Syscall18
 //go:nosplit
 func syscall_Syscall18(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2, err uintptr) {
-	args := [...]uintptr{a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18}
-	return syscall_SyscallN(fn, args[:nargs]...)
+	return syscall_syscalln(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18)
 }
 
 // maxArgs should be divisible by 2, as Windows stack
@@ -503,7 +497,15 @@
 //go:linkname syscall_SyscallN syscall.SyscallN
 //go:nosplit
 func syscall_SyscallN(fn uintptr, args ...uintptr) (r1, r2, err uintptr) {
-	if len(args) > maxArgs {
+	return syscall_syscalln(fn, uintptr(len(args)), args...)
+}
+
+//go:nosplit
+func syscall_syscalln(fn, n uintptr, args ...uintptr) (r1, r2, err uintptr) {
+	if n > uintptr(len(args)) {
+		panic("syscall: n > len(args)") // should not be reachable from user code
+	}
+	if n > maxArgs {
 		panic("runtime: SyscallN has too many arguments")
 	}
 
@@ -512,7 +514,7 @@
 	// calls back into Go.
 	c := &getg().m.winsyscall
 	c.fn = fn
-	c.n = uintptr(len(args))
+	c.n = n
 	if c.n != 0 {
 		c.args = uintptr(noescape(unsafe.Pointer(&args[0])))
 	}
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index 6a056c8..156cf3e 100644
--- a/src/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -1212,6 +1212,13 @@
 	}
 }
 
+func TestSyscallStackUsage(t *testing.T) {
+	// Test that the stack usage of a syscall doesn't exceed the limit.
+	// See https://go.dev/issue/69813.
+	syscall.Syscall15(procSetEvent.Addr(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+	syscall.Syscall18(procSetEvent.Addr(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+}
+
 var (
 	modwinmm    = syscall.NewLazyDLL("winmm.dll")
 	modkernel32 = syscall.NewLazyDLL("kernel32.dll")
diff --git a/src/runtime/time.go b/src/runtime/time.go
index b43cf95..7b344a3 100644
--- a/src/runtime/time.go
+++ b/src/runtime/time.go
@@ -30,35 +30,6 @@
 	state  uint8        // state bits
 	isChan bool         // timer has a channel; immutable; can be read without lock
 
-	// isSending is used to handle races between running a
-	// channel timer and stopping or resetting the timer.
-	// It is used only for channel timers (t.isChan == true).
-	// The lowest zero bit is set when about to send a value on the channel,
-	// and cleared after sending the value.
-	// The stop/reset code uses this to detect whether it
-	// stopped the channel send.
-	//
-	// An isSending bit is set only when t.mu is held.
-	// An isSending bit is cleared only when t.sendLock is held.
-	// isSending is read only when both t.mu and t.sendLock are held.
-	//
-	// Setting and clearing Uint8 bits handles the case of
-	// a timer that is reset concurrently with unlockAndRun.
-	// If the reset timer runs immediately, we can wind up with
-	// concurrent calls to unlockAndRun for the same timer.
-	// Using matched bit set and clear in unlockAndRun
-	// ensures that the value doesn't get temporarily out of sync.
-	//
-	// We use a uint8 to keep the timer struct small.
-	// This means that we can only support up to 8 concurrent
-	// runs of a timer, where a concurrent run can only occur if
-	// we start a run, unlock the timer, the timer is reset to a new
-	// value (or the ticker fires again), it is ready to run,
-	// and it is actually run, all before the first run completes.
-	// Since completing a run is fast, even 2 concurrent timer runs are
-	// nearly impossible, so this should be safe in practice.
-	isSending atomic.Uint8
-
 	blocked uint32 // number of goroutines blocked on timer's channel
 
 	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
@@ -98,6 +69,20 @@
 	// sendLock protects sends on the timer's channel.
 	// Not used for async (pre-Go 1.23) behavior when debug.asynctimerchan.Load() != 0.
 	sendLock mutex
+
+	// isSending is used to handle races between running a
+	// channel timer and stopping or resetting the timer.
+	// It is used only for channel timers (t.isChan == true).
+	// It is not used for tickers.
+	// The value is incremented when about to send a value on the channel,
+	// and decremented after sending the value.
+	// The stop/reset code uses this to detect whether it
+	// stopped the channel send.
+	//
+	// isSending is incremented only when t.mu is held.
+	// isSending is decremented only when t.sendLock is held.
+	// isSending is read only when both t.mu and t.sendLock are held.
+	isSending atomic.Int32
 }
 
 // init initializes a newly allocated timer t.
@@ -467,7 +452,7 @@
 		// send from actually happening. That means
 		// that we should return true: the timer was
 		// stopped, even though t.when may be zero.
-		if t.isSending.Load() > 0 {
+		if t.period == 0 && t.isSending.Load() > 0 {
 			pending = true
 		}
 	}
@@ -529,6 +514,7 @@
 		t.maybeRunAsync()
 	}
 	t.trace("modify")
+	oldPeriod := t.period
 	t.period = period
 	if f != nil {
 		t.f = f
@@ -570,7 +556,7 @@
 		// send from actually happening. That means
 		// that we should return true: the timer was
 		// stopped, even though t.when may be zero.
-		if t.isSending.Load() > 0 {
+		if oldPeriod == 0 && t.isSending.Load() > 0 {
 			pending = true
 		}
 	}
@@ -1063,20 +1049,11 @@
 	}
 
 	async := debug.asynctimerchan.Load() != 0
-	var isSendingClear uint8
-	if !async && t.isChan {
+	if !async && t.isChan && t.period == 0 {
 		// Tell Stop/Reset that we are sending a value.
-		// Set the lowest zero bit.
-		// We do this awkward step because atomic.Uint8
-		// doesn't support Add or CompareAndSwap.
-		// We only set bits with t locked.
-		v := t.isSending.Load()
-		i := sys.TrailingZeros8(^v)
-		if i == 8 {
+		if t.isSending.Add(1) < 0 {
 			throw("too many concurrent timer firings")
 		}
-		isSendingClear = 1 << i
-		t.isSending.Or(isSendingClear)
 	}
 
 	t.unlock()
@@ -1114,6 +1091,16 @@
 		// started to send the value. That lets them correctly return
 		// true meaning that no value was sent.
 		lock(&t.sendLock)
+
+		if t.period == 0 {
+			// We are committed to possibly sending a value
+			// based on seq, so no need to keep telling
+			// stop/modify that we are sending.
+			if t.isSending.Add(-1) < 0 {
+				throw("mismatched isSending updates")
+			}
+		}
+
 		if t.seq != seq {
 			f = func(any, uintptr, int64) {}
 		}
@@ -1122,9 +1109,6 @@
 	f(arg, seq, delay)
 
 	if !async && t.isChan {
-		// We are no longer sending a value.
-		t.isSending.And(^isSendingClear)
-
 		unlock(&t.sendLock)
 	}
 
diff --git a/src/runtime/traceruntime.go b/src/runtime/traceruntime.go
index 195b3e1..7c4cb55 100644
--- a/src/runtime/traceruntime.go
+++ b/src/runtime/traceruntime.go
@@ -99,24 +99,26 @@
 	traceBlockDebugCall
 	traceBlockUntilGCEnds
 	traceBlockSleep
+	traceBlockGCWeakToStrongWait
 )
 
 var traceBlockReasonStrings = [...]string{
-	traceBlockGeneric:         "unspecified",
-	traceBlockForever:         "forever",
-	traceBlockNet:             "network",
-	traceBlockSelect:          "select",
-	traceBlockCondWait:        "sync.(*Cond).Wait",
-	traceBlockSync:            "sync",
-	traceBlockChanSend:        "chan send",
-	traceBlockChanRecv:        "chan receive",
-	traceBlockGCMarkAssist:    "GC mark assist wait for work",
-	traceBlockGCSweep:         "GC background sweeper wait",
-	traceBlockSystemGoroutine: "system goroutine wait",
-	traceBlockPreempted:       "preempted",
-	traceBlockDebugCall:       "wait for debug call",
-	traceBlockUntilGCEnds:     "wait until GC ends",
-	traceBlockSleep:           "sleep",
+	traceBlockGeneric:            "unspecified",
+	traceBlockForever:            "forever",
+	traceBlockNet:                "network",
+	traceBlockSelect:             "select",
+	traceBlockCondWait:           "sync.(*Cond).Wait",
+	traceBlockSync:               "sync",
+	traceBlockChanSend:           "chan send",
+	traceBlockChanRecv:           "chan receive",
+	traceBlockGCMarkAssist:       "GC mark assist wait for work",
+	traceBlockGCSweep:            "GC background sweeper wait",
+	traceBlockSystemGoroutine:    "system goroutine wait",
+	traceBlockPreempted:          "preempted",
+	traceBlockDebugCall:          "wait for debug call",
+	traceBlockUntilGCEnds:        "wait until GC ends",
+	traceBlockSleep:              "sleep",
+	traceBlockGCWeakToStrongWait: "GC weak to strong wait",
 }
 
 // traceGoStopReason is an enumeration of reasons a goroutine might yield.
diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go
index 81134cb..a7873e6 100644
--- a/src/syscall/dll_windows.go
+++ b/src/syscall/dll_windows.go
@@ -42,6 +42,7 @@
 // Deprecated: Use [SyscallN] instead.
 func Syscall18(trap, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2 uintptr, err Errno)
 
+//go:noescape
 func SyscallN(trap uintptr, args ...uintptr) (r1, r2 uintptr, err Errno)
 func loadlibrary(filename *uint16) (handle uintptr, err Errno)
 func loadsystemlibrary(filename *uint16) (handle uintptr, err Errno)
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go
index 2684412..dfd9a83 100644
--- a/src/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -7,6 +7,7 @@
 package syscall
 
 import (
+	errpkg "errors"
 	"internal/itoa"
 	"runtime"
 	"unsafe"
@@ -328,6 +329,7 @@
 	if clone3 != nil {
 		pid, err1 = rawVforkSyscall(_SYS_clone3, uintptr(unsafe.Pointer(clone3)), unsafe.Sizeof(*clone3), 0)
 	} else {
+		// N.B. Keep in sync with doCheckClonePidfd.
 		flags |= uintptr(SIGCHLD)
 		if runtime.GOARCH == "s390x" {
 			// On Linux/s390, the first two arguments of clone(2) are swapped.
@@ -743,3 +745,82 @@
 		*sys.PidFD = -1
 	}
 }
+
+// checkClonePidfd verifies that clone(CLONE_PIDFD) works by actually doing a
+// clone.
+//
+//go:linkname os_checkClonePidfd os.checkClonePidfd
+func os_checkClonePidfd() error {
+	pidfd := int32(-1)
+	pid, errno := doCheckClonePidfd(&pidfd)
+	if errno != 0 {
+		return errno
+	}
+
+	if pidfd == -1 {
+		// Bad: CLONE_PIDFD failed to provide a pidfd. Reap the process
+		// before returning.
+
+		var err error
+		for {
+			var status WaitStatus
+			_, err = Wait4(int(pid), &status, 0, nil)
+			if err != EINTR {
+				break
+			}
+		}
+		if err != nil {
+			return err
+		}
+
+		return errpkg.New("clone(CLONE_PIDFD) failed to return pidfd")
+	}
+
+	// Good: CLONE_PIDFD provided a pidfd. Reap the process and close the
+	// pidfd.
+	defer Close(int(pidfd))
+
+	for {
+		const _P_PIDFD = 3
+		_, _, errno = Syscall6(SYS_WAITID, _P_PIDFD, uintptr(pidfd), 0, WEXITED, 0, 0)
+		if errno != EINTR {
+			break
+		}
+	}
+	if errno != 0 {
+		return errno
+	}
+
+	return nil
+}
+
+// doCheckClonePidfd implements the actual clone call of os_checkClonePidfd and
+// child execution. This is a separate function so we can separate the child's
+// and parent's stack frames if we're using vfork.
+//
+// This is go:noinline because the point is to keep the stack frames of this
+// and os_checkClonePidfd separate.
+//
+//go:noinline
+func doCheckClonePidfd(pidfd *int32) (pid uintptr, errno Errno) {
+	flags := uintptr(CLONE_VFORK|CLONE_VM|CLONE_PIDFD|SIGCHLD)
+	if runtime.GOARCH == "s390x" {
+		// On Linux/s390, the first two arguments of clone(2) are swapped.
+		pid, errno = rawVforkSyscall(SYS_CLONE, 0, flags, uintptr(unsafe.Pointer(pidfd)))
+	} else {
+		pid, errno = rawVforkSyscall(SYS_CLONE, flags, 0, uintptr(unsafe.Pointer(pidfd)))
+	}
+	if errno != 0 || pid != 0 {
+		// If we're in the parent, we must return immediately
+		// so we're not in the same stack frame as the child.
+		// This can at most use the return PC, which the child
+		// will not modify, and the results of
+		// rawVforkSyscall, which must have been written after
+		// the child was replaced.
+		return
+	}
+
+	for {
+		RawSyscall(SYS_EXIT_GROUP, 0, 0, 0)
+	}
+}
diff --git a/src/syscall/syscall_windows_test.go b/src/syscall/syscall_windows_test.go
index f67e899..a6c6eff 100644
--- a/src/syscall/syscall_windows_test.go
+++ b/src/syscall/syscall_windows_test.go
@@ -213,6 +213,51 @@
 	}
 }
 
+func TestSyscallAllocations(t *testing.T) {
+	testenv.SkipIfOptimizationOff(t)
+
+	// Test that syscall.SyscallN arguments do not escape.
+	// The function used (in this case GetVersion) doesn't matter
+	// as long as it is always available and doesn't panic.
+	h, err := syscall.LoadLibrary("kernel32.dll")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer syscall.FreeLibrary(h)
+	proc, err := syscall.GetProcAddress(h, "GetVersion")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	testAllocs := func(t *testing.T, name string, fn func() error) {
+		t.Run(name, func(t *testing.T) {
+			n := int(testing.AllocsPerRun(10, func() {
+				if err := fn(); err != nil {
+					t.Fatalf("%s: %v", name, err)
+				}
+			}))
+			if n > 0 {
+				t.Errorf("allocs = %d, want 0", n)
+			}
+		})
+	}
+
+	testAllocs(t, "SyscallN", func() error {
+		r0, _, e1 := syscall.SyscallN(proc, 0, 0, 0)
+		if r0 == 0 {
+			return syscall.Errno(e1)
+		}
+		return nil
+	})
+	testAllocs(t, "Syscall", func() error {
+		r0, _, e1 := syscall.Syscall(proc, 3, 0, 0, 0)
+		if r0 == 0 {
+			return syscall.Errno(e1)
+		}
+		return nil
+	})
+}
+
 func FuzzUTF16FromString(f *testing.F) {
 	f.Add("hi")           // ASCII
 	f.Add("â")            // latin1
diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go
index 5357ed2..285a2e7 100644
--- a/src/time/sleep_test.go
+++ b/src/time/sleep_test.go
@@ -847,6 +847,57 @@
 	wg.Wait()
 }
 
+// Test having a large number of goroutines wake up a ticker simultaneously.
+// This used to trigger a crash when run under x/tools/cmd/stress.
+func TestMultiWakeupTicker(t *testing.T) {
+	if testing.Short() {
+		t.Skip("-short")
+	}
+
+	goroutines := runtime.GOMAXPROCS(0)
+	timer := NewTicker(Microsecond)
+	var wg sync.WaitGroup
+	wg.Add(goroutines)
+	for range goroutines {
+		go func() {
+			defer wg.Done()
+			for range 100000 {
+				select {
+				case <-timer.C:
+				case <-After(Millisecond):
+				}
+			}
+		}()
+	}
+	wg.Wait()
+}
+
+// Test having a large number of goroutines wake up a timer simultaneously.
+// This used to trigger a crash when run under x/tools/cmd/stress.
+func TestMultiWakeupTimer(t *testing.T) {
+	if testing.Short() {
+		t.Skip("-short")
+	}
+
+	goroutines := runtime.GOMAXPROCS(0)
+	timer := NewTimer(Nanosecond)
+	var wg sync.WaitGroup
+	wg.Add(goroutines)
+	for range goroutines {
+		go func() {
+			defer wg.Done()
+			for range 10000 {
+				select {
+				case <-timer.C:
+				default:
+				}
+				timer.Reset(Nanosecond)
+			}
+		}()
+	}
+	wg.Wait()
+}
+
 // Benchmark timer latency when the thread that creates the timer is busy with
 // other work and the timers must be serviced by other threads.
 // https://golang.org/issue/38860
diff --git a/src/time/time_test.go b/src/time/time_test.go
index 70eb614..c12b911 100644
--- a/src/time/time_test.go
+++ b/src/time/time_test.go
@@ -14,6 +14,7 @@
 	"math/rand"
 	"os"
 	"runtime"
+	"slices"
 	"strings"
 	"sync"
 	"testing"
@@ -1084,10 +1085,15 @@
 	// So GMT+1 corresponds to -3600 in the Go zone, not +3600.
 	name, offset := Now().In(loc).Zone()
 	// The zone abbreviation is "-01" since tzdata-2016g, and "GMT+1"
-	// on earlier versions; we accept both. (Issue #17276).
-	if !(name == "GMT+1" || name == "-01") || offset != -1*60*60 {
-		t.Errorf("Now().In(loc).Zone() = %q, %d, want %q or %q, %d",
-			name, offset, "GMT+1", "-01", -1*60*60)
+	// on earlier versions; we accept both. (Issue 17276.)
+	wantName := []string{"GMT+1", "-01"}
+	// The zone abbreviation may be "+01" on OpenBSD. (Issue 69840.)
+	if runtime.GOOS == "openbsd" {
+		wantName = append(wantName, "+01")
+	}
+	if !slices.Contains(wantName, name) || offset != -1*60*60 {
+		t.Errorf("Now().In(loc).Zone() = %q, %d, want %q (one of), %d",
+			name, offset, wantName, -1*60*60)
 	}
 }
 
diff --git a/test/fixedbugs/issue14636.go b/test/fixedbugs/issue14636.go
index c8e751f..a866c9a 100644
--- a/test/fixedbugs/issue14636.go
+++ b/test/fixedbugs/issue14636.go
@@ -12,22 +12,29 @@
 	"bytes"
 	"log"
 	"os/exec"
+	"runtime"
 	"strings"
 )
 
 func main() {
-	checkLinkOutput("", "-B argument must start with 0x")
+	// The cannot open file error indicates that the parsing of -B flag
+	// succeeded and it failed at a later step.
 	checkLinkOutput("0", "-B argument must start with 0x")
-	checkLinkOutput("0x", "usage")
+	checkLinkOutput("0x", "cannot open file nonexistent.o")
 	checkLinkOutput("0x0", "-B argument must have even number of digits")
-	checkLinkOutput("0x00", "usage")
+	checkLinkOutput("0x00", "cannot open file nonexistent.o")
 	checkLinkOutput("0xYZ", "-B argument contains invalid hex digit")
-	checkLinkOutput("0x"+strings.Repeat("00", 32), "usage")
-	checkLinkOutput("0x"+strings.Repeat("00", 33), "-B option too long (max 32 digits)")
+
+	maxLen := 32
+	if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
+		maxLen = 16
+	}
+	checkLinkOutput("0x"+strings.Repeat("00", maxLen), "cannot open file nonexistent.o")
+	checkLinkOutput("0x"+strings.Repeat("00", maxLen+1), "-B option too long")
 }
 
 func checkLinkOutput(buildid string, message string) {
-	cmd := exec.Command("go", "tool", "link", "-B", buildid)
+	cmd := exec.Command("go", "tool", "link", "-B", buildid, "nonexistent.o")
 	out, err := cmd.CombinedOutput()
 	if err == nil {
 		log.Fatalf("expected cmd/link to fail")
@@ -39,6 +46,6 @@
 	}
 
 	if !strings.Contains(firstLine, message) {
-		log.Fatalf("cmd/link output did not include expected message %q: %s", message, firstLine)
+		log.Fatalf("%s: cmd/link output did not include expected message %q: %s", buildid, message, firstLine)
 	}
 }