diff --git a/api/go1.25.txt b/api/go1.25.txt
new file mode 100644
index 0000000000..cb3900bf46
--- /dev/null
+++ b/api/go1.25.txt
@@ -0,0 +1,110 @@
+pkg crypto, func SignMessage(Signer, io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405
+pkg crypto, type MessageSigner interface { Public, Sign, SignMessage } #63405
+pkg crypto, type MessageSigner interface, Public() PublicKey #63405
+pkg crypto, type MessageSigner interface, Sign(io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405
+pkg crypto, type MessageSigner interface, SignMessage(io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405
+pkg crypto/ecdsa, func ParseRawPrivateKey(elliptic.Curve, []uint8) (*PrivateKey, error) #63963
+pkg crypto/ecdsa, func ParseUncompressedPublicKey(elliptic.Curve, []uint8) (*PublicKey, error) #63963
+pkg crypto/ecdsa, method (*PrivateKey) Bytes() ([]uint8, error) #63963
+pkg crypto/ecdsa, method (*PublicKey) Bytes() ([]uint8, error) #63963
+pkg crypto/sha3, method (*SHA3) Clone() (hash.Cloner, error) #69521
+pkg crypto/tls, type Config struct, GetEncryptedClientHelloKeys func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) #71920
+pkg crypto/tls, type ConnectionState struct, CurveID CurveID #67516
+pkg debug/elf, const PT_RISCV_ATTRIBUTES = 1879048195 #72843
+pkg debug/elf, const PT_RISCV_ATTRIBUTES ProgType #72843
+pkg debug/elf, const SHT_RISCV_ATTRIBUTES = 1879048195 #72843
+pkg debug/elf, const SHT_RISCV_ATTRIBUTES SectionType #72843
+pkg go/ast, const FilterFuncDuplicates //deprecated #73088
+pkg go/ast, const FilterImportDuplicates //deprecated #73088
+pkg go/ast, const FilterUnassociatedComments //deprecated #73088
+pkg go/ast, func FilterPackage //deprecated #73088
+pkg go/ast, func MergePackageFiles //deprecated #73088
+pkg go/ast, func PackageExports //deprecated #73088
+pkg go/ast, func PreorderStack(Node, []Node, func(Node, []Node) bool) #73319
+pkg go/ast, type MergeMode //deprecated #73088
+pkg go/parser, func ParseDir //deprecated #71122
+pkg go/token, method (*FileSet) AddExistingFiles(...*File) #73205
+pkg go/types, const FieldVar = 6 #70250
+pkg go/types, const FieldVar VarKind #70250
+pkg go/types, const LocalVar = 2 #70250
+pkg go/types, const LocalVar VarKind #70250
+pkg go/types, const PackageVar = 1 #70250
+pkg go/types, const PackageVar VarKind #70250
+pkg go/types, const ParamVar = 4 #70250
+pkg go/types, const ParamVar VarKind #70250
+pkg go/types, const RecvVar = 3 #70250
+pkg go/types, const RecvVar VarKind #70250
+pkg go/types, const ResultVar = 5 #70250
+pkg go/types, const ResultVar VarKind #70250
+pkg go/types, func LookupSelection(Type, bool, *Package, string) (Selection, bool) #70737
+pkg go/types, method (*Var) Kind() VarKind #70250
+pkg go/types, method (*Var) SetKind(VarKind) #70250
+pkg go/types, method (VarKind) String() string #70250
+pkg go/types, type VarKind uint8 #70250
+pkg hash, type Cloner interface { BlockSize, Clone, Reset, Size, Sum, Write } #69521
+pkg hash, type Cloner interface, BlockSize() int #69521
+pkg hash, type Cloner interface, Clone() (Cloner, error) #69521
+pkg hash, type Cloner interface, Reset() #69521
+pkg hash, type Cloner interface, Size() int #69521
+pkg hash, type Cloner interface, Sum([]uint8) []uint8 #69521
+pkg hash, type Cloner interface, Write([]uint8) (int, error) #69521
+pkg hash, type XOF interface { BlockSize, Read, Reset, Write } #69518
+pkg hash, type XOF interface, BlockSize() int #69518
+pkg hash, type XOF interface, Read([]uint8) (int, error) #69518
+pkg hash, type XOF interface, Reset() #69518
+pkg hash, type XOF interface, Write([]uint8) (int, error) #69518
+pkg hash/maphash, method (*Hash) Clone() (hash.Cloner, error) #69521
+pkg io/fs, func Lstat(FS, string) (FileInfo, error) #49580
+pkg io/fs, func ReadLink(FS, string) (string, error) #49580
+pkg io/fs, type ReadLinkFS interface { Lstat, Open, ReadLink } #49580
+pkg io/fs, type ReadLinkFS interface, Lstat(string) (FileInfo, error) #49580
+pkg io/fs, type ReadLinkFS interface, Open(string) (File, error) #49580
+pkg io/fs, type ReadLinkFS interface, ReadLink(string) (string, error) #49580
+pkg log/slog, func GroupAttrs(string, ...Attr) Attr #66365
+pkg log/slog, method (Record) Source() *Source #70280
+pkg mime/multipart, func FileContentDisposition(string, string) string #46771
+pkg net/http, func NewCrossOriginProtection() *CrossOriginProtection #73626
+pkg net/http, method (*CrossOriginProtection) AddInsecureBypassPattern(string) #73626
+pkg net/http, method (*CrossOriginProtection) AddTrustedOrigin(string) error #73626
+pkg net/http, method (*CrossOriginProtection) Check(*Request) error #73626
+pkg net/http, method (*CrossOriginProtection) Handler(Handler) Handler #73626
+pkg net/http, method (*CrossOriginProtection) SetDenyHandler(Handler) #73626
+pkg net/http, type CrossOriginProtection struct #73626
+pkg os, method (*Root) Chmod(string, fs.FileMode) error #67002
+pkg os, method (*Root) Chown(string, int, int) error #67002
+pkg os, method (*Root) Chtimes(string, time.Time, time.Time) error #67002
+pkg os, method (*Root) Lchown(string, int, int) error #67002
+pkg os, method (*Root) Link(string, string) error #67002
+pkg os, method (*Root) MkdirAll(string, fs.FileMode) error #67002
+pkg os, method (*Root) ReadFile(string) ([]uint8, error) #73126
+pkg os, method (*Root) Readlink(string) (string, error) #67002
+pkg os, method (*Root) RemoveAll(string) error #67002
+pkg os, method (*Root) Rename(string, string) error #67002
+pkg os, method (*Root) Symlink(string, string) error #67002
+pkg os, method (*Root) WriteFile(string, []uint8, fs.FileMode) error #73126
+pkg reflect, func TypeAssert[$0 interface{}](Value) ($0, bool) #62121
+pkg runtime, func SetDefaultGOMAXPROCS() #73193
+pkg runtime/trace, func NewFlightRecorder(FlightRecorderConfig) *FlightRecorder #63185
+pkg runtime/trace, method (*FlightRecorder) Enabled() bool #63185
+pkg runtime/trace, method (*FlightRecorder) Start() error #63185
+pkg runtime/trace, method (*FlightRecorder) Stop() #63185
+pkg runtime/trace, method (*FlightRecorder) WriteTo(io.Writer) (int64, error) #63185
+pkg runtime/trace, type FlightRecorder struct #63185
+pkg runtime/trace, type FlightRecorderConfig struct #63185
+pkg runtime/trace, type FlightRecorderConfig struct, MaxBytes uint64 #63185
+pkg runtime/trace, type FlightRecorderConfig struct, MinAge time.Duration #63185
+pkg sync, method (*WaitGroup) Go(func()) #63796
+pkg testing, method (*B) Attr(string, string) #43936
+pkg testing, method (*B) Output() io.Writer #59928
+pkg testing, method (*F) Attr(string, string) #43936
+pkg testing, method (*F) Output() io.Writer #59928
+pkg testing, method (*T) Attr(string, string) #43936
+pkg testing, method (*T) Output() io.Writer #59928
+pkg testing, type TB interface, Attr(string, string) #43936
+pkg testing/fstest, method (MapFS) Lstat(string) (fs.FileInfo, error) #49580
+pkg testing/fstest, method (MapFS) ReadLink(string) (string, error) #49580
+pkg testing/synctest, func Test(*testing.T, func(*testing.T)) #67434
+pkg testing/synctest, func Wait() #67434
+pkg unicode, var CategoryAliases map[string]string #70780
+pkg unicode, var Cn *RangeTable #70780
+pkg unicode, var LC *RangeTable #70780
diff --git a/api/next/43936.txt b/api/next/43936.txt
deleted file mode 100644
index e32bd75ed9..0000000000
--- a/api/next/43936.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pkg testing, method (*B) Attr(string, string) #43936
-pkg testing, method (*F) Attr(string, string) #43936
-pkg testing, method (*T) Attr(string, string) #43936
-pkg testing, type TB interface, Attr(string, string) #43936
diff --git a/api/next/46771.txt b/api/next/46771.txt
deleted file mode 100644
index f7aad4b04a..0000000000
--- a/api/next/46771.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg mime/multipart, func FileContentDisposition(string, string) string #46771
diff --git a/api/next/49580.txt b/api/next/49580.txt
deleted file mode 100644
index ce213cc9ca..0000000000
--- a/api/next/49580.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-pkg io/fs, func Lstat(FS, string) (FileInfo, error) #49580
-pkg io/fs, func ReadLink(FS, string) (string, error) #49580
-pkg io/fs, type ReadLinkFS interface { Lstat, Open, ReadLink } #49580
-pkg io/fs, type ReadLinkFS interface, Lstat(string) (FileInfo, error) #49580
-pkg io/fs, type ReadLinkFS interface, Open(string) (File, error) #49580
-pkg io/fs, type ReadLinkFS interface, ReadLink(string) (string, error) #49580
-pkg testing/fstest, method (MapFS) Lstat(string) (fs.FileInfo, error) #49580
-pkg testing/fstest, method (MapFS) ReadLink(string) (string, error) #49580
diff --git a/api/next/59928.txt b/api/next/59928.txt
deleted file mode 100644
index 375c7c0e90..0000000000
--- a/api/next/59928.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg testing, method (*B) Output() io.Writer #59928
-pkg testing, method (*F) Output() io.Writer #59928
-pkg testing, method (*T) Output() io.Writer #59928
diff --git a/api/next/62121.txt b/api/next/62121.txt
deleted file mode 100644
index bb220a619a..0000000000
--- a/api/next/62121.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg reflect, func TypeAssert[$0 interface{}](Value) ($0, bool) #62121
diff --git a/api/next/63185.txt b/api/next/63185.txt
deleted file mode 100644
index b5127ff8b2..0000000000
--- a/api/next/63185.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg runtime/trace, func NewFlightRecorder(FlightRecorderConfig) *FlightRecorder #63185
-pkg runtime/trace, method (*FlightRecorder) Enabled() bool #63185
-pkg runtime/trace, method (*FlightRecorder) Start() error #63185
-pkg runtime/trace, method (*FlightRecorder) Stop() #63185
-pkg runtime/trace, method (*FlightRecorder) WriteTo(io.Writer) (int64, error) #63185
-pkg runtime/trace, type FlightRecorder struct #63185
-pkg runtime/trace, type FlightRecorderConfig struct #63185
-pkg runtime/trace, type FlightRecorderConfig struct, MaxBytes uint64 #63185
-pkg runtime/trace, type FlightRecorderConfig struct, MinAge time.Duration #63185
diff --git a/api/next/63405.txt b/api/next/63405.txt
deleted file mode 100644
index 5892ef4adc..0000000000
--- a/api/next/63405.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-pkg crypto, func SignMessage(Signer, io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405
-pkg crypto, type MessageSigner interface { Public, Sign, SignMessage } #63405
-pkg crypto, type MessageSigner interface, Public() PublicKey #63405
-pkg crypto, type MessageSigner interface, Sign(io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405
-pkg crypto, type MessageSigner interface, SignMessage(io.Reader, []uint8, SignerOpts) ([]uint8, error) #63405
diff --git a/api/next/63796.txt b/api/next/63796.txt
deleted file mode 100644
index bb1a4b4858..0000000000
--- a/api/next/63796.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg sync, method (*WaitGroup) Go(func()) #63796
diff --git a/api/next/63963.txt b/api/next/63963.txt
deleted file mode 100644
index f64f214c10..0000000000
--- a/api/next/63963.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pkg crypto/ecdsa, func ParseRawPrivateKey(elliptic.Curve, []uint8) (*PrivateKey, error) #63963
-pkg crypto/ecdsa, func ParseUncompressedPublicKey(elliptic.Curve, []uint8) (*PublicKey, error) #63963
-pkg crypto/ecdsa, method (*PrivateKey) Bytes() ([]uint8, error) #63963
-pkg crypto/ecdsa, method (*PublicKey) Bytes() ([]uint8, error) #63963
diff --git a/api/next/66365.txt b/api/next/66365.txt
deleted file mode 100644
index 52f1c7ea8e..0000000000
--- a/api/next/66365.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg log/slog, func GroupAttrs(string, ...Attr) Attr #66365
diff --git a/api/next/67002.txt b/api/next/67002.txt
deleted file mode 100644
index 2a442fd6a4..0000000000
--- a/api/next/67002.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-pkg os, method (*Root) Chmod(string, fs.FileMode) error #67002
-pkg os, method (*Root) Chown(string, int, int) error #67002
-pkg os, method (*Root) Chtimes(string, time.Time, time.Time) error #67002
-pkg os, method (*Root) Lchown(string, int, int) error #67002
-pkg os, method (*Root) Link(string, string) error #67002
-pkg os, method (*Root) MkdirAll(string, fs.FileMode) error #67002
-pkg os, method (*Root) Readlink(string) (string, error) #67002
-pkg os, method (*Root) RemoveAll(string) error #67002
-pkg os, method (*Root) Rename(string, string) error #67002
-pkg os, method (*Root) Symlink(string, string) error #67002
diff --git a/api/next/67434.txt b/api/next/67434.txt
deleted file mode 100644
index 203c55e2a6..0000000000
--- a/api/next/67434.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-pkg testing/synctest, func Test(*testing.T, func(*testing.T)) #67434
-pkg testing/synctest, func Wait() #67434
diff --git a/api/next/67516.txt b/api/next/67516.txt
deleted file mode 100644
index a9b6007d06..0000000000
--- a/api/next/67516.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg crypto/tls, type ConnectionState struct, CurveID CurveID #67516
diff --git a/api/next/69518.txt b/api/next/69518.txt
deleted file mode 100644
index b70fcc13fb..0000000000
--- a/api/next/69518.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-pkg hash, type XOF interface { BlockSize, Read, Reset, Write } #69518
-pkg hash, type XOF interface, BlockSize() int #69518
-pkg hash, type XOF interface, Read([]uint8) (int, error) #69518
-pkg hash, type XOF interface, Reset() #69518
-pkg hash, type XOF interface, Write([]uint8) (int, error) #69518
diff --git a/api/next/69521.txt b/api/next/69521.txt
deleted file mode 100644
index 6974226086..0000000000
--- a/api/next/69521.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-pkg crypto/sha3, method (*SHA3) Clone() (hash.Cloner, error) #69521
-pkg hash, type Cloner interface { BlockSize, Clone, Reset, Size, Sum, Write } #69521
-pkg hash, type Cloner interface, BlockSize() int #69521
-pkg hash, type Cloner interface, Clone() (Cloner, error) #69521
-pkg hash, type Cloner interface, Reset() #69521
-pkg hash, type Cloner interface, Size() int #69521
-pkg hash, type Cloner interface, Sum([]uint8) []uint8 #69521
-pkg hash, type Cloner interface, Write([]uint8) (int, error) #69521
-pkg hash/maphash, method (*Hash) Clone() (hash.Cloner, error) #69521
diff --git a/api/next/70250.txt b/api/next/70250.txt
deleted file mode 100644
index faad356cef..0000000000
--- a/api/next/70250.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-pkg go/types, const FieldVar = 6 #70250
-pkg go/types, const FieldVar VarKind #70250
-pkg go/types, const LocalVar = 2 #70250
-pkg go/types, const LocalVar VarKind #70250
-pkg go/types, const PackageVar = 1 #70250
-pkg go/types, const PackageVar VarKind #70250
-pkg go/types, const ParamVar = 4 #70250
-pkg go/types, const ParamVar VarKind #70250
-pkg go/types, const RecvVar = 3 #70250
-pkg go/types, const RecvVar VarKind #70250
-pkg go/types, const ResultVar = 5 #70250
-pkg go/types, const ResultVar VarKind #70250
-pkg go/types, func LookupSelection(Type, bool, *Package, string) (Selection, bool) #70737
-pkg go/types, method (*Var) Kind() VarKind #70250
-pkg go/types, method (*Var) SetKind(VarKind) #70250
-pkg go/types, method (VarKind) String() string #70250
-pkg go/types, type VarKind uint8 #70250
diff --git a/api/next/70280.txt b/api/next/70280.txt
deleted file mode 100644
index f2dd74af48..0000000000
--- a/api/next/70280.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg log/slog, method (Record) Source() *Source #70280
diff --git a/api/next/70780.txt b/api/next/70780.txt
deleted file mode 100644
index 2843836ac8..0000000000
--- a/api/next/70780.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-pkg unicode, var CategoryAliases map[string]string #70780
-pkg unicode, var Cn *RangeTable #70780
-pkg unicode, var LC *RangeTable #70780
diff --git a/api/next/71122.txt b/api/next/71122.txt
deleted file mode 100644
index a679899e0c..0000000000
--- a/api/next/71122.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg go/parser, func ParseDir //deprecated #71122
diff --git a/api/next/71920.txt b/api/next/71920.txt
deleted file mode 100644
index c15759f45f..0000000000
--- a/api/next/71920.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg crypto/tls, type Config struct, GetEncryptedClientHelloKeys func(*ClientHelloInfo) ([]EncryptedClientHelloKey, error) #71920
diff --git a/api/next/72843.txt b/api/next/72843.txt
deleted file mode 100644
index efd45ccc6f..0000000000
--- a/api/next/72843.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-pkg debug/elf, const PT_RISCV_ATTRIBUTES = 1879048195 #72843
-pkg debug/elf, const PT_RISCV_ATTRIBUTES ProgType #72843
-pkg debug/elf, const SHT_RISCV_ATTRIBUTES = 1879048195 #72843
-pkg debug/elf, const SHT_RISCV_ATTRIBUTES SectionType #72843
diff --git a/api/next/73088.txt b/api/next/73088.txt
deleted file mode 100644
index 2d15b83816..0000000000
--- a/api/next/73088.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-pkg go/ast, const FilterFuncDuplicates //deprecated #73088
-pkg go/ast, const FilterImportDuplicates //deprecated #73088
-pkg go/ast, const FilterUnassociatedComments //deprecated #73088
-pkg go/ast, func FilterPackage //deprecated #73088
-pkg go/ast, func MergePackageFiles //deprecated #73088
-pkg go/ast, func PackageExports //deprecated #73088
-pkg go/ast, type MergeMode //deprecated #73088
diff --git a/api/next/73126.txt b/api/next/73126.txt
deleted file mode 100644
index 9392448c02..0000000000
--- a/api/next/73126.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-pkg os, method (*Root) ReadFile(string) ([]uint8, error) #73126
-pkg os, method (*Root) WriteFile(string, []uint8, fs.FileMode) error #73126
diff --git a/api/next/73193.txt b/api/next/73193.txt
deleted file mode 100644
index f2b6ea748c..0000000000
--- a/api/next/73193.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg runtime, func SetDefaultGOMAXPROCS() #73193
diff --git a/api/next/73205.txt b/api/next/73205.txt
deleted file mode 100644
index 3cc2c09543..0000000000
--- a/api/next/73205.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg go/token, method (*FileSet) AddExistingFiles(...*File) #73205
diff --git a/api/next/73319.txt b/api/next/73319.txt
deleted file mode 100644
index 39a3ece5f8..0000000000
--- a/api/next/73319.txt
+++ /dev/null
@@ -1 +0,0 @@
-pkg go/ast, func PreorderStack(Node, []Node, func(Node, []Node) bool) #73319
diff --git a/api/next/73626.txt b/api/next/73626.txt
deleted file mode 100644
index ef4d0683b2..0000000000
--- a/api/next/73626.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-pkg net/http, func NewCrossOriginProtection() *CrossOriginProtection #73626
-pkg net/http, method (*CrossOriginProtection) AddInsecureBypassPattern(string) #73626
-pkg net/http, method (*CrossOriginProtection) AddTrustedOrigin(string) error #73626
-pkg net/http, method (*CrossOriginProtection) Check(*Request) error #73626
-pkg net/http, method (*CrossOriginProtection) Handler(Handler) Handler #73626
-pkg net/http, method (*CrossOriginProtection) SetDenyHandler(Handler) #73626
-pkg net/http, type CrossOriginProtection struct #73626
diff --git a/doc/next/1-intro.md b/doc/next/1-intro.md
deleted file mode 100644
index 77a9aed59f..0000000000
--- a/doc/next/1-intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-## DRAFT RELEASE NOTES — Introduction to Go 1.N {#introduction}
-
-**Go 1.25 is not yet released. These are work-in-progress release notes.
-Go 1.25 is expected to be released in August 2025.**
diff --git a/doc/next/2-language.md b/doc/next/2-language.md
deleted file mode 100644
index 61030bd676..0000000000
--- a/doc/next/2-language.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## Changes to the language {#language}
-
-
diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md
deleted file mode 100644
index b61848bca7..0000000000
--- a/doc/next/3-tools.md
+++ /dev/null
@@ -1,42 +0,0 @@
-## Tools {#tools}
-
-### Go command {#go-command}
-
-The `go build` `-asan` option now defaults to doing leak detection at
-program exit.
-This will report an error if memory allocated by C is not freed and is
-not referenced by any other memory allocated by either C or Go.
-These new error reports may be disabled by setting
-`ASAN_OPTIONS=detect_leaks=0` in the environment when running the
-program.
-
-
-
-The new `work` package pattern matches all packages in the work (formerly called main)
-modules: either the single work module in module mode or the set of workspace modules
-in workspace mode.
-
-
-
-When the go command updates the `go` line in a `go.mod` or `go.work` file,
-it [no longer](/ref/mod#go-mod-file-toolchain) adds a toolchain line
-specifying the command's current version.
-
-### Cgo {#cgo}
-
-### Vet {#vet}
-
-The `go vet` command includes new analyzers:
-
-
-
-- [waitgroup](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup),
- which reports misplaced calls to [sync.WaitGroup.Add]; and
-
-
-
-- [hostport](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/hostport),
- which reports uses of `fmt.Sprintf("%s:%d", host, port)` to
- construct addresses for [net.Dial], as these will not work with
- IPv6; instead it suggests using [net.JoinHostPort].
-
diff --git a/doc/next/4-runtime.md b/doc/next/4-runtime.md
deleted file mode 100644
index 67c1cee401..0000000000
--- a/doc/next/4-runtime.md
+++ /dev/null
@@ -1,63 +0,0 @@
-## Runtime {#runtime}
-
-
-
-The message printed when a program exits due to an unhandled panic
-that was recovered and repanicked no longer repeats the text of
-the panic value.
-
-Previously, a program which panicked with `panic("PANIC")`,
-recovered the panic, and then repanicked with the original
-value would print:
-
- panic: PANIC [recovered]
- panic: PANIC
-
-This program will now print:
-
- panic: PANIC [recovered, repanicked]
-
-
-
-The default behavior of the `GOMAXPROCS` has changed. In prior versions of Go,
-`GOMAXPROCS` defaults to the number of logical CPUs available at startup
-([runtime.NumCPU]). Go 1.25 introduces two changes:
-
-1. On Linux, the runtime considers the CPU bandwidth limit of the cgroup
- containing the process, if any. If the CPU bandwidth limit is lower than the
- number of logical CPUs available, `GOMAXPROCS` will default to the lower
- limit. In container runtime systems like Kubernetes, cgroup CPU bandwidth
- limits generally correspond to the "CPU limit" option. The Go runtime does
- not consider the "CPU requests" option.
-
-2. On all OSes, the runtime periodically updates `GOMAXPROCS` if the number
- of logical CPUs available or the cgroup CPU bandwidth limit change.
-
-Both of these behaviors are automatically disabled if `GOMAXPROCS` is set
-manually via the `GOMAXPROCS` environment variable or a call to
-[runtime.GOMAXPROCS]. They can also be disabled explicitly with the [GODEBUG
-settings](/doc/godebug) `containermaxprocs=0` and `updatemaxprocs=0`,
-respectively.
-
-In order to support reading updated cgroup limits, the runtime will keep cached
-file descriptors for the cgroup files for the duration of the process lifetime.
-
-
-
-On Linux systems with kernel support for anonymous VMA names
-(`CONFIG_ANON_VMA_NAME`), the Go runtime will annotate anonymous memory
-mappings with context about their purpose. e.g., `[anon: Go: heap]` for heap
-memory. This can be disabled with the [GODEBUG setting](/doc/godebug)
-`decoratemappings=0`.
-
-
-
-A new experimental garbage collector is now available as an experiment. The
-new design aims to improve the efficiency of garbage collection through better
-locality and CPU scalability in the mark algorithm. Benchmark result vary, but
-we expect somewhere between a 10—40% reduction in garbage collection overhead
-in real-world programs that heavily use the garbage collector.
-
-The new garbage collector may be enabled by setting `GOEXPERIMENT=greenteagc`
-at build time. See the [GitHub issue](/issue/73581) for more details on the design
-and instructions on how to report feedback.
diff --git a/doc/next/5-toolchain.md b/doc/next/5-toolchain.md
deleted file mode 100644
index 84a7624bb5..0000000000
--- a/doc/next/5-toolchain.md
+++ /dev/null
@@ -1,56 +0,0 @@
-## Compiler {#compiler}
-
-
-
-The compiler and linker in Go 1.25 now generate debug information
-using [DWARF version 5](https://dwarfstd.org/dwarf5std.html); the
-newer DWARF version reduces the space required for debugging
-information in Go binaries.
-DWARF 5 generation is gated by the "dwarf5" GOEXPERIMENT; this
-functionality can be disabled (for now) using GOEXPERIMENT=nodwarf5.
-
-
-
-The compiler [has been fixed](/cl/657715)
-to ensure that nil pointer checks are performed promptly. Programs like the following,
-which used to execute successfully, will now panic with a nil-pointer exception:
-
-```
-package main
-
-import "os"
-
-func main() {
- f, err := os.Open("nonExistentFile")
- name := f.Name()
- if err != nil {
- return
- }
- println(name)
-}
-```
-
-This program is incorrect in that it uses the result of `os.Open` before checking
-the error. The main result of `os.Open` can be a nil pointer if the error result is non-nil.
-But because of [a compiler bug](/issue/72860), this program ran successfully under
-Go versions 1.21 through 1.24 (in violation of the Go spec). It will no longer run
-successfully in Go 1.25. If this change is affecting your code, the solution is to put
-the non-nil error check earlier in your code, preferably immediately after
-the error-generating statement.
-
-
-
-The compiler can now allocate the backing store for slices on the
-stack in more situations, which improves performance. This change has
-the potential to amplify the effects of incorrect
-[unsafe.Pointer](/pkg/unsafe#Pointer) usage, see for example [issue
-73199](/issue/73199). In order to track down these problems, the
-[bisect tool](https://pkg.go.dev/golang.org/x/tools/cmd/bisect) can be
-used to find the allocation causing trouble using the
-`-compile=variablemake` flag. All such new stack allocations can also
-be turned off using `-gcflags=all=-d=variablemakehash=n`.
-
-## Assembler {#assembler}
-
-## Linker {#linker}
-
diff --git a/doc/next/6-stdlib/0-heading.md b/doc/next/6-stdlib/0-heading.md
deleted file mode 100644
index a992170d43..0000000000
--- a/doc/next/6-stdlib/0-heading.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## Standard library {#library}
-
diff --git a/doc/next/6-stdlib/1-synctest.md b/doc/next/6-stdlib/1-synctest.md
deleted file mode 100644
index 0a34930470..0000000000
--- a/doc/next/6-stdlib/1-synctest.md
+++ /dev/null
@@ -1,12 +0,0 @@
-### New testing/synctest package
-
-
-The new [testing/synctest](/pkg/testing/synctest) package
-provides support for testing concurrent code.
-
-The [synctest.Test] function runs a test function in an isolated
-"bubble". Within the bubble, [time](/pkg/time) package functions
-operate on a fake clock.
-
-The [synctest.Wait] function waits for all goroutines in the
-current bubble to block.
diff --git a/doc/next/6-stdlib/99-minor/0-heading.md b/doc/next/6-stdlib/99-minor/0-heading.md
deleted file mode 100644
index a98105e8cc..0000000000
--- a/doc/next/6-stdlib/99-minor/0-heading.md
+++ /dev/null
@@ -1,3 +0,0 @@
-### Minor changes to the library {#minor_library_changes}
-
-
diff --git a/doc/next/6-stdlib/99-minor/README b/doc/next/6-stdlib/99-minor/README
deleted file mode 100644
index fac778de05..0000000000
--- a/doc/next/6-stdlib/99-minor/README
+++ /dev/null
@@ -1 +0,0 @@
-API changes and other small changes to the standard library go here.
diff --git a/doc/next/6-stdlib/99-minor/archive/tar/49580.md b/doc/next/6-stdlib/99-minor/archive/tar/49580.md
deleted file mode 100644
index 8fa43681fa..0000000000
--- a/doc/next/6-stdlib/99-minor/archive/tar/49580.md
+++ /dev/null
@@ -1,2 +0,0 @@
-The [*Writer.AddFS] implementation now supports symbolic links
-for filesystems that implement [io/fs.ReadLinkFS].
diff --git a/doc/next/6-stdlib/99-minor/crypto/63405.md b/doc/next/6-stdlib/99-minor/crypto/63405.md
deleted file mode 100644
index d16dc5ab00..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/63405.md
+++ /dev/null
@@ -1 +0,0 @@
-[MessageSigner] is a new signing interface that can be implemented by signers that wish to hash the message to be signed themselves. A new function is also introduced, [SignMessage] which attempts to update a [Signer] interface to [MessageSigner], using the [MessageSigner.SignMessage] method if successful, and [Signer.Sign] if not. This can be used when code wishes to support both [Signer] and [MessageSigner].
\ No newline at end of file
diff --git a/doc/next/6-stdlib/99-minor/crypto/ecdsa/63963.md b/doc/next/6-stdlib/99-minor/crypto/ecdsa/63963.md
deleted file mode 100644
index 5c329c7d51..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/ecdsa/63963.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The new [ParseRawPrivateKey], [ParseUncompressedPublicKey], [PrivateKey.Bytes],
-and [PublicKey.Bytes] functions and methods implement low-level encodings,
-replacing the need to use crypto/elliptic or math/big functions and methods.
diff --git a/doc/next/6-stdlib/99-minor/crypto/elliptic/hidden.md b/doc/next/6-stdlib/99-minor/crypto/elliptic/hidden.md
deleted file mode 100644
index eb3bef50d3..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/elliptic/hidden.md
+++ /dev/null
@@ -1,2 +0,0 @@
-The hidden and undocumented `Inverse` and `CombinedMult` methods on some [Curve]
-implementations have been removed.
diff --git a/doc/next/6-stdlib/99-minor/crypto/sha3/69521.md b/doc/next/6-stdlib/99-minor/crypto/sha3/69521.md
deleted file mode 100644
index 2af674dcb4..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/sha3/69521.md
+++ /dev/null
@@ -1 +0,0 @@
-The new [SHA3.Clone] method implements [hash.Cloner](/pkg/hash#Cloner).
diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/67516.md b/doc/next/6-stdlib/99-minor/crypto/tls/67516.md
deleted file mode 100644
index 3790533d16..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/tls/67516.md
+++ /dev/null
@@ -1,2 +0,0 @@
-The new [ConnectionState.CurveID] field exposes the key exchange mechanism used
-to establish the connection.
diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/71920.md b/doc/next/6-stdlib/99-minor/crypto/tls/71920.md
deleted file mode 100644
index 848211751a..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/tls/71920.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The new [Config.GetEncryptedClientHelloKeys] callback can be used to set the
-[EncryptedClientHelloKey]s for a server to use when a client sends an Encrypted
-Client Hello extension.
\ No newline at end of file
diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/72883.md b/doc/next/6-stdlib/99-minor/crypto/tls/72883.md
deleted file mode 100644
index 70e06192a3..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/tls/72883.md
+++ /dev/null
@@ -1,3 +0,0 @@
-SHA-1 signature algorithms are now disallowed in TLS 1.2 handshakes, per
-[RFC 9155](https://www.rfc-editor.org/rfc/rfc9155.html).
-They can be re-enabled with the `tlssha1=1` GODEBUG option.
diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/fips.md b/doc/next/6-stdlib/99-minor/crypto/tls/fips.md
deleted file mode 100644
index 0f0c9459ce..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/tls/fips.md
+++ /dev/null
@@ -1,2 +0,0 @@
-When [FIPS 140-3 mode](/doc/security/fips140) is enabled, Extended Master Secret
-is now required in TLS 1.2, and Ed25519 and X25519MLKEM768 are now allowed.
diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/version_pref.md b/doc/next/6-stdlib/99-minor/crypto/tls/version_pref.md
deleted file mode 100644
index 5686f3ca0a..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/tls/version_pref.md
+++ /dev/null
@@ -1 +0,0 @@
-TLS servers now prefer the highest supported protocol version, even if it isn't the client's most preferred protocol version.
diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/63405.md b/doc/next/6-stdlib/99-minor/crypto/x509/63405.md
deleted file mode 100644
index 4c3a1750da..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/x509/63405.md
+++ /dev/null
@@ -1 +0,0 @@
-[CreateCertificate], [CreateCertificateRequest], and [CreateRevocationList] can now accept a [crypto.MessageSigner] signing interface as well as [crypto.Signer]. This allows these functions to use signers which implement "one-shot" signing interfaces, where hashing is done as part of the signing operation, instead of by the caller.
\ No newline at end of file
diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/71746.md b/doc/next/6-stdlib/99-minor/crypto/x509/71746.md
deleted file mode 100644
index 44e60293d3..0000000000
--- a/doc/next/6-stdlib/99-minor/crypto/x509/71746.md
+++ /dev/null
@@ -1,2 +0,0 @@
-[CreateCertificate] now uses truncated SHA-256 to populate the `SubjectKeyId` if
-it is missing. The GODEBUG setting `x509sha256skid=0` reverts to SHA-1.
diff --git a/doc/next/6-stdlib/99-minor/debug/elf/72843.md b/doc/next/6-stdlib/99-minor/debug/elf/72843.md
deleted file mode 100644
index 491c2dc1a1..0000000000
--- a/doc/next/6-stdlib/99-minor/debug/elf/72843.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The [debug/elf] package adds two new constants:
-- [PT_RISCV_ATTRIBUTES]
-- [SHT_RISCV_ATTRIBUTES]
-for RISC-V ELF parsing.
diff --git a/doc/next/6-stdlib/99-minor/go/ast/73088.md b/doc/next/6-stdlib/99-minor/go/ast/73088.md
deleted file mode 100644
index e7035a7047..0000000000
--- a/doc/next/6-stdlib/99-minor/go/ast/73088.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The [ast.FilterPackage], [ast.PackageExports], and
-[ast.MergePackageFiles] functions, and the [MergeMode] type and its
-constants, are all deprecated, as they are for use only with the
-long-deprecated [ast.Object] and [ast.Package] machinery.
diff --git a/doc/next/6-stdlib/99-minor/go/ast/73319.md b/doc/next/6-stdlib/99-minor/go/ast/73319.md
deleted file mode 100644
index b99e20e316..0000000000
--- a/doc/next/6-stdlib/99-minor/go/ast/73319.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The new [PreorderStack] function, like [Inspect], traverses a syntax
-tree and provides control over descent into subtrees, but as a
-convenience it also provides the stack of enclosing nodes at each
-point.
diff --git a/doc/next/6-stdlib/99-minor/go/parser/71122.md b/doc/next/6-stdlib/99-minor/go/parser/71122.md
deleted file mode 100644
index 2043d30403..0000000000
--- a/doc/next/6-stdlib/99-minor/go/parser/71122.md
+++ /dev/null
@@ -1 +0,0 @@
-The [ParseDir] function is deprecated.
diff --git a/doc/next/6-stdlib/99-minor/go/token/73205.md b/doc/next/6-stdlib/99-minor/go/token/73205.md
deleted file mode 100644
index d743663736..0000000000
--- a/doc/next/6-stdlib/99-minor/go/token/73205.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The new [FileSet.AddExistingFiles] method enables existing Files to be
-added to a FileSet, or a FileSet to be constructed for an arbitrary
-set of Files, alleviating the problems associated with a single global
-FileSet in long-lived applications.
diff --git a/doc/next/6-stdlib/99-minor/go/types/70250.md b/doc/next/6-stdlib/99-minor/go/types/70250.md
deleted file mode 100644
index 49fbdadfe9..0000000000
--- a/doc/next/6-stdlib/99-minor/go/types/70250.md
+++ /dev/null
@@ -1,3 +0,0 @@
-[Var] now has a [Var.Kind] method that classifies the variable as one
-of: package-level, receiver, parameter, result, or local variable, or
-a struct field.
diff --git a/doc/next/6-stdlib/99-minor/go/types/70737.md b/doc/next/6-stdlib/99-minor/go/types/70737.md
deleted file mode 100644
index 6d1b4136bf..0000000000
--- a/doc/next/6-stdlib/99-minor/go/types/70737.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The new [LookupSelection] function looks up the field or method of a
-given name and receiver type, like the existing [LookupFieldOrMethod]
-function, but returns the result in the form of a [Selection].
diff --git a/doc/next/6-stdlib/99-minor/hash/69518.md b/doc/next/6-stdlib/99-minor/hash/69518.md
deleted file mode 100644
index ae9e133cd7..0000000000
--- a/doc/next/6-stdlib/99-minor/hash/69518.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The new [XOF](/pkg/hash#XOF) interface can be implemented by "extendable output
-functions", which are hash functions with arbitrary or unlimited output length
-such as [SHAKE](https://pkg.go.dev/crypto/sha3#SHAKE).
diff --git a/doc/next/6-stdlib/99-minor/hash/69521.md b/doc/next/6-stdlib/99-minor/hash/69521.md
deleted file mode 100644
index a8d58e3074..0000000000
--- a/doc/next/6-stdlib/99-minor/hash/69521.md
+++ /dev/null
@@ -1,2 +0,0 @@
-Hashes implementing the new [Cloner] interface can return a copy of their state.
-All standard library [Hash] implementations now implement [Cloner].
diff --git a/doc/next/6-stdlib/99-minor/hash/maphash/69521.md b/doc/next/6-stdlib/99-minor/hash/maphash/69521.md
deleted file mode 100644
index 497df8b6aa..0000000000
--- a/doc/next/6-stdlib/99-minor/hash/maphash/69521.md
+++ /dev/null
@@ -1 +0,0 @@
-The new [Hash.Clone] method implements [hash.Cloner](/pkg/hash#Cloner).
diff --git a/doc/next/6-stdlib/99-minor/io/fs/49580.md b/doc/next/6-stdlib/99-minor/io/fs/49580.md
deleted file mode 100644
index c1cba5a395..0000000000
--- a/doc/next/6-stdlib/99-minor/io/fs/49580.md
+++ /dev/null
@@ -1 +0,0 @@
-A new [ReadLinkFS] interface provides the ability to read symbolic links in a filesystem.
diff --git a/doc/next/6-stdlib/99-minor/log/slog/66365.md b/doc/next/6-stdlib/99-minor/log/slog/66365.md
deleted file mode 100644
index b6b0c81fe5..0000000000
--- a/doc/next/6-stdlib/99-minor/log/slog/66365.md
+++ /dev/null
@@ -1 +0,0 @@
-[GroupAttrs] creates a group [Attr] from a slice of [Attr] values.
diff --git a/doc/next/6-stdlib/99-minor/log/slog/70280.md b/doc/next/6-stdlib/99-minor/log/slog/70280.md
deleted file mode 100644
index 7f1b734d4f..0000000000
--- a/doc/next/6-stdlib/99-minor/log/slog/70280.md
+++ /dev/null
@@ -1 +0,0 @@
-[Record] now has a Source() method, returning its source location or nil if unavailable.
diff --git a/doc/next/6-stdlib/99-minor/mime/multipart/46771.md b/doc/next/6-stdlib/99-minor/mime/multipart/46771.md
deleted file mode 100644
index b8b8641b78..0000000000
--- a/doc/next/6-stdlib/99-minor/mime/multipart/46771.md
+++ /dev/null
@@ -1,2 +0,0 @@
-The new helper function [FieldContentDisposition] builds multipart
-Content-Disposition header fields.
\ No newline at end of file
diff --git a/doc/next/6-stdlib/99-minor/net/10350.md b/doc/next/6-stdlib/99-minor/net/10350.md
deleted file mode 100644
index 7290112f41..0000000000
--- a/doc/next/6-stdlib/99-minor/net/10350.md
+++ /dev/null
@@ -1,3 +0,0 @@
-On Windows, the [TCPConn.File], [UDPConn.File], [UnixConn.File],
-[IPConn.File], [TCPListener.File], and [UnixListener.File]
-methods are now supported.
\ No newline at end of file
diff --git a/doc/next/6-stdlib/99-minor/net/56025.md b/doc/next/6-stdlib/99-minor/net/56025.md
deleted file mode 100644
index 2e3b230ef0..0000000000
--- a/doc/next/6-stdlib/99-minor/net/56025.md
+++ /dev/null
@@ -1,5 +0,0 @@
-[LookupMX] and [*Resolver.LookupMX] now return DNS names that look
-like valid IP address, as well as valid domain names.
-Previously if a name server returned an IP address as a DNS name,
-LookupMX would discard it, as required by the RFCs.
-However, name servers in practice do sometimes return IP addresses.
diff --git a/doc/next/6-stdlib/99-minor/net/63529.md b/doc/next/6-stdlib/99-minor/net/63529.md
deleted file mode 100644
index 4cf05c90cd..0000000000
--- a/doc/next/6-stdlib/99-minor/net/63529.md
+++ /dev/null
@@ -1 +0,0 @@
-On Windows, the [ListenMulticastUDP] now supports IPv6 addresses.
diff --git a/doc/next/6-stdlib/99-minor/net/9503.md b/doc/next/6-stdlib/99-minor/net/9503.md
deleted file mode 100644
index d2aef10132..0000000000
--- a/doc/next/6-stdlib/99-minor/net/9503.md
+++ /dev/null
@@ -1,2 +0,0 @@
-On Windows, the [FileConn], [FilePacketConn], [FileListener]
-functions are now supported.
diff --git a/doc/next/6-stdlib/99-minor/net/http/73626.md b/doc/next/6-stdlib/99-minor/net/http/73626.md
deleted file mode 100644
index 88a204b8a4..0000000000
--- a/doc/next/6-stdlib/99-minor/net/http/73626.md
+++ /dev/null
@@ -1,7 +0,0 @@
-The new [CrossOriginProtection] implements protections against [Cross-Site
-Request Forgery (CSRF)][] by rejecting non-safe cross-origin browser requests.
-It uses [modern browser Fetch metadata][Sec-Fetch-Site], doesn't require tokens
-or cookies, and supports origin-based and pattern-based bypasses.
-
-[Sec-Fetch-Site]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Site
-[Cross-Site Request Forgery (CSRF)]: https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/CSRF
diff --git a/doc/next/6-stdlib/99-minor/os/15388.md b/doc/next/6-stdlib/99-minor/os/15388.md
deleted file mode 100644
index 04b3e91d8b..0000000000
--- a/doc/next/6-stdlib/99-minor/os/15388.md
+++ /dev/null
@@ -1,14 +0,0 @@
-On Windows, [NewFile] now supports handles opened for asynchronous I/O (that is,
-[syscall.FILE_FLAG_OVERLAPPED] is specified in the [syscall.CreateFile] call).
-These handles are associated with the Go runtime's I/O completion port,
-which provides the following benefits for the resulting [File]:
-
-- I/O methods ([File.Read], [File.Write], [File.ReadAt], and [File.WriteAt]) do not block an OS thread.
-- Deadline methods ([File.SetDeadline], [File.SetReadDeadline], and [File.SetWriteDeadline]) are supported.
-
-This enhancement is especially beneficial for applications that communicate via named pipes on Windows.
-
-Note that a handle can only be associated with one completion port at a time.
-If the handle provided to [NewFile] is already associated with a completion port,
-the returned [File] is downgraded to synchronous I/O mode.
-In this case, I/O methods will block an OS thread, and the deadline methods have no effect.
diff --git a/doc/next/6-stdlib/99-minor/os/49580.md b/doc/next/6-stdlib/99-minor/os/49580.md
deleted file mode 100644
index 18d8831e7b..0000000000
--- a/doc/next/6-stdlib/99-minor/os/49580.md
+++ /dev/null
@@ -1,2 +0,0 @@
-The filesystem returned by [DirFS] implements the new [io/fs.ReadLinkFS] interface.
-[CopyFS] supports symlinks when copying filesystems that implement [io/fs.ReadLinkFS].
diff --git a/doc/next/6-stdlib/99-minor/os/67002.md b/doc/next/6-stdlib/99-minor/os/67002.md
deleted file mode 100644
index 481a2c171c..0000000000
--- a/doc/next/6-stdlib/99-minor/os/67002.md
+++ /dev/null
@@ -1,14 +0,0 @@
-The [os.Root] type supports the following additional methods:
-
- * [os.Root.Chmod]
- * [os.Root.Chown]
- * [os.Root.Chtimes]
- * [os.Root.Lchown]
- * [os.Root.Link]
- * [os.Root.MkdirAll]
- * [os.Root.ReadFile]
- * [os.Root.Readlink]
- * [os.Root.RemoveAll]
- * [os.Root.Rename]
- * [os.Root.Symlink]
- * [os.Root.WriteFile]
diff --git a/doc/next/6-stdlib/99-minor/os/73126.md b/doc/next/6-stdlib/99-minor/os/73126.md
deleted file mode 100644
index 1cd40d79ee..0000000000
--- a/doc/next/6-stdlib/99-minor/os/73126.md
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/doc/next/6-stdlib/99-minor/reflect/62121.md b/doc/next/6-stdlib/99-minor/reflect/62121.md
deleted file mode 100644
index f6148ceb60..0000000000
--- a/doc/next/6-stdlib/99-minor/reflect/62121.md
+++ /dev/null
@@ -1,3 +0,0 @@
-The new [TypeAssert] function permits converting a [Value] directly to a Go value
-of the given type. This is like using a type assertion on the result of [Value.Interface],
-but avoids unnecessary memory allocations.
diff --git a/doc/next/6-stdlib/99-minor/regexp/syntax/70781.md b/doc/next/6-stdlib/99-minor/regexp/syntax/70781.md
deleted file mode 100644
index 63794b4671..0000000000
--- a/doc/next/6-stdlib/99-minor/regexp/syntax/70781.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The `\p{name}` and `\P{name}` character class syntaxes now accept the names
-Any, ASCII, Assigned, Cn, and LC, as well as Unicode category aliases like `\p{Letter}` for `\pL`.
-Following [Unicode TR18](https://unicode.org/reports/tr18/), they also now use
-case-insensitive name lookups, ignoring spaces, underscores, and hyphens.
diff --git a/doc/next/6-stdlib/99-minor/runtime/71825.md b/doc/next/6-stdlib/99-minor/runtime/71825.md
deleted file mode 100644
index 156d244643..0000000000
--- a/doc/next/6-stdlib/99-minor/runtime/71825.md
+++ /dev/null
@@ -1,5 +0,0 @@
-Cleanup functions scheduled by [AddCleanup] are now executed
-concurrently and in parallel, making cleanups more viable for heavy
-use like the [unique] package. Note that individual cleanups should
-still shunt their work to a new goroutine if they must execute or
-block for a long time to avoid blocking the cleanup queue.
diff --git a/doc/next/6-stdlib/99-minor/runtime/72949.md b/doc/next/6-stdlib/99-minor/runtime/72949.md
deleted file mode 100644
index 6bab38d94c..0000000000
--- a/doc/next/6-stdlib/99-minor/runtime/72949.md
+++ /dev/null
@@ -1,8 +0,0 @@
-When `GODEBUG=checkfinalizers=1` is set, the runtime will run
-diagnostics on each garbage collection cycle to find common issues
-with how the program might use finalizers and cleanups, such as those
-described [in the GC
-guide](/doc/gc-guide#Finalizers_cleanups_and_weak_pointers). In this
-mode, the runtime will also regularly report the finalizer and
-cleanup queue lengths to stderr to help identify issues with
-long-running finalizers and/or cleanups.
diff --git a/doc/next/6-stdlib/99-minor/runtime/73193.md b/doc/next/6-stdlib/99-minor/runtime/73193.md
deleted file mode 100644
index a729f6a3c4..0000000000
--- a/doc/next/6-stdlib/99-minor/runtime/73193.md
+++ /dev/null
@@ -1,5 +0,0 @@
-The new [SetDefaultGOMAXPROCS] function sets `GOMAXPROCS` to the runtime
-default value, as if the `GOMAXPROCS` environment variable is not set. This is
-useful for enabling the [new `GOMAXPROCS` default](#runtime) if it has been
-disabled by the `GOMAXPROCS` environment variable or a prior call to
-[GOMAXPROCS].
diff --git a/doc/next/6-stdlib/99-minor/runtime/pprof/66999.md b/doc/next/6-stdlib/99-minor/runtime/pprof/66999.md
deleted file mode 100644
index f222628aae..0000000000
--- a/doc/next/6-stdlib/99-minor/runtime/pprof/66999.md
+++ /dev/null
@@ -1,6 +0,0 @@
-The mutex profile for contention on runtime-internal locks now correctly points
-to the end of the critical section that caused the delay. This matches the
-profile's behavior for contention on `sync.Mutex` values. The
-`runtimecontentionstacks` setting for `GODEBUG`, which allowed opting in to the
-unusual behavior of Go 1.22 through 1.24 for this part of the profile, is now
-gone.
diff --git a/doc/next/6-stdlib/99-minor/runtime/trace/63185.md b/doc/next/6-stdlib/99-minor/runtime/trace/63185.md
deleted file mode 100644
index 80ba088b75..0000000000
--- a/doc/next/6-stdlib/99-minor/runtime/trace/63185.md
+++ /dev/null
@@ -1,2 +0,0 @@
-
-TODO The flight recorder has been added to the runtime/trace package.
diff --git a/doc/next/6-stdlib/99-minor/sync/63796.md b/doc/next/6-stdlib/99-minor/sync/63796.md
deleted file mode 100644
index 60d91a949a..0000000000
--- a/doc/next/6-stdlib/99-minor/sync/63796.md
+++ /dev/null
@@ -1,2 +0,0 @@
-[WaitGroup] has added a new method [WaitGroup.Go],
-that makes the common pattern of creating and counting goroutines more convenient.
diff --git a/doc/next/6-stdlib/99-minor/testing/43936.md b/doc/next/6-stdlib/99-minor/testing/43936.md
deleted file mode 100644
index 5be98d5db8..0000000000
--- a/doc/next/6-stdlib/99-minor/testing/43936.md
+++ /dev/null
@@ -1,10 +0,0 @@
-The new methods [T.Attr], [B.Attr], and [F.Attr] emit an
-attribute to the test log. An attribute is an arbitrary
-key and value associated with a test.
-
-For example, in a test named `TestAttr`,
-`t.Attr("key", "value")` emits:
-
-```
-=== ATTR TestAttr key value
-```
diff --git a/doc/next/6-stdlib/99-minor/testing/59928.md b/doc/next/6-stdlib/99-minor/testing/59928.md
deleted file mode 100644
index 6879a10d63..0000000000
--- a/doc/next/6-stdlib/99-minor/testing/59928.md
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-The new [Output] method of [testing.T], [testing.B] and [testing.F] provides a Writer
-that writes to the same test output stream as [TB.Log], but omits the file and line number.
diff --git a/doc/next/6-stdlib/99-minor/testing/fstest/49580.md b/doc/next/6-stdlib/99-minor/testing/fstest/49580.md
deleted file mode 100644
index 5b3c0d6a84..0000000000
--- a/doc/next/6-stdlib/99-minor/testing/fstest/49580.md
+++ /dev/null
@@ -1,3 +0,0 @@
-[MapFS] implements the new [io/fs.ReadLinkFS] interface.
-[TestFS] will verify the functionality of the [io/fs.ReadLinkFS] interface if implemented.
-[TestFS] will no longer follow symlinks to avoid unbounded recursion.
diff --git a/doc/next/6-stdlib/99-minor/testing/synctest/67434.md b/doc/next/6-stdlib/99-minor/testing/synctest/67434.md
deleted file mode 100644
index d36a55111c..0000000000
--- a/doc/next/6-stdlib/99-minor/testing/synctest/67434.md
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/doc/next/6-stdlib/99-minor/unicode/70780.md b/doc/next/6-stdlib/99-minor/unicode/70780.md
deleted file mode 100644
index d799ca0c35..0000000000
--- a/doc/next/6-stdlib/99-minor/unicode/70780.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The new [CategoryAliases] map provides access to category alias names, such as “Letter” for “L”.
-The new categories [Cn] and [LC] define unassigned codepoints and cased letters, respectively.
-These have always been defined by Unicode but were inadvertently omitted in earlier versions of Go.
-The [C] category now includes [Cn], meaning it has added all unassigned code points.
diff --git a/doc/next/6-stdlib/99-minor/unique/71772.md b/doc/next/6-stdlib/99-minor/unique/71772.md
deleted file mode 100644
index 5b789446ae..0000000000
--- a/doc/next/6-stdlib/99-minor/unique/71772.md
+++ /dev/null
@@ -1,4 +0,0 @@
-The [unique] package now reclaims interned values more eagerly,
-more efficiently, and in parallel. As a consequence, applications using
-[Make] are now less likely to experience memory blow-up when lots of
-truly unique values are interned.
diff --git a/doc/next/6-stdlib/99-minor/unique/71846.md b/doc/next/6-stdlib/99-minor/unique/71846.md
deleted file mode 100644
index b1f86f0739..0000000000
--- a/doc/next/6-stdlib/99-minor/unique/71846.md
+++ /dev/null
@@ -1,4 +0,0 @@
-Values passed to [Make] containing [Handle]s previously required multiple
-garbage collection cycles to collect, proportional to the depth of the chain
-of [Handle] values. Now, they are collected promptly in a single cycle, once
-unused.
diff --git a/doc/next/7-ports.md b/doc/next/7-ports.md
deleted file mode 100644
index eb4f0d5a97..0000000000
--- a/doc/next/7-ports.md
+++ /dev/null
@@ -1,11 +0,0 @@
-## Ports {#ports}
-
-### Darwin
-
-
-As [announced](/doc/go1.24#darwin) in the Go 1.24 release notes, Go 1.25 requires macOS 12 Monterey or later; support for previous versions has been discontinued.
-
-### Windows
-
-
-Go 1.25 is the last release that contains the [broken](/doc/go1.24#windows) 32-bit windows/arm port (`GOOS=windows` `GOARCH=arm`). It will be removed in Go 1.26.
diff --git a/doc/next/9-todo.md b/doc/next/9-todo.md
deleted file mode 100644
index fa1c71084f..0000000000
--- a/doc/next/9-todo.md
+++ /dev/null
@@ -1,206 +0,0 @@
-
-
-### TODO
-
-**Please turn these into proper release notes**
-
-
-all: implement plugin build mode for riscv64
-
-
-cmd/link/internal/ld: introduce -funcalign=N option
-This patch adds linker option -funcalign=N that allows to set alignment
-for function entries.
-For \#72130.
-
-
-cmd/fix: automate migrations for simple deprecations
-
-
-cmd/go: allow serving module under the subdirectory of git repository
-cmd/go: add subdirectory support to go-import meta tag
-This CL adds ability to specify a subdirectory in the go-import meta tag.
-A go-import meta tag now will support:
-\
-Fixes: \#34055
-
-
-cmd/go: add global ignore mechanism for Go tooling ecosystem
-
-
-cmd/cover: extend coverage testing to include applications
-
-
-all: add GOARM64=v8.1 and so on
-runtime: check LSE support on ARM64 at runtime init
-Check presence of LSE support on ARM64 chip if we targeted it at compile
-time.
-Related to \#69124
-Updates \#60905
-Fixes \#71411
-
-
-all: add GORISCV64 environment variable
-cmd/go: add rva23u64 as a valid value for GORISCV64
-The RVA23 profile was ratified on the 21st of October 2024.
-https://riscv.org/announcements/2024/10/risc-v-announces-ratification-of-the-rva23-profile-standard/
-Now that it's ratified we can add rva23u64 as a valid value for the
-GORISCV64 environment variable. This will allow the compiler and
-assembler to generate instructions made mandatory by the new profile
-without a runtime check. Examples of such instructions include those
-introduced by the Vector and Zicond extensions.
-Setting GORISCV64=rva23u64 defines the riscv64.rva20u64,
-riscv64.rva22u64 and riscv64.rva23u64 build tags, sets the internal
-variable buildcfg.GORISCV64 to 23 and defines the macros
-GORISCV64_rva23u64, hasV, hasZba, hasZbb, hasZbs, hasZfa, and
-hasZicond for use in assembly language code.
-Updates \#61476
-
-
-math/rand/v2: revised API for math/rand
-rand: deprecate in favor of math/rand/v2
-For golang/go#61716
-Fixes golang/go#71373
-
-
-cmd/go: enable GOCACHEPROG by default
-cmd/go/internal/cacheprog: drop Request.ObjectID
-ObjectID was a misnaming of OutputID from cacheprog's initial
-implementation. It was maintained for compatibility with existing
-cacheprog users in 1.24 but can be removed in 1.25.
-
-
-cmd/go: doc -http should start a pkgsite instance and open a browser
-
-
-cmd/go: -json flag for go version -m
-cmd/go: support -json flag in go version
-It supports features described in the issue:
-- add -json flag for 'go version -m' to print json encoding of
- runtime/debug.BuildSetting to standard output.
-- report an error when specifying -json flag without -m.
-- print build settings on seperated line for each binary
-Fixes \#69712
-
-
-crypto: mechanism to enable FIPS mode
-
-
-spec: remove notion of core types
-
-
-cmd/go: add fips140 module selection mechanism
-lib/fips140: set inprocess.txt to v1.0.0
-
-
-testing: panic in AllocsPerRun during parallel test
-testing: panic in AllocsPerRun if parallel tests are running
-If other tests are running, AllocsPerRun's result will be inherently flaky.
-Saw this with CL 630136 and \#70327.
-Proposed in \#70464.
-Fixes \#70464.
-
-
-encoding/json/v2: add new JSON API behind a GOEXPERIMENT=jsonv2 guard
-
-
-cmd/go, cmd/distpack: build and run tools that are not necessary for builds as needed and don't include in binary distribution
-
-
diff --git a/lib/time/update.bash b/lib/time/update.bash
index 940596fb11..66494752ea 100755
--- a/lib/time/update.bash
+++ b/lib/time/update.bash
@@ -24,8 +24,8 @@
# in the CL match the update.bash in the CL.
# Versions to use.
-CODE=2025a
-DATA=2025a
+CODE=2025b
+DATA=2025b
set -e
diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip
index f8099b1b49..b107695d1e 100644
Binary files a/lib/time/zoneinfo.zip and b/lib/time/zoneinfo.zip differ
diff --git a/src/cmd/compile/default.pgo b/src/cmd/compile/default.pgo
index 65c28706ea..2c2588704f 100644
Binary files a/src/cmd/compile/default.pgo and b/src/cmd/compile/default.pgo differ
diff --git a/src/cmd/compile/internal/noder/doc.go b/src/cmd/compile/internal/noder/doc.go
index f76e5723b7..baf7c67463 100644
--- a/src/cmd/compile/internal/noder/doc.go
+++ b/src/cmd/compile/internal/noder/doc.go
@@ -39,8 +39,7 @@ kind. Go constructs are mapped onto (potentially multiple) elements.
Elements are accessed using an index relative to the start of the
section.
- // TODO(markfreeman): Rename to SectionIndex.
- RelIndex = Uint64 .
+ RelElemIdx = Uint64 .
## String Section
String values are stored as elements in the string section. Elements
@@ -147,7 +146,7 @@ referenced element.
.
RefTableEntry = [ Sync ]
SectionKind
- RelIndex
+ RelElemIdx
.
Elements encode references to other elements as an index in the
@@ -155,7 +154,7 @@ reference table — not the location of the referenced element directly.
// TODO(markfreeman): Rename to RefUse.
UseReloc = [ Sync ]
- RelIndex
+ RelElemIdx
.
# Primitives
diff --git a/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go
index a8ec2a278c..0f17843565 100644
--- a/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go
@@ -897,8 +897,8 @@ func init() {
inputs: []regMask{buildReg("DI")},
clobbers: buildReg("DI"),
},
- faultOnNilArg0: true,
- unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
+ //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
+ unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// arg0 = address of memory to zero
@@ -935,10 +935,10 @@ func init() {
inputs: []regMask{buildReg("DI"), buildReg("SI")},
clobbers: buildReg("DI SI X0"), // uses X0 as a temporary
},
- clobberFlags: true,
- faultOnNilArg0: true,
- faultOnNilArg1: true,
- unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
+ clobberFlags: true,
+ //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
+ //faultOnNilArg1: true,
+ unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// arg0 = destination pointer
diff --git a/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go
index 8ebbd7e95e..ebb7ed5299 100644
--- a/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go
+++ b/src/cmd/compile/internal/ssa/_gen/ARM64Ops.go
@@ -554,8 +554,8 @@ func init() {
inputs: []regMask{buildReg("R20")},
clobbers: buildReg("R16 R17 R20 R30"),
},
- faultOnNilArg0: true,
- unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
+ //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
+ unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
},
// large zeroing
@@ -595,9 +595,9 @@ func init() {
inputs: []regMask{buildReg("R21"), buildReg("R20")},
clobbers: buildReg("R16 R17 R20 R21 R26 R30"),
},
- faultOnNilArg0: true,
- faultOnNilArg1: true,
- unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
+ //faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
+ //faultOnNilArg1: true,
+ unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
},
// large move
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 90a38c783a..5d13f81841 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -13874,11 +13874,10 @@ var opcodeTable = [...]opInfo{
},
},
{
- name: "DUFFZERO",
- auxType: auxInt64,
- argLen: 2,
- faultOnNilArg0: true,
- unsafePoint: true,
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 2,
+ unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 128}, // DI
@@ -13948,13 +13947,11 @@ var opcodeTable = [...]opInfo{
},
},
{
- name: "DUFFCOPY",
- auxType: auxInt64,
- argLen: 3,
- clobberFlags: true,
- faultOnNilArg0: true,
- faultOnNilArg1: true,
- unsafePoint: true,
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ clobberFlags: true,
+ unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 128}, // DI
@@ -23039,11 +23036,10 @@ var opcodeTable = [...]opInfo{
},
},
{
- name: "DUFFZERO",
- auxType: auxInt64,
- argLen: 2,
- faultOnNilArg0: true,
- unsafePoint: true,
+ name: "DUFFZERO",
+ auxType: auxInt64,
+ argLen: 2,
+ unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 524288}, // R20
@@ -23065,12 +23061,10 @@ var opcodeTable = [...]opInfo{
},
},
{
- name: "DUFFCOPY",
- auxType: auxInt64,
- argLen: 3,
- faultOnNilArg0: true,
- faultOnNilArg1: true,
- unsafePoint: true,
+ name: "DUFFCOPY",
+ auxType: auxInt64,
+ argLen: 3,
+ unsafePoint: true,
reg: regInfo{
inputs: []inputInfo{
{0, 1048576}, // R21
diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go
index d262ab9f85..31a1aa2abe 100644
--- a/src/cmd/compile/internal/types2/check.go
+++ b/src/cmd/compile/internal/types2/check.go
@@ -11,6 +11,7 @@ import (
"fmt"
"go/constant"
. "internal/types/errors"
+ "os"
"sync/atomic"
)
@@ -419,7 +420,24 @@ func (check *Checker) handleBailout(err *error) {
// normal return or early exit
*err = check.firstErr
default:
- // TODO(markfreeman): dump posStack if available
+ if len(check.posStack) > 0 {
+ doPrint := func(ps []syntax.Pos) {
+ for i := len(ps) - 1; i >= 0; i-- {
+ fmt.Fprintf(os.Stderr, "\t%v\n", ps[i])
+ }
+ }
+
+ fmt.Fprintln(os.Stderr, "The following panic happened checking types near:")
+ if len(check.posStack) <= 10 {
+ doPrint(check.posStack)
+ } else {
+ // if it's long, truncate the middle; it's least likely to help
+ doPrint(check.posStack[len(check.posStack)-5:])
+ fmt.Fprintln(os.Stderr, "\t...")
+ doPrint(check.posStack[:5])
+ }
+ }
+
// re-panic
panic(p)
}
diff --git a/src/cmd/distpack/pack.go b/src/cmd/distpack/pack.go
index 8e0b58af21..4f14210e5f 100644
--- a/src/cmd/distpack/pack.go
+++ b/src/cmd/distpack/pack.go
@@ -171,7 +171,7 @@ func main() {
switch strings.TrimSuffix(path.Base(name), ".exe") {
default:
return false
- case "asm", "cgo", "compile", "cover", "link", "pack", "preprofile", "vet":
+ case "asm", "cgo", "compile", "cover", "link", "preprofile", "vet":
}
}
return true
diff --git a/src/cmd/distpack/test.go b/src/cmd/distpack/test.go
index 4f260cb0df..7479bd77f5 100644
--- a/src/cmd/distpack/test.go
+++ b/src/cmd/distpack/test.go
@@ -66,6 +66,8 @@ var zipRules = []testRule{
{name: "go/pkg/tool/*/compile", goos: "darwin"},
{name: "go/pkg/tool/*/compile", goos: "windows", exclude: true},
{name: "go/pkg/tool/*/compile.exe", goos: "windows"},
+ {name: "go/pkg/tool/*/pack", exclude: true},
+ {name: "go/pkg/tool/*/pack.exe", exclude: true},
}
var modRules = []testRule{
@@ -100,6 +102,8 @@ var modRules = []testRule{
{name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "darwin"},
{name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "windows", exclude: true},
{name: "golang.org/toolchain@*/pkg/tool/*/compile.exe", goos: "windows"},
+ {name: "golang.org/toolchain@*/pkg/tool/*/pack", exclude: true},
+ {name: "golang.org/toolchain@*/pkg/tool/*/pack.exe", exclude: true},
// go.mod are renamed to _go.mod.
{name: "**/go.mod", exclude: true},
diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go
index 70d22580a3..39a1f5f74c 100644
--- a/src/cmd/go/internal/work/gc.go
+++ b/src/cmd/go/internal/work/gc.go
@@ -482,7 +482,7 @@ func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) er
p := a.Package
sh := b.Shell(a)
if cfg.BuildN || cfg.BuildX {
- cmdline := str.StringList(base.Tool("pack"), "r", absAfile, absOfiles)
+ cmdline := str.StringList("go", "tool", "pack", "r", absAfile, absOfiles)
sh.ShowCmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
}
if cfg.BuildN {
diff --git a/src/cmd/internal/obj/s390x/condition_code.go b/src/cmd/internal/obj/s390x/condition_code.go
index f498fd6f77..3330d1310d 100644
--- a/src/cmd/internal/obj/s390x/condition_code.go
+++ b/src/cmd/internal/obj/s390x/condition_code.go
@@ -122,7 +122,7 @@ func (c CCMask) String() string {
}
// invalid
- return fmt.Sprintf("Invalid (%#x)", c)
+ return fmt.Sprintf("Invalid (%#x)", uint8(c))
}
func (CCMask) CanBeAnSSAAux() {}
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 128173b8cf..6561362210 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -452,33 +452,50 @@ func (st *loadState) addSym(name string, ver int, r *oReader, li uint32, kind in
if oldsym.Dupok() {
return oldi
}
- // If one is a DATA symbol (i.e. has content, DataSize != 0)
- // and the other is BSS, the one with content wins.
+ // If one is a DATA symbol (i.e. has content, DataSize != 0,
+ // including RODATA) and the other is BSS, the one with content wins.
// If both are BSS, the one with larger size wins.
- // Specifically, the "overwrite" variable and the final result are
//
- // new sym old sym overwrite
+ // For a special case, we allow a TEXT symbol overwrites a BSS symbol
+ // even if the BSS symbol has larger size. This is because there is
+ // code like below to take the address of a function
+ //
+ // //go:linkname fn
+ // var fn uintptr
+ // var fnAddr = uintptr(unsafe.Pointer(&fn))
+ //
+ // TODO: maybe limit this case to just pointer sized variable?
+ //
+ // In summary, the "overwrite" variable and the final result are
+ //
+ // new sym old sym result
// ---------------------------------------------
- // DATA DATA true => ERROR
- // DATA lg/eq BSS sm/eq true => new wins
- // DATA small BSS large true => ERROR
- // BSS large DATA small true => ERROR
- // BSS large BSS small true => new wins
- // BSS sm/eq D/B lg/eq false => old wins
- overwrite := r.DataSize(li) != 0 || oldsz < sz
- if overwrite {
+ // TEXT BSS new wins
+ // DATA DATA ERROR
+ // DATA lg/eq BSS sm/eq new wins
+ // DATA small BSS large ERROR
+ // BSS large DATA small ERROR
+ // BSS large BSS small new wins
+ // BSS sm/eq D/B lg/eq old wins
+ // BSS TEXT old wins
+ oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
+ newtyp := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
+ oldIsText := oldtyp.IsText()
+ newIsText := newtyp.IsText()
+ oldHasContent := oldr.DataSize(oldli) != 0
+ newHasContent := r.DataSize(li) != 0
+ oldIsBSS := oldtyp.IsData() && !oldHasContent
+ newIsBSS := newtyp.IsData() && !newHasContent
+ switch {
+ case newIsText && oldIsBSS,
+ newHasContent && oldIsBSS && sz >= oldsz,
+ newIsBSS && oldIsBSS && sz > oldsz:
// new symbol overwrites old symbol.
- oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
- if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) || oldsz > sz {
- log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
- }
l.objSyms[oldi] = objSym{r.objidx, li}
- } else {
- // old symbol overwrites new symbol.
- typ := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
- if !typ.IsData() { // only allow overwriting data symbol
- log.Fatalf("duplicated definition of symbol %s, from %s and %s", name, r.unit.Lib.Pkg, oldr.unit.Lib.Pkg)
- }
+ case newIsBSS && (oldsz >= sz || oldIsText):
+ // old win, just ignore the new symbol.
+ default:
+ log.Fatalf("duplicated definition of symbol %s, from %s (type %s size %d) and %s (type %s size %d)", name, r.unit.Lib.Pkg, newtyp, sz, oldr.unit.Lib.Pkg, oldtyp, oldsz)
}
return oldi
}
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go
index 7c3ca427ed..2fe32600f1 100644
--- a/src/cmd/link/link_test.go
+++ b/src/cmd/link/link_test.go
@@ -1601,6 +1601,9 @@ func TestCheckLinkname(t *testing.T) {
{"ok.go", true},
// push linkname is ok
{"push.go", true},
+ // using a linknamed variable to reference an assembly
+ // function in the same package is ok
+ {"textvar", true},
// pull linkname of blocked symbol is not ok
{"coro.go", false},
{"coro_var.go", false},
@@ -1618,7 +1621,7 @@ func TestCheckLinkname(t *testing.T) {
test := test
t.Run(test.src, func(t *testing.T) {
t.Parallel()
- src := filepath.Join("testdata", "linkname", test.src)
+ src := "./testdata/linkname/" + test.src
exe := filepath.Join(tmpdir, test.src+".exe")
cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", exe, src)
out, err := cmd.CombinedOutput()
diff --git a/src/cmd/link/testdata/linkname/textvar/asm.s b/src/cmd/link/testdata/linkname/textvar/asm.s
new file mode 100644
index 0000000000..332dcdb4e7
--- /dev/null
+++ b/src/cmd/link/testdata/linkname/textvar/asm.s
@@ -0,0 +1,6 @@
+// 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.
+
+TEXT ·asmfunc(SB),0,$0-0
+ RET
diff --git a/src/cmd/link/testdata/linkname/textvar/main.go b/src/cmd/link/testdata/linkname/textvar/main.go
new file mode 100644
index 0000000000..b38995e706
--- /dev/null
+++ b/src/cmd/link/testdata/linkname/textvar/main.go
@@ -0,0 +1,17 @@
+// 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.
+
+// Using a linknamed variable to reference an assembly
+// function in the same package is ok.
+
+package main
+
+import _ "unsafe"
+
+func main() {
+ println(&asmfunc)
+}
+
+//go:linkname asmfunc
+var asmfunc uintptr
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index b2668a3d7d..6d92542e31 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -103,6 +103,7 @@ var depsRules = `
< sync/atomic
< internal/sync
< weak
+ < internal/synctest
< sync
< internal/bisect
< internal/godebug
@@ -136,9 +137,6 @@ var depsRules = `
unicode !< path;
- RUNTIME
- < internal/synctest;
-
# SYSCALL is RUNTIME plus the packages necessary for basic system calls.
RUNTIME, unicode/utf8, unicode/utf16, internal/synctest
< internal/syscall/windows/sysdll, syscall/js
diff --git a/src/go/doc/doc.go b/src/go/doc/doc.go
index 4d01ae458b..f7e3c1bad8 100644
--- a/src/go/doc/doc.go
+++ b/src/go/doc/doc.go
@@ -188,6 +188,7 @@ func (p *Package) collectFuncs(funcs []*Func) {
//
// The package is specified by a list of *ast.Files and corresponding
// file set, which must not be nil.
+//
// NewFromFiles uses all provided files when computing documentation,
// so it is the caller's responsibility to provide only the files that
// match the desired build context. "go/build".Context.MatchFile can
@@ -226,49 +227,38 @@ func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opt
// Collect .go and _test.go files.
var (
+ pkgName string
goFiles = make(map[string]*ast.File)
testGoFiles []*ast.File
)
- for i := range files {
- f := fset.File(files[i].Pos())
+ for i, file := range files {
+ f := fset.File(file.Pos())
if f == nil {
return nil, fmt.Errorf("file files[%d] is not found in the provided file set", i)
}
- switch name := f.Name(); {
- case strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go"):
- goFiles[name] = files[i]
- case strings.HasSuffix(name, "_test.go"):
- testGoFiles = append(testGoFiles, files[i])
+ switch filename := f.Name(); {
+ case strings.HasSuffix(filename, "_test.go"):
+ testGoFiles = append(testGoFiles, file)
+ case strings.HasSuffix(filename, ".go"):
+ pkgName = file.Name.Name
+ goFiles[filename] = file
default:
- return nil, fmt.Errorf("file files[%d] filename %q does not have a .go extension", i, name)
+ return nil, fmt.Errorf("file files[%d] filename %q does not have a .go extension", i, filename)
}
}
- // TODO(dmitshur,gri): A relatively high level call to ast.NewPackage with a simpleImporter
- // ast.Importer implementation is made below. It might be possible to short-circuit and simplify.
-
// Compute package documentation.
- pkg, _ := ast.NewPackage(fset, goFiles, simpleImporter, nil) // Ignore errors that can happen due to unresolved identifiers.
+ //
+ // Since this package doesn't need Package.{Scope,Imports}, or
+ // handle errors, and ast.File's Scope field is unset in files
+ // parsed with parser.SkipObjectResolution, we construct the
+ // Package directly instead of calling [ast.NewPackage].
+ pkg := &ast.Package{Name: pkgName, Files: goFiles}
p := New(pkg, importPath, mode)
classifyExamples(p, Examples(testGoFiles...))
return p, nil
}
-// simpleImporter returns a (dummy) package object named by the last path
-// component of the provided package path (as is the convention for packages).
-// This is sufficient to resolve package identifiers without doing an actual
-// import. It never returns an error.
-func simpleImporter(imports map[string]*ast.Object, path string) (*ast.Object, error) {
- pkg := imports[path]
- if pkg == nil {
- // note that strings.LastIndex returns -1 if there is no "/"
- pkg = ast.NewObj(ast.Pkg, path[strings.LastIndex(path, "/")+1:])
- pkg.Data = ast.NewScope(nil) // required by ast.NewPackage for dot-import
- imports[path] = pkg
- }
- return pkg, nil
-}
-
// lookupSym reports whether the package has a given symbol or method.
//
// If recv == "", HasSym reports whether the package has a top-level
diff --git a/src/go/doc/example_test.go b/src/go/doc/example_test.go
index 7919c3a2c0..2fd54f8abb 100644
--- a/src/go/doc/example_test.go
+++ b/src/go/doc/example_test.go
@@ -328,7 +328,7 @@ func exampleNames(exs []*doc.Example) (out []string) {
}
func mustParse(fset *token.FileSet, filename, src string) *ast.File {
- f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
+ f, err := parser.ParseFile(fset, filename, src, parser.ParseComments|parser.SkipObjectResolution)
if err != nil {
panic(err)
}
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 77bff811b9..e4e8e95c99 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -13,6 +13,7 @@ import (
"go/token"
"internal/godebug"
. "internal/types/errors"
+ "os"
"sync/atomic"
)
@@ -444,7 +445,24 @@ func (check *Checker) handleBailout(err *error) {
// normal return or early exit
*err = check.firstErr
default:
- // TODO(markfreeman): dump posStack if available
+ if len(check.posStack) > 0 {
+ doPrint := func(ps []positioner) {
+ for i := len(ps) - 1; i >= 0; i-- {
+ fmt.Fprintf(os.Stderr, "\t%v\n", check.fset.Position(ps[i].Pos()))
+ }
+ }
+
+ fmt.Fprintln(os.Stderr, "The following panic happened checking types near:")
+ if len(check.posStack) <= 10 {
+ doPrint(check.posStack)
+ } else {
+ // if it's long, truncate the middle; it's least likely to help
+ doPrint(check.posStack[len(check.posStack)-5:])
+ fmt.Fprintln(os.Stderr, "\t...")
+ doPrint(check.posStack[:5])
+ }
+ }
+
// re-panic
panic(p)
}
diff --git a/src/internal/pkgbits/reloc.go b/src/internal/pkgbits/reloc.go
index 5f6ec2ab79..6074296d9e 100644
--- a/src/internal/pkgbits/reloc.go
+++ b/src/internal/pkgbits/reloc.go
@@ -37,7 +37,68 @@ type AbsElemIdx = uint32
// relative to some other index, such as the start of a section.
type RelElemIdx = Index
-// TODO(markfreeman): Isn't this strictly less efficient than an AbsElemIdx?
+/*
+All elements are preceded by a reference table. Reference tables provide an
+additional indirection layer for element references. That is, for element A to
+reference element B, A encodes the reference table index pointing to B, rather
+than the table entry itself.
+
+# Functional Considerations
+Reference table layout is important primarily to the UIR linker. After noding,
+the UIR linker sees a UIR file for each package with imported objects
+represented as stubs. In a simple sense, the job of the UIR linker is to merge
+these "stubbed" UIR files into a single "linked" UIR file for the target package
+with stubs replaced by object definitions.
+
+To do this, the UIR linker walks each stubbed UIR file and pulls in elements in
+dependency order; that is, if A references B, then B must be placed into the
+linked UIR file first. This depth-first traversal is done by recursing through
+each element's reference table.
+
+When placing A in the linked UIR file, the reference table entry for B must be
+updated, since B is unlikely to be at the same relative element index as it was
+in the stubbed UIR file.
+
+Without reference tables, the UIR linker would need to read in the element to
+discover its references. Note that the UIR linker cannot jump directly to the
+reference locations after discovering merely the type of the element;
+variable-width primitives prevent this.
+
+After updating the reference table, the rest of the element may be copied
+directly into the linked UIR file. Note that the UIR linker may decide to read
+in the element anyway (for unrelated reasons).
+
+In short, reference tables provide an efficient mechanism for traversing,
+discovering, and updating element references during UIR linking.
+
+# Storage Considerations
+Reference tables also have compactness benefits:
+ - If A refers to B multiple times, the entry is deduplicated and referred to
+ more compactly by the index.
+ - Relative (to a section) element indices are typically smaller than absolute
+ element indices, and thus fit into smaller varints.
+ - Most elements do not reference many elements; thus table size indicators and
+ table indices are typically a byte each.
+
+Thus, the storage performance is as follows:
++-----------------------------+-----------+--------------+
+| Scenario | Best Case | Typical Case |
++-----------------------------+-----------+--------------+
+| First reference from A to B | 3 Bytes | 4 Bytes |
+| Other reference from A to B | 1 Byte | 1 Byte |
++-----------------------------+-----------+--------------+
+
+The typical case for the first scenario changes because many sections have more
+than 127 (range of a 1-byte uvarint) elements and thus the relative index is
+typically 2 bytes, though this depends on the distribution of referenced indices
+within the section.
+
+The second does not because most elements do not reference more than 127
+elements and the table index can thus keep to 1 byte.
+
+Typically, A will only reference B once, so most references are 4 bytes.
+*/
+
// A RefTableEntry is an entry in an element's reference table. All
// elements are preceded by a reference table which provides locations
// for referenced elements.
diff --git a/src/internal/synctest/synctest.go b/src/internal/synctest/synctest.go
index 19190d30f1..4d7fa3730c 100644
--- a/src/internal/synctest/synctest.go
+++ b/src/internal/synctest/synctest.go
@@ -8,7 +8,7 @@
package synctest
import (
- _ "unsafe" // for go:linkname
+ "unsafe"
)
//go:linkname Run
@@ -17,6 +17,36 @@ func Run(f func())
//go:linkname Wait
func Wait()
+// IsInBubble reports whether the current goroutine is in a bubble.
+//
+//go:linkname IsInBubble
+func IsInBubble() bool
+
+// Associate associates p with the current bubble.
+// It returns false if p has an existing association with a different bubble.
+func Associate[T any](p *T) (ok bool) {
+ return associate(unsafe.Pointer(p))
+}
+
+//go:linkname associate
+func associate(p unsafe.Pointer) bool
+
+// Disassociate disassociates p from any bubble.
+func Disassociate[T any](p *T) {
+ disassociate(unsafe.Pointer(p))
+}
+
+//go:linkname disassociate
+func disassociate(b unsafe.Pointer)
+
+// IsAssociated reports whether p is associated with the current bubble.
+func IsAssociated[T any](p *T) bool {
+ return isAssociated(unsafe.Pointer(p))
+}
+
+//go:linkname isAssociated
+func isAssociated(p unsafe.Pointer) bool
+
//go:linkname acquire
func acquire() any
diff --git a/src/internal/synctest/synctest_test.go b/src/internal/synctest/synctest_test.go
index 7f71df1710..2e1393591f 100644
--- a/src/internal/synctest/synctest_test.go
+++ b/src/internal/synctest/synctest_test.go
@@ -7,11 +7,14 @@ package synctest_test
import (
"fmt"
"internal/synctest"
+ "internal/testenv"
"iter"
+ "os"
"reflect"
"runtime"
"slices"
"strconv"
+ "strings"
"sync"
"testing"
"time"
@@ -523,7 +526,7 @@ func TestReflectFuncOf(t *testing.T) {
})
}
-func TestWaitGroup(t *testing.T) {
+func TestWaitGroupInBubble(t *testing.T) {
synctest.Run(func() {
var wg sync.WaitGroup
wg.Add(1)
@@ -540,6 +543,83 @@ func TestWaitGroup(t *testing.T) {
})
}
+func TestWaitGroupOutOfBubble(t *testing.T) {
+ var wg sync.WaitGroup
+ wg.Add(1)
+ donec := make(chan struct{})
+ go synctest.Run(func() {
+ // Since wg.Add was called outside the bubble, Wait is not durably blocking
+ // and this waits until wg.Done is called below.
+ wg.Wait()
+ close(donec)
+ })
+ select {
+ case <-donec:
+ t.Fatalf("synctest.Run finished before WaitGroup.Done called")
+ case <-time.After(1 * time.Millisecond):
+ }
+ wg.Done()
+ <-donec
+}
+
+func TestWaitGroupMovedIntoBubble(t *testing.T) {
+ wantFatal(t, "fatal error: sync: WaitGroup.Add called from inside and outside synctest bubble", func() {
+ var wg sync.WaitGroup
+ wg.Add(1)
+ synctest.Run(func() {
+ wg.Add(1)
+ })
+ })
+}
+
+func TestWaitGroupMovedOutOfBubble(t *testing.T) {
+ wantFatal(t, "fatal error: sync: WaitGroup.Add called from inside and outside synctest bubble", func() {
+ var wg sync.WaitGroup
+ synctest.Run(func() {
+ wg.Add(1)
+ })
+ wg.Add(1)
+ })
+}
+
+func TestWaitGroupMovedBetweenBubblesWithNonZeroCount(t *testing.T) {
+ wantFatal(t, "fatal error: sync: WaitGroup.Add called from multiple synctest bubbles", func() {
+ var wg sync.WaitGroup
+ synctest.Run(func() {
+ wg.Add(1)
+ })
+ synctest.Run(func() {
+ wg.Add(1)
+ })
+ })
+}
+
+func TestWaitGroupMovedBetweenBubblesWithZeroCount(t *testing.T) {
+ var wg sync.WaitGroup
+ synctest.Run(func() {
+ wg.Add(1)
+ wg.Done()
+ })
+ synctest.Run(func() {
+ // Reusing the WaitGroup is safe, because its count is zero.
+ wg.Add(1)
+ wg.Done()
+ })
+}
+
+func TestWaitGroupMovedBetweenBubblesAfterWait(t *testing.T) {
+ var wg sync.WaitGroup
+ synctest.Run(func() {
+ wg.Go(func() {})
+ wg.Wait()
+ })
+ synctest.Run(func() {
+ // Reusing the WaitGroup is safe, because its count is zero.
+ wg.Go(func() {})
+ wg.Wait()
+ })
+}
+
func TestHappensBefore(t *testing.T) {
// Use two parallel goroutines accessing different vars to ensure that
// we correctly account for multiple goroutines in the bubble.
@@ -630,7 +710,7 @@ func TestHappensBefore(t *testing.T) {
// https://go.dev/issue/73817
func TestWeak(t *testing.T) {
synctest.Run(func() {
- for range 100 {
+ for range 5 {
runtime.GC()
b := make([]byte, 1024)
weak.Make(&b)
@@ -647,3 +727,23 @@ func wantPanic(t *testing.T, want string) {
t.Errorf("got no panic, want one")
}
}
+
+func wantFatal(t *testing.T, want string, f func()) {
+ t.Helper()
+
+ if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+ f()
+ return
+ }
+
+ cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^"+t.Name()+"$")
+ cmd = testenv.CleanCmdEnv(cmd)
+ cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
+ out, err := cmd.CombinedOutput()
+ if err == nil {
+ t.Errorf("expected test function to panic, but test returned successfully")
+ }
+ if !strings.Contains(string(out), want) {
+ t.Errorf("wanted test output contaiing %q; got %q", want, string(out))
+ }
+}
diff --git a/src/internal/trace/export_reader_test.go b/src/internal/trace/export_reader_test.go
new file mode 100644
index 0000000000..042c70864c
--- /dev/null
+++ b/src/internal/trace/export_reader_test.go
@@ -0,0 +1,12 @@
+// Copyright 2025 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 trace
+
+import "internal/trace/version"
+
+// GoVersion is the version set in the trace header.
+func (r *Reader) GoVersion() version.Version {
+ return r.version
+}
diff --git a/src/internal/trace/reader_test.go b/src/internal/trace/reader_test.go
index 691cda6688..39ae77471e 100644
--- a/src/internal/trace/reader_test.go
+++ b/src/internal/trace/reader_test.go
@@ -11,6 +11,7 @@ import (
"io"
"os"
"path/filepath"
+ "runtime"
"strings"
"testing"
"time"
@@ -109,6 +110,10 @@ func testReader(t *testing.T, tr io.Reader, v *testtrace.Validator, exp *testtra
if err == io.EOF {
break
}
+ v.GoVersion = r.GoVersion()
+ if runtime.GOOS == "windows" || runtime.GOARCH == "wasm" {
+ v.SkipClockSnapshotChecks()
+ }
if err != nil {
if err := exp.Check(err); err != nil {
t.Error(err)
diff --git a/src/os/root.go b/src/os/root.go
index 953cd6b9b9..d759727ce7 100644
--- a/src/os/root.go
+++ b/src/os/root.go
@@ -352,8 +352,8 @@ func splitPathInRoot(s string, prefix, suffix []string) (_ []string, suffixSep s
// FS returns a file system (an fs.FS) for the tree of files in the root.
//
-// The result implements [io/fs.StatFS], [io/fs.ReadFileFS] and
-// [io/fs.ReadDirFS].
+// The result implements [io/fs.StatFS], [io/fs.ReadFileFS],
+// [io/fs.ReadDirFS], and [io/fs.ReadLinkFS].
func (r *Root) FS() fs.FS {
return (*rootFS)(r)
}
@@ -409,6 +409,14 @@ func (rfs *rootFS) ReadFile(name string) ([]byte, error) {
return readFileContents(statOrZero(f), f.Read)
}
+func (rfs *rootFS) ReadLink(name string) (string, error) {
+ r := (*Root)(rfs)
+ if !isValidRootFSPath(name) {
+ return "", &PathError{Op: "readlink", Path: name, Err: ErrInvalid}
+ }
+ return r.Readlink(name)
+}
+
func (rfs *rootFS) Stat(name string) (FileInfo, error) {
r := (*Root)(rfs)
if !isValidRootFSPath(name) {
@@ -417,6 +425,14 @@ func (rfs *rootFS) Stat(name string) (FileInfo, error) {
return r.Stat(name)
}
+func (rfs *rootFS) Lstat(name string) (FileInfo, error) {
+ r := (*Root)(rfs)
+ if !isValidRootFSPath(name) {
+ return nil, &PathError{Op: "lstat", Path: name, Err: ErrInvalid}
+ }
+ return r.Lstat(name)
+}
+
// isValidRootFSPath reports whether name is a valid filename to pass a Root.FS method.
func isValidRootFSPath(name string) bool {
if !fs.ValidPath(name) {
diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go
index 221a9a95cc..8696672065 100644
--- a/src/runtime/crash_test.go
+++ b/src/runtime/crash_test.go
@@ -1228,3 +1228,20 @@ func TestFinalizerOrCleanupDeadlock(t *testing.T) {
})
}
}
+
+func TestSynctestCondSignalFromNoBubble(t *testing.T) {
+ for _, test := range []string{
+ "SynctestCond/signal/no_bubble",
+ "SynctestCond/broadcast/no_bubble",
+ "SynctestCond/signal/other_bubble",
+ "SynctestCond/broadcast/other_bubble",
+ } {
+ t.Run(test, func(t *testing.T) {
+ output := runTestProg(t, "testprog", test)
+ want := "fatal error: semaphore wake of synctest goroutine from outside bubble"
+ if !strings.Contains(output, want) {
+ t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
+ }
+ })
+ }
+}
diff --git a/src/runtime/debug.go b/src/runtime/debug.go
index 94d1dab34d..bdaaa7196d 100644
--- a/src/runtime/debug.go
+++ b/src/runtime/debug.go
@@ -39,10 +39,18 @@ func GOMAXPROCS(n int) int {
lock(&sched.lock)
ret := int(gomaxprocs)
- unlock(&sched.lock)
if n <= 0 || n == ret {
+ unlock(&sched.lock)
return ret
}
+ // Set early so we can wait for sysmon befor STW. See comment on
+ // computeMaxProcsLock.
+ sched.customGOMAXPROCS = true
+ unlock(&sched.lock)
+
+ // Wait for sysmon to complete running defaultGOMAXPROCS.
+ lock(&computeMaxProcsLock)
+ unlock(&computeMaxProcsLock)
stw := stopTheWorldGC(stwGOMAXPROCS)
@@ -51,7 +59,6 @@ func GOMAXPROCS(n int) int {
// TODO(prattmic): this could use a nicer API. Perhaps add it to the
// stw parameter?
newprocs = int32(n)
- newprocsCustom = true
startTheWorldGC(stw)
return ret
@@ -91,7 +98,9 @@ func SetDefaultGOMAXPROCS() {
// TODO(prattmic): this could use a nicer API. Perhaps add it to the
// stw parameter?
newprocs = procs
- newprocsCustom = false
+ lock(&sched.lock)
+ sched.customGOMAXPROCS = false
+ unlock(&sched.lock)
startTheWorldGC(stw)
}
diff --git a/src/runtime/lockrank.go b/src/runtime/lockrank.go
index 7f32e6397b..44015ce862 100644
--- a/src/runtime/lockrank.go
+++ b/src/runtime/lockrank.go
@@ -14,7 +14,8 @@ const (
lockRankSysmon
lockRankScavenge
lockRankForcegc
- lockRankUpdateGOMAXPROCS
+ lockRankComputeMaxProcs
+ lockRankUpdateMaxProcsG
lockRankDefer
lockRankSweepWaiters
lockRankAssistQueue
@@ -23,6 +24,7 @@ const (
lockRankSweep
lockRankTestR
lockRankTestW
+ lockRankVgetrandom
lockRankTimerSend
lockRankAllocmW
lockRankExecW
@@ -91,7 +93,8 @@ var lockNames = []string{
lockRankSysmon: "sysmon",
lockRankScavenge: "scavenge",
lockRankForcegc: "forcegc",
- lockRankUpdateGOMAXPROCS: "updateGOMAXPROCS",
+ lockRankComputeMaxProcs: "computeMaxProcs",
+ lockRankUpdateMaxProcsG: "updateMaxProcsG",
lockRankDefer: "defer",
lockRankSweepWaiters: "sweepWaiters",
lockRankAssistQueue: "assistQueue",
@@ -100,6 +103,7 @@ var lockNames = []string{
lockRankSweep: "sweep",
lockRankTestR: "testR",
lockRankTestW: "testW",
+ lockRankVgetrandom: "vgetrandom",
lockRankTimerSend: "timerSend",
lockRankAllocmW: "allocmW",
lockRankExecW: "execW",
@@ -174,7 +178,8 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
lockRankSysmon: {},
lockRankScavenge: {lockRankSysmon},
lockRankForcegc: {lockRankSysmon},
- lockRankUpdateGOMAXPROCS: {lockRankSysmon},
+ lockRankComputeMaxProcs: {lockRankSysmon},
+ lockRankUpdateMaxProcsG: {lockRankSysmon},
lockRankDefer: {},
lockRankSweepWaiters: {},
lockRankAssistQueue: {},
@@ -183,6 +188,7 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
lockRankSweep: {},
lockRankTestR: {},
lockRankTestW: {},
+ lockRankVgetrandom: {},
lockRankTimerSend: {},
lockRankAllocmW: {},
lockRankExecW: {},
@@ -191,11 +197,11 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
lockRankPollDesc: {},
lockRankWakeableSleep: {},
lockRankHchan: {lockRankSysmon, lockRankScavenge, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankWakeableSleep, lockRankHchan},
- lockRankAllocmR: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
- lockRankExecR: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
- lockRankSched: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR},
- lockRankAllg: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
- lockRankAllp: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
+ lockRankAllocmR: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
+ lockRankExecR: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan},
+ lockRankSched: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR},
+ lockRankAllg: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched},
+ lockRankAllp: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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},
@@ -208,29 +214,29 @@ var lockPartialOrder [][]lockRank = [][]lockRank{
lockRankUserArenaState: {},
lockRankTraceBuf: {lockRankSysmon, lockRankScavenge},
lockRankTraceStrings: {lockRankSysmon, lockRankScavenge, lockRankTraceBuf},
- lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture},
- lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
- lockRankStackLarge: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
- lockRankHchanLeaf: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankHchanLeaf},
- lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
- lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans},
- lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
- lockRankGlobalAlloc: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankMheapSpecial},
- lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
- lockRankTraceStackTab: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankTrace},
+ lockRankFin: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankSpanSetSpine: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankMspanSpecial: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankTraceTypeTab: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankGcBitsArenas: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankMspanSpecial},
+ lockRankProfInsert: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankProfBlock: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankProfMemActive: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings},
+ lockRankProfMemFuture: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankItab, lockRankReflectOffs, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankProfMemActive},
+ lockRankGscan: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture},
+ lockRankStackpool: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
+ lockRankStackLarge: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
+ lockRankHchanLeaf: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankHchanLeaf},
+ lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan},
+ lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans},
+ lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
+ lockRankGlobalAlloc: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap, lockRankMheapSpecial},
+ lockRankTrace: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, lockRankUserArenaState, lockRankTraceBuf, lockRankTraceStrings, lockRankFin, lockRankSpanSetSpine, lockRankMspanSpecial, lockRankGcBitsArenas, lockRankProfInsert, lockRankProfBlock, lockRankProfMemActive, lockRankProfMemFuture, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankWbufSpans, lockRankMheap},
+ lockRankTraceStackTab: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankDefer, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankVgetrandom, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollCache, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR, lockRankExecR, lockRankSched, lockRankAllg, lockRankAllp, lockRankNotifyList, lockRankSudog, lockRankTimers, lockRankTimer, lockRankNetpollInit, lockRankRoot, lockRankItab, lockRankReflectOffs, lockRankSynctest, 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, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankAllocmW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR},
- lockRankExecRInternal: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankUpdateGOMAXPROCS, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankExecR},
+ lockRankAllocmRInternal: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankAllocmW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankAllocmR},
+ lockRankExecRInternal: {lockRankSysmon, lockRankScavenge, lockRankForcegc, lockRankComputeMaxProcs, lockRankUpdateMaxProcsG, lockRankSweepWaiters, lockRankAssistQueue, lockRankStrongFromWeakQueue, lockRankCleanupQueue, lockRankSweep, lockRankTestR, lockRankTimerSend, lockRankExecW, lockRankCpuprof, lockRankPollDesc, lockRankWakeableSleep, lockRankHchan, lockRankExecR},
lockRankTestRInternal: {lockRankTestR, lockRankTestW},
}
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index 3612d71e66..9361089b80 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -223,6 +223,7 @@ type mheap struct {
specialReachableAlloc fixalloc // allocator for specialReachable
specialPinCounterAlloc fixalloc // allocator for specialPinCounter
specialWeakHandleAlloc fixalloc // allocator for specialWeakHandle
+ specialBubbleAlloc fixalloc // allocator for specialBubble
speciallock mutex // lock for special record allocators.
arenaHintAlloc fixalloc // allocator for arenaHints
@@ -799,6 +800,7 @@ func (h *mheap) init() {
h.specialReachableAlloc.init(unsafe.Sizeof(specialReachable{}), nil, nil, &memstats.other_sys)
h.specialPinCounterAlloc.init(unsafe.Sizeof(specialPinCounter{}), nil, nil, &memstats.other_sys)
h.specialWeakHandleAlloc.init(unsafe.Sizeof(specialWeakHandle{}), nil, nil, &memstats.gcMiscSys)
+ h.specialBubbleAlloc.init(unsafe.Sizeof(specialBubble{}), nil, nil, &memstats.other_sys)
h.arenaHintAlloc.init(unsafe.Sizeof(arenaHint{}), nil, nil, &memstats.other_sys)
// Don't zero mspan allocations. Background sweeping can
@@ -2003,6 +2005,8 @@ const (
// _KindSpecialCheckFinalizer adds additional context to a finalizer or cleanup.
// Used only if debug.checkfinalizers != 0.
_KindSpecialCheckFinalizer = 8
+ // _KindSpecialBubble is used to associate objects with synctest bubbles.
+ _KindSpecialBubble = 9
)
type special struct {
@@ -2839,6 +2843,11 @@ func freeSpecial(s *special, p unsafe.Pointer, size uintptr) {
lock(&mheap_.speciallock)
mheap_.specialTinyBlockAlloc.free(unsafe.Pointer(st))
unlock(&mheap_.speciallock)
+ case _KindSpecialBubble:
+ st := (*specialBubble)(unsafe.Pointer(s))
+ lock(&mheap_.speciallock)
+ mheap_.specialBubbleAlloc.free(unsafe.Pointer(st))
+ unlock(&mheap_.speciallock)
default:
throw("bad special kind")
panic("not reached")
diff --git a/src/runtime/mklockrank.go b/src/runtime/mklockrank.go
index 2e3375331a..46a063fdce 100644
--- a/src/runtime/mklockrank.go
+++ b/src/runtime/mklockrank.go
@@ -41,7 +41,7 @@ const ranks = `
# Sysmon
NONE
< sysmon
-< scavenge, forcegc, updateGOMAXPROCS;
+< scavenge, forcegc, computeMaxProcs, updateMaxProcsG;
# Defer
NONE < defer;
@@ -57,6 +57,9 @@ NONE <
# Test only
NONE < testR, testW;
+# vgetrandom
+NONE < vgetrandom;
+
NONE < timerSend;
# Scheduler, timers, netpoll
@@ -64,9 +67,10 @@ NONE < allocmW, execW, cpuprof, pollCache, pollDesc, wakeableSleep;
scavenge, sweep, testR, wakeableSleep, timerSend < hchan;
assistQueue,
cleanupQueue,
+ computeMaxProcs,
cpuprof,
forcegc,
- updateGOMAXPROCS,
+ updateMaxProcsG,
hchan,
pollDesc, # pollDesc can interact with timers, which can lock sched.
scavenge,
@@ -134,7 +138,8 @@ allg,
reflectOffs,
timer,
traceStrings,
- userArenaState
+ userArenaState,
+ vgetrandom
# Above MALLOC are things that can allocate memory.
< MALLOC
# Below MALLOC is the malloc implementation.
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 4925528783..5b8db2bee4 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -835,6 +835,7 @@ func schedinit() {
lockInit(&reflectOffs.lock, lockRankReflectOffs)
lockInit(&finlock, lockRankFin)
lockInit(&cpuprof.lock, lockRankCpuprof)
+ lockInit(&computeMaxProcsLock, lockRankComputeMaxProcs)
allocmLock.init(lockRankAllocmR, lockRankAllocmRInternal, lockRankAllocmW)
execLock.init(lockRankExecR, lockRankExecRInternal, lockRankExecW)
traceLockInit()
@@ -1727,7 +1728,6 @@ func startTheWorldWithSema(now int64, w worldStop) int64 {
procs := gomaxprocs
if newprocs != 0 {
procs = newprocs
- sched.customGOMAXPROCS = newprocsCustom
newprocs = 0
}
p1 := procresize(procs)
@@ -6546,7 +6546,7 @@ func schedtrace(detailed bool) {
unlock(&sched.lock)
}
-type updateGOMAXPROCSState struct {
+type updateMaxProcsGState struct {
lock mutex
g *g
idle atomic.Bool
@@ -6556,28 +6556,97 @@ type updateGOMAXPROCSState struct {
}
var (
- updateGOMAXPROCS updateGOMAXPROCSState
-
+ // GOMAXPROCS update godebug metric. Incremented if automatic
+ // GOMAXPROCS updates actually change the value of GOMAXPROCS.
updatemaxprocs = &godebugInc{name: "updatemaxprocs"}
+
+ // Synchronization and state between updateMaxProcsGoroutine and
+ // sysmon.
+ updateMaxProcsG updateMaxProcsGState
+
+ // Synchronization between GOMAXPROCS and sysmon.
+ //
+ // Setting GOMAXPROCS via a call to GOMAXPROCS disables automatic
+ // GOMAXPROCS updates.
+ //
+ // We want to make two guarantees to callers of GOMAXPROCS. After
+ // GOMAXPROCS returns:
+ //
+ // 1. The runtime will not make any automatic changes to GOMAXPROCS.
+ //
+ // 2. The runtime will not perform any of the system calls used to
+ // determine the appropriate value of GOMAXPROCS (i.e., it won't
+ // call defaultGOMAXPROCS).
+ //
+ // (1) is the baseline guarantee that everyone needs. The GOMAXPROCS
+ // API isn't useful to anyone if automatic updates may occur after it
+ // returns. This is easily achieved by double-checking the state under
+ // STW before committing an automatic GOMAXPROCS update.
+ //
+ // (2) doesn't matter to most users, as it is isn't observable as long
+ // as (1) holds. However, it can be important to users sandboxing Go.
+ // They want disable these system calls and need some way to know when
+ // they are guaranteed the calls will stop.
+ //
+ // This would be simple to achieve if we simply called
+ // defaultGOMAXPROCS under STW in updateMaxProcsGoroutine below.
+ // However, we would like to avoid scheduling this goroutine every
+ // second when it will almost never do anything. Instead, sysmon calls
+ // defaultGOMAXPROCS to decide whether to schedule
+ // updateMaxProcsGoroutine. Thus we need to synchronize between sysmon
+ // and GOMAXPROCS calls.
+ //
+ // GOMAXPROCS can't hold a runtime mutex across STW. It could hold a
+ // semaphore, but sysmon cannot take semaphores. Instead, we have a
+ // more complex scheme:
+ //
+ // * sysmon holds computeMaxProcsLock while calling defaultGOMAXPROCS.
+ // * sysmon skips the current update if sched.customGOMAXPROCS is
+ // set.
+ // * GOMAXPROCS sets sched.customGOMAXPROCS once it is committed to
+ // changing GOMAXPROCS.
+ // * GOMAXPROCS takes computeMaxProcsLock to wait for outstanding
+ // defaultGOMAXPROCS calls to complete.
+ //
+ // N.B. computeMaxProcsLock could simply be sched.lock, but we want to
+ // avoid holding that lock during the potentially slow
+ // defaultGOMAXPROCS.
+ computeMaxProcsLock mutex
)
// Start GOMAXPROCS update helper goroutine.
//
// This is based on forcegchelper.
func defaultGOMAXPROCSUpdateEnable() {
- go updateGOMAXPROCSHelper()
+ if debug.updatemaxprocs == 0 {
+ // Unconditionally increment the metric when updates are disabled.
+ //
+ // It would be more descriptive if we did a dry run of the
+ // complete update, determining the appropriate value of
+ // GOMAXPROCS and the bailing out and just incrementing the
+ // metric if a change would occur.
+ //
+ // Not only is that a lot of ongoing work for a disabled
+ // feature, but some users need to be able to completely
+ // disable the update system calls (such as sandboxes).
+ // Currently, updatemaxprocs=0 serves that purpose.
+ updatemaxprocs.IncNonDefault()
+ return
+ }
+
+ go updateMaxProcsGoroutine()
}
-func updateGOMAXPROCSHelper() {
- updateGOMAXPROCS.g = getg()
- lockInit(&updateGOMAXPROCS.lock, lockRankUpdateGOMAXPROCS)
+func updateMaxProcsGoroutine() {
+ updateMaxProcsG.g = getg()
+ lockInit(&updateMaxProcsG.lock, lockRankUpdateMaxProcsG)
for {
- lock(&updateGOMAXPROCS.lock)
- if updateGOMAXPROCS.idle.Load() {
- throw("updateGOMAXPROCS: phase error")
+ lock(&updateMaxProcsG.lock)
+ if updateMaxProcsG.idle.Load() {
+ throw("updateMaxProcsGoroutine: phase error")
}
- updateGOMAXPROCS.idle.Store(true)
- goparkunlock(&updateGOMAXPROCS.lock, waitReasonUpdateGOMAXPROCSIdle, traceBlockSystemGoroutine, 1)
+ updateMaxProcsG.idle.Store(true)
+ goparkunlock(&updateMaxProcsG.lock, waitReasonUpdateGOMAXPROCSIdle, traceBlockSystemGoroutine, 1)
// This goroutine is explicitly resumed by sysmon.
stw := stopTheWorldGC(stwGOMAXPROCS)
@@ -6595,29 +6664,32 @@ func updateGOMAXPROCSHelper() {
//
// TODO(prattmic): this could use a nicer API. Perhaps add it to the
// stw parameter?
- newprocs = updateGOMAXPROCS.procs
- newprocsCustom = false
+ newprocs = updateMaxProcsG.procs
+ lock(&sched.lock)
+ sched.customGOMAXPROCS = false
+ unlock(&sched.lock)
startTheWorldGC(stw)
-
- // We actually changed something.
- updatemaxprocs.IncNonDefault()
}
}
func sysmonUpdateGOMAXPROCS() {
+ // Synchronize with GOMAXPROCS. See comment on computeMaxProcsLock.
+ lock(&computeMaxProcsLock)
+
// No update if GOMAXPROCS was set manually.
lock(&sched.lock)
custom := sched.customGOMAXPROCS
curr := gomaxprocs
unlock(&sched.lock)
if custom {
+ unlock(&computeMaxProcsLock)
return
}
// Don't hold sched.lock while we read the filesystem.
procs := defaultGOMAXPROCS(0)
-
+ unlock(&computeMaxProcsLock)
if procs == curr {
// Nothing to do.
return
@@ -6626,14 +6698,14 @@ func sysmonUpdateGOMAXPROCS() {
// Sysmon can't directly stop the world. Run the helper to do so on our
// behalf. If updateGOMAXPROCS.idle is false, then a previous update is
// still pending.
- if updateGOMAXPROCS.idle.Load() {
- lock(&updateGOMAXPROCS.lock)
- updateGOMAXPROCS.procs = procs
- updateGOMAXPROCS.idle.Store(false)
+ if updateMaxProcsG.idle.Load() {
+ lock(&updateMaxProcsG.lock)
+ updateMaxProcsG.procs = procs
+ updateMaxProcsG.idle.Store(false)
var list gList
- list.push(updateGOMAXPROCS.g)
+ list.push(updateMaxProcsG.g)
injectglist(&list)
- unlock(&updateGOMAXPROCS.lock)
+ unlock(&updateMaxProcsG.lock)
}
}
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 94ab87f6db..589642efc6 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -1096,6 +1096,7 @@ const (
waitReasonSynctestChanReceive // "chan receive (synctest)"
waitReasonSynctestChanSend // "chan send (synctest)"
waitReasonSynctestSelect // "select (synctest)"
+ waitReasonSynctestWaitGroupWait // "sync.WaitGroup.Wait (synctest)"
waitReasonCleanupWait // "cleanup wait"
)
@@ -1145,6 +1146,7 @@ var waitReasonStrings = [...]string{
waitReasonSynctestChanReceive: "chan receive (synctest)",
waitReasonSynctestChanSend: "chan send (synctest)",
waitReasonSynctestSelect: "select (synctest)",
+ waitReasonSynctestWaitGroupWait: "sync.WaitGroup.Wait (synctest)",
waitReasonCleanupWait: "cleanup wait",
}
@@ -1190,18 +1192,18 @@ func (w waitReason) isIdleInSynctest() bool {
// isIdleInSynctest indicates that a goroutine is considered idle by synctest.Wait.
var isIdleInSynctest = [len(waitReasonStrings)]bool{
- waitReasonChanReceiveNilChan: true,
- waitReasonChanSendNilChan: true,
- waitReasonSelectNoCases: true,
- waitReasonSleep: true,
- waitReasonSyncCondWait: true,
- waitReasonSyncWaitGroupWait: true,
- waitReasonCoroutine: true,
- waitReasonSynctestRun: true,
- waitReasonSynctestWait: true,
- waitReasonSynctestChanReceive: true,
- waitReasonSynctestChanSend: true,
- waitReasonSynctestSelect: true,
+ waitReasonChanReceiveNilChan: true,
+ waitReasonChanSendNilChan: true,
+ waitReasonSelectNoCases: true,
+ waitReasonSleep: true,
+ waitReasonSyncCondWait: true,
+ waitReasonSynctestWaitGroupWait: true,
+ waitReasonCoroutine: true,
+ waitReasonSynctestRun: true,
+ waitReasonSynctestWait: true,
+ waitReasonSynctestChanReceive: true,
+ waitReasonSynctestChanSend: true,
+ waitReasonSynctestSelect: true,
}
var (
@@ -1211,7 +1213,6 @@ var (
forcegc forcegcstate
sched schedt
newprocs int32
- newprocsCustom bool // newprocs value is manually set via runtime.GOMAXPROCS.
)
var (
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
index 4890df3464..0f029f604f 100644
--- a/src/runtime/sema.go
+++ b/src/runtime/sema.go
@@ -106,8 +106,12 @@ func sync_runtime_SemacquireRWMutex(addr *uint32, lifo bool, skipframes int) {
}
//go:linkname sync_runtime_SemacquireWaitGroup sync.runtime_SemacquireWaitGroup
-func sync_runtime_SemacquireWaitGroup(addr *uint32) {
- semacquire1(addr, false, semaBlockProfile, 0, waitReasonSyncWaitGroupWait)
+func sync_runtime_SemacquireWaitGroup(addr *uint32, synctestDurable bool) {
+ reason := waitReasonSyncWaitGroupWait
+ if synctestDurable {
+ reason = waitReasonSynctestWaitGroupWait
+ }
+ semacquire1(addr, false, semaBlockProfile, 0, reason)
}
//go:linkname poll_runtime_Semrelease internal/poll.runtime_Semrelease
@@ -631,7 +635,7 @@ func notifyListNotifyAll(l *notifyList) {
s.next = nil
if s.g.bubble != nil && getg().bubble != s.g.bubble {
println("semaphore wake of synctest goroutine", s.g.goid, "from outside bubble")
- panic("semaphore wake of synctest goroutine from outside bubble")
+ fatal("semaphore wake of synctest goroutine from outside bubble")
}
readyWithTime(s, 4)
s = next
@@ -688,7 +692,7 @@ func notifyListNotifyOne(l *notifyList) {
s.next = nil
if s.g.bubble != nil && getg().bubble != s.g.bubble {
println("semaphore wake of synctest goroutine", s.g.goid, "from outside bubble")
- panic("semaphore wake of synctest goroutine from outside bubble")
+ fatal("semaphore wake of synctest goroutine from outside bubble")
}
readyWithTime(s, 4)
return
diff --git a/src/runtime/synctest.go b/src/runtime/synctest.go
index ff1979a8d8..f676afa20d 100644
--- a/src/runtime/synctest.go
+++ b/src/runtime/synctest.go
@@ -5,6 +5,7 @@
package runtime
import (
+ "internal/runtime/atomic"
"internal/runtime/sys"
"unsafe"
)
@@ -13,12 +14,13 @@ import (
type synctestBubble struct {
mu mutex
timers timers
- now int64 // current fake time
- root *g // caller of synctest.Run
- waiter *g // caller of synctest.Wait
- main *g // goroutine started by synctest.Run
- waiting bool // true if a goroutine is calling synctest.Wait
- done bool // true if main has exited
+ id uint64 // unique id
+ now int64 // current fake time
+ root *g // caller of synctest.Run
+ waiter *g // caller of synctest.Wait
+ main *g // goroutine started by synctest.Run
+ waiting bool // true if a goroutine is calling synctest.Wait
+ done bool // true if main has exited
// The bubble is active (not blocked) so long as running > 0 || active > 0.
//
@@ -163,6 +165,8 @@ func (bubble *synctestBubble) raceaddr() unsafe.Pointer {
return unsafe.Pointer(bubble)
}
+var bubbleGen atomic.Uint64 // bubble ID counter
+
//go:linkname synctestRun internal/synctest.Run
func synctestRun(f func()) {
if debug.asynctimerchan.Load() != 0 {
@@ -174,6 +178,7 @@ func synctestRun(f func()) {
panic("synctest.Run called from within a synctest bubble")
}
bubble := &synctestBubble{
+ id: bubbleGen.Add(1),
total: 1,
running: 1,
root: gp,
@@ -313,6 +318,11 @@ func synctestwait_c(gp *g, _ unsafe.Pointer) bool {
return true
}
+//go:linkname synctest_isInBubble internal/synctest.IsInBubble
+func synctest_isInBubble() bool {
+ return getg().bubble != nil
+}
+
//go:linkname synctest_acquire internal/synctest.acquire
func synctest_acquire() any {
if bubble := getg().bubble; bubble != nil {
@@ -339,3 +349,85 @@ func synctest_inBubble(bubble any, f func()) {
}()
f()
}
+
+// specialBubble is a special used to associate objects with bubbles.
+type specialBubble struct {
+ _ sys.NotInHeap
+ special special
+ bubbleid uint64
+}
+
+// getOrSetBubbleSpecial checks the special record for p's bubble membership.
+//
+// If add is true and p is not associated with any bubble,
+// it adds a special record for p associating it with bubbleid.
+//
+// It returns ok==true if p is associated with bubbleid
+// (including if a new association was added),
+// and ok==false if not.
+func getOrSetBubbleSpecial(p unsafe.Pointer, bubbleid uint64, add bool) (ok bool) {
+ span := spanOfHeap(uintptr(p))
+ if span == nil {
+ throw("getOrSetBubbleSpecial on invalid pointer")
+ }
+
+ // Ensure that the span is swept.
+ // Sweeping accesses the specials list w/o locks, so we have
+ // to synchronize with it. And it's just much safer.
+ mp := acquirem()
+ span.ensureSwept()
+
+ offset := uintptr(p) - span.base()
+
+ lock(&span.speciallock)
+
+ // Find splice point, check for existing record.
+ iter, exists := span.specialFindSplicePoint(offset, _KindSpecialBubble)
+ if exists {
+ // p is already associated with a bubble.
+ // Return true iff it's the same bubble.
+ s := (*specialBubble)((unsafe.Pointer)(*iter))
+ ok = s.bubbleid == bubbleid
+ } else if add {
+ // p is not associated with a bubble,
+ // and we've been asked to add an association.
+ s := (*specialBubble)(mheap_.specialBubbleAlloc.alloc())
+ s.bubbleid = bubbleid
+ s.special.kind = _KindSpecialBubble
+ s.special.offset = offset
+ s.special.next = *iter
+ *iter = (*special)(unsafe.Pointer(s))
+ spanHasSpecials(span)
+ ok = true
+ } else {
+ // p is not associated with a bubble.
+ ok = false
+ }
+
+ unlock(&span.speciallock)
+ releasem(mp)
+
+ return ok
+}
+
+// synctest_associate associates p with the current bubble.
+// It returns false if p is already associated with a different bubble.
+//
+//go:linkname synctest_associate internal/synctest.associate
+func synctest_associate(p unsafe.Pointer) (ok bool) {
+ return getOrSetBubbleSpecial(p, getg().bubble.id, true)
+}
+
+// synctest_disassociate disassociates p from its bubble.
+//
+//go:linkname synctest_disassociate internal/synctest.disassociate
+func synctest_disassociate(p unsafe.Pointer) {
+ removespecial(p, _KindSpecialBubble)
+}
+
+// synctest_isAssociated reports whether p is associated with the current bubble.
+//
+//go:linkname synctest_isAssociated internal/synctest.isAssociated
+func synctest_isAssociated(p unsafe.Pointer) bool {
+ return getOrSetBubbleSpecial(p, getg().bubble.id, false)
+}
diff --git a/src/runtime/testdata/testprog/synctest.go b/src/runtime/testdata/testprog/synctest.go
new file mode 100644
index 0000000000..dd3a6df8a0
--- /dev/null
+++ b/src/runtime/testdata/testprog/synctest.go
@@ -0,0 +1,58 @@
+// Copyright 2025 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 main
+
+import (
+ "internal/synctest"
+ "sync"
+)
+
+func init() {
+ register("SynctestCond/signal/no_bubble", func() {
+ synctestCond(func(cond *sync.Cond) {
+ cond.Signal()
+ })
+ })
+ register("SynctestCond/broadcast/no_bubble", func() {
+ synctestCond(func(cond *sync.Cond) {
+ cond.Broadcast()
+ })
+ })
+ register("SynctestCond/signal/other_bubble", func() {
+ synctestCond(func(cond *sync.Cond) {
+ synctest.Run(cond.Signal)
+ })
+ })
+ register("SynctestCond/broadcast/other_bubble", func() {
+ synctestCond(func(cond *sync.Cond) {
+ synctest.Run(cond.Broadcast)
+ })
+ })
+}
+
+func synctestCond(f func(*sync.Cond)) {
+ var (
+ mu sync.Mutex
+ cond = sync.NewCond(&mu)
+ readyc = make(chan struct{})
+ wg sync.WaitGroup
+ )
+ defer wg.Wait()
+ wg.Go(func() {
+ synctest.Run(func() {
+ go func() {
+ mu.Lock()
+ defer mu.Unlock()
+ cond.Wait()
+ }()
+ synctest.Wait()
+ <-readyc // #1: signal that cond.Wait is waiting
+ <-readyc // #2: wait to continue
+ cond.Signal()
+ })
+ })
+ readyc <- struct{}{}
+ f(cond)
+}
diff --git a/src/runtime/traceruntime.go b/src/runtime/traceruntime.go
index 98ac1082a8..39adeb4c07 100644
--- a/src/runtime/traceruntime.go
+++ b/src/runtime/traceruntime.go
@@ -574,7 +574,9 @@ func (tl traceLocker) HeapAlloc(live uint64) {
// HeapGoal reads the current heap goal and emits a HeapGoal event.
func (tl traceLocker) HeapGoal() {
heapGoal := gcController.heapGoal()
- if heapGoal == ^uint64(0) {
+ // The heapGoal calculations will result in strange numbers if the GC if off. See go.dev/issue/63864.
+ // Check gcPercent before using the heapGoal in the trace.
+ if heapGoal == ^uint64(0) || gcController.gcPercent.Load() < 0 {
// Heap-based triggering is disabled.
heapGoal = 0
}
diff --git a/src/runtime/vgetrandom_linux.go b/src/runtime/vgetrandom_linux.go
index 8f39f6d3a6..225f7029be 100644
--- a/src/runtime/vgetrandom_linux.go
+++ b/src/runtime/vgetrandom_linux.go
@@ -40,7 +40,7 @@ func vgetrandomInit() {
vgetrandomAlloc.mmapProt = int32(params.MmapProt)
vgetrandomAlloc.mmapFlags = int32(params.MmapFlags)
- lockInit(&vgetrandomAlloc.statesLock, lockRankLeafRank)
+ lockInit(&vgetrandomAlloc.statesLock, lockRankVgetrandom)
}
func vgetrandomGetState() uintptr {
diff --git a/src/slices/iter.go b/src/slices/iter.go
index cd8f308ca0..bbea6134d9 100644
--- a/src/slices/iter.go
+++ b/src/slices/iter.go
@@ -46,6 +46,7 @@ func Values[Slice ~[]E, E any](s Slice) iter.Seq[E] {
// AppendSeq appends the values from seq to the slice and
// returns the extended slice.
+// If seq is empty, the result preserves the nilness of s.
func AppendSeq[Slice ~[]E, E any](s Slice, seq iter.Seq[E]) Slice {
for v := range seq {
s = append(s, v)
@@ -54,12 +55,14 @@ func AppendSeq[Slice ~[]E, E any](s Slice, seq iter.Seq[E]) Slice {
}
// Collect collects values from seq into a new slice and returns it.
+// If seq is empty, the result is nil.
func Collect[E any](seq iter.Seq[E]) []E {
return AppendSeq([]E(nil), seq)
}
// Sorted collects values from seq into a new slice, sorts the slice,
// and returns it.
+// If seq is empty, the result is nil.
func Sorted[E cmp.Ordered](seq iter.Seq[E]) []E {
s := Collect(seq)
Sort(s)
@@ -68,6 +71,7 @@ func Sorted[E cmp.Ordered](seq iter.Seq[E]) []E {
// SortedFunc collects values from seq into a new slice, sorts the slice
// using the comparison function, and returns it.
+// If seq is empty, the result is nil.
func SortedFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
s := Collect(seq)
SortFunc(s, cmp)
@@ -78,6 +82,7 @@ func SortedFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
// It then sorts the slice while keeping the original order of equal elements,
// using the comparison function to compare elements.
// It returns the new slice.
+// If seq is empty, the result is nil.
func SortedStableFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
s := Collect(seq)
SortStableFunc(s, cmp)
diff --git a/src/slices/slices.go b/src/slices/slices.go
index 32029cd8ed..30595793c9 100644
--- a/src/slices/slices.go
+++ b/src/slices/slices.go
@@ -131,6 +131,7 @@ func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
// and, if i < len(s), r[i+len(v)] == value originally at r[i].
// Insert panics if i > len(s).
// This function is O(len(s) + len(v)).
+// If the result is empty, it has the same nilness as s.
func Insert[S ~[]E, E any](s S, i int, v ...E) S {
_ = s[i:] // bounds check
@@ -217,6 +218,7 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
+// If the result is empty, it has the same nilness as s.
func Delete[S ~[]E, E any](s S, i, j int) S {
_ = s[i:j:len(s)] // bounds check
@@ -233,6 +235,7 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
// DeleteFunc removes any elements from s for which del returns true,
// returning the modified slice.
// DeleteFunc zeroes the elements between the new length and the original length.
+// If the result is empty, it has the same nilness as s.
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
i := IndexFunc(s, del)
if i == -1 {
@@ -253,6 +256,7 @@ func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
// modified slice.
// Replace panics if j > len(s) or s[i:j] is not a valid slice of s.
// When len(v) < (j-i), Replace zeroes the elements between the new length and the original length.
+// If the result is empty, it has the same nilness as s.
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
_ = s[i:j] // bounds check
@@ -345,6 +349,7 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
// Clone returns a copy of the slice.
// The elements are copied using assignment, so this is a shallow clone.
// The result may have additional unused capacity.
+// The result preserves the nilness of s.
func Clone[S ~[]E, E any](s S) S {
// Preserve nilness in case it matters.
if s == nil {
@@ -360,6 +365,7 @@ func Clone[S ~[]E, E any](s S) S {
// Compact modifies the contents of the slice s and returns the modified slice,
// which may have a smaller length.
// Compact zeroes the elements between the new length and the original length.
+// The result preserves the nilness of s.
func Compact[S ~[]E, E comparable](s S) S {
if len(s) < 2 {
return s
@@ -384,6 +390,7 @@ func Compact[S ~[]E, E comparable](s S) S {
// CompactFunc is like [Compact] but uses an equality function to compare elements.
// For runs of elements that compare equal, CompactFunc keeps the first one.
// CompactFunc zeroes the elements between the new length and the original length.
+// The result preserves the nilness of s.
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
if len(s) < 2 {
return s
@@ -409,6 +416,7 @@ func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
// another n elements. After Grow(n), at least n elements can be appended
// to the slice without another allocation. If n is negative or too large to
// allocate the memory, Grow panics.
+// The result preserves the nilness of s.
func Grow[S ~[]E, E any](s S, n int) S {
if n < 0 {
panic("cannot be negative")
@@ -421,6 +429,7 @@ func Grow[S ~[]E, E any](s S, n int) S {
}
// Clip removes unused capacity from the slice, returning s[:len(s):len(s)].
+// The result preserves the nilness of s.
func Clip[S ~[]E, E any](s S) S {
return s[:len(s):len(s)]
}
@@ -476,6 +485,7 @@ func Reverse[S ~[]E, E any](s S) {
}
// Concat returns a new slice concatenating the passed in slices.
+// If the concatenation is empty, the result is nil.
func Concat[S ~[]E, E any](slices ...S) S {
size := 0
for _, s := range slices {
diff --git a/src/slices/slices_test.go b/src/slices/slices_test.go
index 4ced7c0759..edf7e7b610 100644
--- a/src/slices/slices_test.go
+++ b/src/slices/slices_test.go
@@ -1462,3 +1462,86 @@ func TestIssue68488(t *testing.T) {
t.Error("clone keeps alive s due to array overlap")
}
}
+
+// This test asserts the behavior when the primary slice operand is nil.
+//
+// Some operations preserve the nilness of their operand while others
+// do not, but in all cases the behavior is documented.
+func TestNilness(t *testing.T) {
+ var (
+ emptySlice = []int{}
+ nilSlice = []int(nil)
+ emptySeq = func(yield func(int) bool) {}
+ truth = func(int) bool { return true }
+ equal = func(x, y int) bool { panic("unreachable") }
+ )
+
+ wantNil := func(slice []int, cond string) {
+ if slice != nil {
+ t.Errorf("%s != nil", cond)
+ }
+ }
+ wantNonNil := func(slice []int, cond string) {
+ if slice == nil {
+ t.Errorf("%s == nil", cond)
+ }
+ }
+
+ // The update functions
+ // Insert, AppendSeq, Delete, DeleteFunc, Clone, Compact, CompactFunc
+ // preserve nilness, like s[i:j].
+ wantNil(AppendSeq(nilSlice, emptySeq), "AppendSeq(nil, empty)")
+ wantNonNil(AppendSeq(emptySlice, emptySeq), "AppendSeq(nil, empty)")
+
+ wantNil(Insert(nilSlice, 0), "Insert(nil, 0)")
+ wantNonNil(Insert(emptySlice, 0), "Insert(empty, 0)")
+
+ wantNil(Delete(nilSlice, 0, 0), "Delete(nil, 0, 0)")
+ wantNonNil(Delete(emptySlice, 0, 0), "Delete(empty, 0, 0)")
+ wantNonNil(Delete([]int{1}, 0, 1), "Delete([]int{1}, 0, 1)")
+
+ wantNil(DeleteFunc(nilSlice, truth), "DeleteFunc(nil, f)")
+ wantNonNil(DeleteFunc(emptySlice, truth), "DeleteFunc(empty, f)")
+ wantNonNil(DeleteFunc([]int{1}, truth), "DeleteFunc([]int{1}, truth)")
+
+ wantNil(Replace(nilSlice, 0, 0), "Replace(nil, 0, 0)")
+ wantNonNil(Replace(emptySlice, 0, 0), "Replace(empty, 0, 0)")
+ wantNonNil(Replace([]int{1}, 0, 1), "Replace([]int{1}, 0, 1)")
+
+ wantNil(Clone(nilSlice), "Clone(nil)")
+ wantNonNil(Clone(emptySlice), "Clone(empty)")
+
+ wantNil(Compact(nilSlice), "Compact(nil)")
+ wantNonNil(Compact(emptySlice), "Compact(empty)")
+
+ wantNil(CompactFunc(nilSlice, equal), "CompactFunc(nil)")
+ wantNonNil(CompactFunc(emptySlice, equal), "CompactFunc(empty)")
+
+ wantNil(Grow(nilSlice, 0), "Grow(nil, 0)")
+ wantNonNil(Grow(emptySlice, 0), "Grow(empty, 0)")
+
+ wantNil(Clip(nilSlice), "Clip(nil)")
+ wantNonNil(Clip(emptySlice), "Clip(empty)")
+ wantNonNil(Clip([]int{1}[:0:0]), "Clip([]int{1}[:0:0])")
+
+ // Concat returns nil iff the result is empty.
+ // This is an unfortunate irregularity.
+ wantNil(Concat(nilSlice, emptySlice, nilSlice, emptySlice), "Concat(nil, ...empty...)")
+ wantNil(Concat(emptySlice, emptySlice, nilSlice, emptySlice), "Concat(empty, ...empty...)")
+ wantNil(Concat[[]int](), "Concat()")
+
+ // Repeat never returns nil. Another irregularity.
+ wantNonNil(Repeat(nilSlice, 0), "Repeat(nil, 0)")
+ wantNonNil(Repeat(emptySlice, 0), "Repeat(empty, 0)")
+ wantNonNil(Repeat(nilSlice, 2), "Repeat(nil, 2)")
+ wantNonNil(Repeat(emptySlice, 2), "Repeat(empty, 2)")
+
+ // The collection functions
+ // Collect, Sorted, SortedFunc, SortedStableFunc
+ // return nil given an empty sequence.
+ wantNil(Collect(emptySeq), "Collect(empty)")
+
+ wantNil(Sorted(emptySeq), "Sorted(empty)")
+ wantNil(SortedFunc(emptySeq, cmp.Compare), "SortedFunc(empty)")
+ wantNil(SortedStableFunc(emptySeq, cmp.Compare), "SortedStableFunc(empty)")
+}
diff --git a/src/sync/runtime.go b/src/sync/runtime.go
index 99e5bccbee..ae3368e58d 100644
--- a/src/sync/runtime.go
+++ b/src/sync/runtime.go
@@ -14,7 +14,7 @@ import "unsafe"
func runtime_Semacquire(s *uint32)
// SemacquireWaitGroup is like Semacquire, but for WaitGroup.Wait.
-func runtime_SemacquireWaitGroup(s *uint32)
+func runtime_SemacquireWaitGroup(s *uint32, synctestDurable bool)
// Semacquire(RW)Mutex(R) is like Semacquire, but for profiling contended
// Mutexes and RWMutexes.
diff --git a/src/sync/waitgroup.go b/src/sync/waitgroup.go
index c850f58ed1..efc63be099 100644
--- a/src/sync/waitgroup.go
+++ b/src/sync/waitgroup.go
@@ -6,6 +6,7 @@ package sync
import (
"internal/race"
+ "internal/synctest"
"sync/atomic"
"unsafe"
)
@@ -47,10 +48,17 @@ import (
type WaitGroup struct {
noCopy noCopy
- state atomic.Uint64 // high 32 bits are counter, low 32 bits are waiter count.
+ // Bits (high to low):
+ // bits[0:32] counter
+ // bits[32] flag: synctest bubble membership
+ // bits[33:64] wait count
+ state atomic.Uint64
sema uint32
}
+// waitGroupBubbleFlag indicates that a WaitGroup is associated with a synctest bubble.
+const waitGroupBubbleFlag = 0x8000_0000
+
// Add adds delta, which may be negative, to the [WaitGroup] task counter.
// If the counter becomes zero, all goroutines blocked on [WaitGroup.Wait] are released.
// If the counter goes negative, Add panics.
@@ -75,9 +83,27 @@ func (wg *WaitGroup) Add(delta int) {
race.Disable()
defer race.Enable()
}
+ if synctest.IsInBubble() {
+ // If Add is called from within a bubble, then all Add calls must be made
+ // from the same bubble.
+ if !synctest.Associate(wg) {
+ // wg is already associated with a different bubble.
+ fatal("sync: WaitGroup.Add called from multiple synctest bubbles")
+ } else {
+ state := wg.state.Or(waitGroupBubbleFlag)
+ if state != 0 && state&waitGroupBubbleFlag == 0 {
+ // Add has been called from outside this bubble.
+ fatal("sync: WaitGroup.Add called from inside and outside synctest bubble")
+ }
+ }
+ }
state := wg.state.Add(uint64(delta) << 32)
+ if state&waitGroupBubbleFlag != 0 && !synctest.IsInBubble() {
+ // Add has been called from within a synctest bubble (and we aren't in one).
+ fatal("sync: WaitGroup.Add called from inside and outside synctest bubble")
+ }
v := int32(state >> 32)
- w := uint32(state)
+ w := uint32(state & 0x7fffffff)
if race.Enabled && delta > 0 && v == int32(delta) {
// The first increment must be synchronized with Wait.
// Need to model this as a read, because there can be
@@ -90,6 +116,13 @@ func (wg *WaitGroup) Add(delta int) {
if w != 0 && delta > 0 && v == int32(delta) {
panic("sync: WaitGroup misuse: Add called concurrently with Wait")
}
+ if v == 0 && state&waitGroupBubbleFlag != 0 {
+ // Disassociate the WaitGroup from its bubble.
+ synctest.Disassociate(wg)
+ if w == 0 {
+ wg.state.Store(0)
+ }
+ }
if v > 0 || w == 0 {
return
}
@@ -147,7 +180,21 @@ func (wg *WaitGroup) Wait() {
// otherwise concurrent Waits will race with each other.
race.Write(unsafe.Pointer(&wg.sema))
}
- runtime_SemacquireWaitGroup(&wg.sema)
+ synctestDurable := false
+ if state&waitGroupBubbleFlag != 0 && synctest.IsInBubble() {
+ if race.Enabled {
+ race.Enable()
+ }
+ if synctest.IsAssociated(wg) {
+ // Add was called within the current bubble,
+ // so this Wait is durably blocking.
+ synctestDurable = true
+ }
+ if race.Enabled {
+ race.Disable()
+ }
+ }
+ runtime_SemacquireWaitGroup(&wg.sema, synctestDurable)
if wg.state.Load() != 0 {
panic("sync: WaitGroup is reused before previous Wait has returned")
}
diff --git a/src/testing/synctest/synctest.go b/src/testing/synctest/synctest.go
index c7e93b2201..57a6fbfbd6 100644
--- a/src/testing/synctest/synctest.go
+++ b/src/testing/synctest/synctest.go
@@ -72,10 +72,17 @@
// - a blocking select statement where every case is a channel created
// within the bubble
// - [sync.Cond.Wait]
-// - [sync.WaitGroup.Wait]
+// - [sync.WaitGroup.Wait], when [sync.WaitGroup.Add] was called within the bubble
// - [time.Sleep]
//
-// Locking a [sync.Mutex] or [sync.RWMutex] is not durably blocking.
+// Operations not in the above list are not durably blocking.
+// In particular, the following operations may block a goroutine,
+// but are not durably blocking because the goroutine can be unblocked
+// by an event occurring outside its bubble:
+//
+// - locking a [sync.Mutex] or [sync.RWMutex]
+// - blocking on I/O, such as reading from a network socket
+// - system calls
//
// # Isolation
//
@@ -83,6 +90,13 @@
// is associated with it. Operating on a bubbled channel, timer, or
// ticker from outside the bubble panics.
//
+// A [sync.WaitGroup] becomes associated with a bubble on the first
+// call to Add or Go. Once a WaitGroup is associated with a bubble,
+// calling Add or Go from outside that bubble is a fatal error.
+//
+// [sync.Cond.Wait] is durably blocking. Waking a goroutine in a bubble
+// blocked on Cond.Wait from outside the bubble is a fatal error.
+//
// Cleanup functions and finalizers registered with
// [runtime.AddCleanup] and [runtime.SetFinalizer]
// run outside of any bubble.
@@ -259,13 +273,19 @@ import (
// associated with the bubble.
// - T.Run, T.Parallel, and T.Deadline must not be called.
func Test(t *testing.T, f func(*testing.T)) {
+ var ok bool
synctest.Run(func() {
- testingSynctestTest(t, f)
+ ok = testingSynctestTest(t, f)
})
+ if !ok {
+ // Fail the test outside the bubble,
+ // so test durations get set using real time.
+ t.FailNow()
+ }
}
//go:linkname testingSynctestTest testing/synctest.testingSynctestTest
-func testingSynctestTest(t *testing.T, f func(*testing.T))
+func testingSynctestTest(t *testing.T, f func(*testing.T)) bool
// Wait blocks until every goroutine within the current bubble,
// other than the current goroutine, is durably blocked.
diff --git a/src/testing/synctest/synctest_test.go b/src/testing/synctest/synctest_test.go
index 4897df999e..822fd6fe1c 100644
--- a/src/testing/synctest/synctest_test.go
+++ b/src/testing/synctest/synctest_test.go
@@ -22,37 +22,56 @@ func TestSuccess(t *testing.T) {
}
func TestFatal(t *testing.T) {
- runTest(t, func() {
+ runTest(t, nil, func() {
synctest.Test(t, func(t *testing.T) {
t.Fatal("fatal")
})
- }, `^=== RUN TestFatal
+ }, `^--- FAIL: TestFatal.*
synctest_test.go:.* fatal
---- FAIL: TestFatal.*
FAIL
$`)
}
func TestError(t *testing.T) {
- runTest(t, func() {
+ runTest(t, nil, func() {
synctest.Test(t, func(t *testing.T) {
t.Error("error")
})
- }, `^=== RUN TestError
+ }, `^--- FAIL: TestError.*
synctest_test.go:.* error
---- FAIL: TestError.*
+FAIL
+$`)
+}
+
+func TestVerboseError(t *testing.T) {
+ runTest(t, []string{"-test.v"}, func() {
+ synctest.Test(t, func(t *testing.T) {
+ t.Error("error")
+ })
+ }, `^=== RUN TestVerboseError
+ synctest_test.go:.* error
+--- FAIL: TestVerboseError.*
FAIL
$`)
}
func TestSkip(t *testing.T) {
- runTest(t, func() {
+ runTest(t, nil, func() {
synctest.Test(t, func(t *testing.T) {
t.Skip("skip")
})
- }, `^=== RUN TestSkip
+ }, `^PASS
+$`)
+}
+
+func TestVerboseSkip(t *testing.T) {
+ runTest(t, []string{"-test.v"}, func() {
+ synctest.Test(t, func(t *testing.T) {
+ t.Skip("skip")
+ })
+ }, `^=== RUN TestVerboseSkip
synctest_test.go:.* skip
---- PASS: TestSkip.*
+--- PASS: TestVerboseSkip.*
PASS
$`)
}
@@ -131,7 +150,7 @@ func wantPanic(t *testing.T, want string) {
}
}
-func runTest(t *testing.T, f func(), pattern string) {
+func runTest(t *testing.T, args []string, f func(), pattern string) {
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
f()
return
@@ -139,7 +158,8 @@ func runTest(t *testing.T, f func(), pattern string) {
t.Helper()
re := regexp.MustCompile(pattern)
testenv.MustHaveExec(t)
- cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^"+t.Name()+"$", "-test.v", "-test.count=1")
+ cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^"+regexp.QuoteMeta(t.Name())+"$", "-test.count=1")
+ cmd.Args = append(cmd.Args, args...)
cmd = testenv.CleanCmdEnv(cmd)
cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
out, _ := cmd.CombinedOutput()
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 85ac1aeb32..b5305f29cc 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -1045,7 +1045,7 @@ func (c *common) destination() *common {
c.mu.Lock()
defer c.mu.Unlock()
- if !c.done {
+ if !c.done && !c.isSynctest {
return c
}
for parent := c.parent; parent != nil; parent = parent.parent {
@@ -1851,7 +1851,8 @@ func tRunner(t *T, fn func(t *T)) {
t.Logf("cleanup panicked with %v", r)
}
// Flush the output log up to the root before dying.
- for root := &t.common; root.parent != nil; root = root.parent {
+ // Skip this if this *T is a synctest bubble, because we're not a subtest.
+ for root := &t.common; !root.isSynctest && root.parent != nil; root = root.parent {
root.mu.Lock()
root.duration += highPrecisionTimeSince(root.start)
d := root.duration
@@ -2013,7 +2014,7 @@ func (t *T) Run(name string, f func(t *T)) bool {
// It is called by synctest.Test, from within an already-created bubble.
//
//go:linkname testingSynctestTest testing/synctest.testingSynctestTest
-func testingSynctestTest(t *T, f func(*T)) {
+func testingSynctestTest(t *T, f func(*T)) (ok bool) {
if t.cleanupStarted.Load() {
panic("testing: synctest.Run called during t.Cleanup")
}
@@ -2037,7 +2038,6 @@ func testingSynctestTest(t *T, f func(*T)) {
},
tstate: t.tstate,
}
- t2.setOutputWriter()
go tRunner(t2, f)
if !<-t2.signal {
@@ -2045,6 +2045,7 @@ func testingSynctestTest(t *T, f func(*T)) {
// parent tests by one of the subtests. Continue aborting up the chain.
runtime.Goexit()
}
+ return !t2.failed
}
// Deadline reports the time at which the test binary will have
diff --git a/test/fixedbugs/issue73748a.go b/test/fixedbugs/issue73748a.go
new file mode 100644
index 0000000000..c8ac10c29c
--- /dev/null
+++ b/test/fixedbugs/issue73748a.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2025 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 main
+
+import (
+ "context"
+ "io"
+ "runtime/trace"
+)
+
+type T struct {
+ a [16]int
+}
+
+//go:noinline
+func f(x *T) {
+ *x = T{}
+}
+
+func main() {
+ trace.Start(io.Discard)
+ defer func() {
+ recover()
+ trace.Log(context.Background(), "a", "b")
+
+ }()
+ f(nil)
+}
diff --git a/test/fixedbugs/issue73748b.go b/test/fixedbugs/issue73748b.go
new file mode 100644
index 0000000000..ff094a9764
--- /dev/null
+++ b/test/fixedbugs/issue73748b.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2025 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 main
+
+import (
+ "context"
+ "io"
+ "runtime/trace"
+)
+
+type T struct {
+ a [16]int
+}
+
+//go:noinline
+func f(x, y *T) {
+ *x = *y
+}
+
+func main() {
+ trace.Start(io.Discard)
+ defer func() {
+ recover()
+ trace.Log(context.Background(), "a", "b")
+
+ }()
+ f(nil, nil)
+}