10 Commits

Author SHA1 Message Date
e3fbb58954 math: add assembly func archExp and archExp2 for riscv64
goos: linux
goarch: riscv64
pkg: math
                       │   math-old    │               math-new               │
                       │    sec/op     │    sec/op     vs base                │
Exp-64                    51.38n ±  0%    31.98n ± 0%  -37.76% (p=0.000 n=10)
ExpGo-64                  59.27n ±  0%    58.48n ± 0%   -1.33% (p=0.000 n=10)
Expm1-64                  26.98n ±  0%    26.98n ± 0%        ~ (p=0.187 n=10)
Exp2-64                   50.04n ±  0%    28.51n ± 0%  -43.03% (p=0.000 n=10)
Exp2Go-64                 57.81n ±  0%    57.81n ± 0%        ~ (p=0.555 n=10)
Frexp-64                  5.629n ±  0%    5.426n ± 0%   -3.60% (p=0.000 n=10)
Ldexp-64                  7.584n ±  0%    7.550n ± 0%   -0.45% (p=0.002 n=10)

Change-Id: Ic122bf9598302f947c6dbf751db591f403c50373
2026-03-12 11:14:13 +08:00
kovan
26d5e16075 runtime/cgo: clarify pinning requirement in Handle example
Add a comment to the void* example in the Handle documentation
highlighting that if the C code keeps the pointer after the call
returns, runtime.Pinner should be used to pin it.

The existing documentation already mentions this requirement in prose
(lines 69-73), but adding a comment directly in the example makes it
more visible and less likely to be missed when copying the example.

Fixes #68044

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change-Id: I20a5b1ad10de1b441980dc7ed3185720e77912bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/741443
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-03-11 16:45:41 -07:00
Ian Lance Taylor
6b7763407c testing: recognize helper functions that use range-over-function
This assumes the current behavior of the gc compiler:
range functions use a suffix of -rangeNNNN.

Fixes #72794

Change-Id: I3c10c60829853cf2cb4c17a75f6243def0313ae9
Reviewed-on: https://go-review.googlesource.com/c/go/+/656775
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: David Chase <drchase@google.com>
2026-03-11 16:42:19 -07:00
kovan
3fc4af70d0 net/http: document which headers Request.Write handles specially
Document that Header values for Host, Content-Length,
Transfer-Encoding, and Trailer are not used by Write, as these
are derived from other Request fields. Also document that
User-Agent defaults to "Go-http-client/1.1" if not set in Header.

Fixes #68635

Change-Id: Ie182777ae094657cf3971fed989af1bd5e875d9f
Reviewed-on: https://go-review.googlesource.com/c/go/+/741442
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
2026-03-11 16:41:01 -07:00
Damien Neil
c43088c7a6 net, net/netip: document the lack of security properties of IsPrivate
IsPrivate reports whether an address is in one of the address blocks
reserved for private use. This is not a security property of an address.
Add some additional text to hopefully make this clearer.

Change-Id: Ib34e67947095fe256b305e429da185707aca039b
Reviewed-on: https://go-review.googlesource.com/c/go/+/583935
Auto-Submit: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Sean Liao <sean@liao.dev>
2026-03-11 15:09:09 -07:00
Russ Cox
3d7681ebab cmd/link: fix macOS 13 build
Write our own load command for macOS builds,
to make sure we can put the versions in.
Builds on older macOS were seeing an LC_VERSION_MIN instead
and scribbling over fields that didn't exist.

Fixes #78070.

Change-Id: If338d0506b1156b133253e496f29818a29a22a91
Reviewed-on: https://go-review.googlesource.com/c/go/+/754241
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Russ Cox <rsc@golang.org>
2026-03-11 13:44:26 -07:00
Noam Cohen
a8f99ef1f6 go/printer: use architecture-independent math for alignment decisions
The `exprList` function uses a geometric mean of expression sizes to
decide whether to break column alignment in composite literals.
Previously, this was computed using `math.Exp` and `math.Log`,
which are not guaranteed to produce bit-for-bit identical results
across CPU architectures. For example, `math.Exp(math.Log(95))`
returns exactly 95.0 on arm64 but 94.999... on amd64, which can flip
the alignment decision.

Replace math operations with approximations that are
architecture-independent. The approximations are sufficient
for this heuristic and are guaranteed to produce identical formatting
on all architectures.

Fixes #77959

Change-Id: I78d00d85fd62859803d14d619b4a45e2e5081499
Reviewed-on: https://go-review.googlesource.com/c/go/+/752862
Auto-Submit: Alan Donovan <adonovan@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2026-03-11 13:27:47 -07:00
Nicholas S. Husin
96d6d38872 net/http: add pluggable HTTP/3 support for closing idle connections
This CL defines the closeIdleConectionser interface, allowing us to call
a CloseIdleConnections method that a pluggable HTTP/3 transport might
implement.

Concretely, this allows an HTTP/3 transport implementation to clean up
resources such as an open UDP socket that is no longer needed,
preventing resources from lingering around indefinitely until the entire
program exits.

For #77440

Change-Id: I7216caee58954c3651f96a56dbf27ec74c539ad3
Reviewed-on: https://go-review.googlesource.com/c/go/+/753161
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
2026-03-11 10:12:36 -07:00
qmuntal
e30e65f7a8 syscall,runtime/cgo: use cgo_ldflag to link against -lsocket and -lxnet on Solaris
The -lsocket and -lxnet flags are needed for accept4 syscall on Solaris.
The runtime/cgo package doens't use them, so it doesn't make sense for
it to explicitly link against those libraries.

Instead, use the //go:cgo_ldflag in the syscall package.

Cq-Include-Trybots: luci.golang.try:gotip-solaris-amd64
Change-Id: I10db524ebf1c720a460515d8c1f362b0070bd771
Reviewed-on: https://go-review.googlesource.com/c/go/+/751760
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Auto-Submit: Quim Muntal <quimmuntal@gmail.com>
2026-03-10 22:58:26 -07:00
qmuntal
d3651c5888 runtime/poll: fix race condition in Window's SendFile
The destination of SendFile is a socket, which doesn't support file
offsets. There is no need to keep track of the file offset, and doing
so causes a race between SendFile and Read.

While here, make sure that SendFile tests do call poll.SendFile.

Fixes #78015

Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-race,gotip-linux-amd64-race
Change-Id: I8cce45c0c110e848d9bdbc5ba340b92ca041f0a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/752860
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
2026-03-10 22:58:01 -07:00
25 changed files with 411 additions and 25 deletions

View File

@@ -461,14 +461,9 @@ func (ctxt *Link) domacho() {
if err != nil {
Exitf("%v", err)
}
if load != nil {
machoPlatform = load.platform
if load != nil && load.platform != PLATFORM_MACOS {
ml := newMachoLoad(ctxt.Arch, load.cmd.type_, uint32(len(load.cmd.data)))
copy(ml.data, load.cmd.data)
if machoPlatform == PLATFORM_MACOS {
ml.data[1] = macOS.version()
ml.data[2] = macSDK.version()
}
break
}
}
@@ -477,7 +472,7 @@ func (ctxt *Link) domacho() {
if buildcfg.GOOS == "ios" {
machoPlatform = PLATFORM_IOS
}
if ctxt.LinkMode == LinkInternal && machoPlatform == PLATFORM_MACOS {
if load == nil && machoPlatform == PLATFORM_MACOS {
ml := newMachoLoad(ctxt.Arch, imacho.LC_BUILD_VERSION, 4)
ml.data[0] = uint32(machoPlatform)
ml.data[1] = macOS.version()

28
src/go/printer/math.go Normal file
View File

@@ -0,0 +1,28 @@
// Copyright 2026 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 printer
import "math"
// log2ish returns a crude approximation to log₂(x).
// The result is only used for heuristic alignment decisions and should
// not be used where precision matters.
// The approximation is guaranteed to produce identical results
// across all architectures.
func log2ish(x float64) float64 {
f, e := math.Frexp(x)
return float64(e) + 2*(f-1)
}
// exp2ish returns a crude approximation to 2**x.
// The result is only used for heuristic alignment decisions and should
// not be used where precision matters.
// The approximation is guaranteed to produce identical results
// across all architectures.
func exp2ish(x float64) float64 {
n := math.Floor(x)
f := x - n
return math.Ldexp(1+f, int(n))
}

View File

@@ -11,7 +11,6 @@ package printer
import (
"go/ast"
"go/token"
"math"
"strconv"
"strings"
"unicode"
@@ -183,9 +182,9 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
// We use the ratio between the geometric mean of the previous key sizes and
// the current size to determine if there should be a break in the alignment.
// To compute the geometric mean we accumulate the ln(size) values (lnsum)
// To compute the geometric mean we accumulate the log₂(size) values (log2sum)
// and the number of sizes included (count).
lnsum := 0.0
log2sum := 0.0
count := 0
// print all list elements
@@ -229,7 +228,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
useFF = false
} else {
const r = 2.5 // threshold
geomean := math.Exp(lnsum / float64(count)) // count > 0
geomean := exp2ish(log2sum / float64(count)) // count > 0
ratio := float64(size) / geomean
useFF = r*ratio <= 1 || r <= ratio
}
@@ -260,7 +259,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
// the section), reset the geomean variables since we are
// starting a new group of elements with the next element.
if nbreaks > 1 {
lnsum = 0
log2sum = 0
count = 0
}
}
@@ -284,7 +283,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
}
if size > 0 {
lnsum += math.Log(float64(size))
log2sum += log2ish(float64(size))
count++
}

View File

@@ -170,3 +170,10 @@ var _ = S{
F1____: []string{},
F2: []string{},
}
// Issue #77959: formatting must be consistent across architectures.
var _ = []any{
(expr_size_95_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(0), // 0
(expr_size_38_xxxxxxxxxxxxxxxxxxxx)(0), // 1
(*expr_size_126_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(nil), // 2
}

View File

@@ -177,3 +177,10 @@ var _ = S{
},
F2: []string{},
}
// Issue #77959: formatting must be consistent across architectures.
var _ = []any{
(expr_size_95_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(0), // 0
(expr_size_38_xxxxxxxxxxxxxxxxxxxx)(0), // 1
(*expr_size_126_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)(nil), // 2
}

View File

@@ -68,8 +68,8 @@ func SendFile(fd *FD, src uintptr, size int64) (written int64, err error, handle
chunkSize = size
}
fd.setOffset(startpos + written)
n, err := fd.execIO('w', func(o *operation) (uint32, error) {
o.setOffset(startpos + written)
err := syscall.TransmitFile(fd.Sysfd, hsrc, uint32(chunkSize), 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
if err != nil {
return 0, err

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build arm64 || loong64
//go:build arm64 || loong64 || riscv64
package math

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !arm64 && !loong64
//go:build !arm64 && !loong64 && !riscv64
package math

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build amd64 || arm64 || loong64 || s390x
//go:build amd64 || arm64 || loong64 || riscv64 || s390x
package math

View File

@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !amd64 && !arm64 && !loong64 && !s390x
//go:build !amd64 && !arm64 && !loong64 && !riscv64 && !s390x
package math

236
src/math/exp_riscv64.s Normal file
View File

@@ -0,0 +1,236 @@
// Copyright 2026 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.
#include "textflag.h"
#define NearZero 0x3e30000000000000 // 2**-28
#define PosInf 0x7ff0000000000000
#define FracMask 0x000fffffffffffff
#define C1 0x3cb0000000000000 // 2**-52
DATA exprodata<>+0(SB)/8, $0.0
DATA exprodata<>+8(SB)/8, $0.5
DATA exprodata<>+16(SB)/8, $1.0
DATA exprodata<>+24(SB)/8, $2.0
DATA exprodata<>+32(SB)/8, $6.93147180369123816490e-01 // Ln2Hi
DATA exprodata<>+40(SB)/8, $1.90821492927058770002e-10 // Ln2Lo
DATA exprodata<>+48(SB)/8, $1.44269504088896338700e+00 // Log2e
DATA exprodata<>+56(SB)/8, $7.09782712893383973096e+02 // Overflow
DATA exprodata<>+64(SB)/8, $-7.45133219101941108420e+02 // Underflow
DATA exprodata<>+72(SB)/8, $1.0239999999999999e+03 // Overflow2
DATA exprodata<>+80(SB)/8, $-1.0740e+03 // Underflow2
DATA exprodata<>+88(SB)/8, $3.7252902984619141e-09 // NearZero
GLOBL exprodata<>+0(SB), NOPTR|RODATA, $96
DATA expmultirodata<>+0(SB)/8, $1.66666666666666657415e-01 // P1
DATA expmultirodata<>+8(SB)/8, $-2.77777777770155933842e-03 // P2
DATA expmultirodata<>+16(SB)/8, $6.61375632143793436117e-05 // P3
DATA expmultirodata<>+24(SB)/8, $-1.65339022054652515390e-06 // P4
DATA expmultirodata<>+32(SB)/8, $4.13813679705723846039e-08 // P5
GLOBL expmultirodata<>+0(SB), NOPTR|RODATA, $40
// Exp returns e**x, the base-e exponential of x.
// This is an assembly implementation of the method used for function Exp in file exp.go.
//
// func Exp(x float64) float64
TEXT ·archExp(SB),$0-16
MOVD x+0(FP), F0 // F0 = x
MOV $exprodata<>+0(SB), X5
MOVD 56(X5), F1 // Overflow
MOVD 64(X5), F2 // Underflow
MOVD 88(X5), F3 // NearZero
MOVD 16(X5), F17 // 1.0
FEQD F0, F0, X7
BEQ X0, X7, isNaN // x = NaN, return NaN
FLTD F0, F1, X7
BNE X0, X7, overflow // x > Overflow, return PosInf
FLTD F2, F0, X7
BNE X0, X7, underflow // x < Underflow, return 0
FABSD F0, F5
FLTD F3, F5, X7
BNE X0, X7, nearzero // fabs(x) < NearZero, return 1 + x
// argument reduction, x = k*ln2 + r, |r| <= 0.5*ln2
// computed as r = hi - lo for extra precision.
MOVD 0(X5), F5
MOVD 8(X5), F3
MOVD 48(X5), F2
FLTD F0, F5, X7
BNE X0, X7, add // x > 0
sub:
FMSUBD F0, F2, F3, F3 // Log2e*x - 0.5
JMP 2(PC)
add:
FMADDD F0, F2, F3, F3 // Log2e*x + 0.5
FCVTLD.RTZ F3, X16 // float64 -> int64
FCVTDL X16, F3 // int64 -> float64
MOVD 32(X5), F4
MOVD 40(X5), F5
FNMSUBD F3, F4, F0, F4
FMULD F3, F5, F5
FSUBD F5, F4, F6
FMULD F6, F6, F7
// compute c
// r=(FMA x y z) -> FMADDD z, y, x, r
// r=(FMA x y z) -> FMADDD x, y, z, r
MOV $expmultirodata<>+0(SB), X6
MOVD 32(X6), F8
MOVD 24(X6), F9
FMADDD F7, F8, F9, F13
MOVD 16(X6), F10
FMADDD F7, F13, F10, F13
MOVD 8(X6), F11
FMADDD F7, F13, F11, F13
MOVD 0(X6), F12
FMADDD F7, F13, F12, F13
FNMSUBD F21, F8, F6, F8
// compute y
MOVD 24(X5), F14
FSUBD F8, F14, F14
FMULD F6, F8, F15
FDIVD F14, F15, F15
FSUBD F15, F5, F15
FSUBD F4, F15, F15
FSUBD F15, F17, F16
// inline Ldexp(y, k), benefit:
// 1, no parameter pass overhead.
// 2, skip unnecessary checks for Inf/NaN/Zero
MOVD F16, X15
MOV $FracMask, X20
AND X20, X15, X17 // fraction
SRL $52, X15, X18 // exponent
ADD X16, X18
MOV $1, X21
BGE X18, X21, normal
ADD $52, X18 // denormal
MOV $C1, X19
MOVD X19, F17
normal:
SLL $52, X18
OR X18, X17, X15
MOVD X15, F0
FMULD F17, F0, F0 // return m * x
MOVD F0, ret+8(FP)
RET
nearzero:
FADDD F17, F0, F0
isNaN:
MOVD F0, ret+8(FP)
RET
underflow:
MOV X0, ret+8(FP)
RET
overflow:
MOV $PosInf, X15
MOV X15, ret+8(FP)
RET
// Exp2 returns 2**x, the base-2 exponential of x.
// This is an assembly implementation of the method used for function Exp2 in file exp.go.
//
// func Exp2(x float64) float64
TEXT ·archExp2(SB),$0-16
MOVD x+0(FP), F0 // F0 = x
MOV $exprodata<>+0(SB), X5
MOVD 72(X5), F1 // Overflow2
MOVD 80(X5), F2 // Underflow2
MOVD 88(X5), F3 // NearZero
FEQD F0, F0, X7
BEQ X0, X7, isNaN // x = NaN, return NaN
FLTD F0, F1, X7
BNE X0, X7, overflow // x > Overflow, return PosInf
FLTD F2, F0, X7
BNE X0, X7, underflow // x < Underflow, return 0
// argument reduction; x = r*lg(e) + k with |r| <= ln(2)/2
// computed as r = hi - lo for extra precision.
MOVD 0(X5), F10
MOVD 8(X5), F2
FLTD F0, F10, X7
BNE X0, X7, add
sub:
FSUBD F2, F0, F3 // x - 0.5
JMP 2(PC)
add:
FADDD F2, F0, F3 // x + 0.5
FCVTLD.RTZ F3, X16
FCVTDL X16, F3
MOVD 32(X5), F4
MOVD 40(X5), F5
FSUBD F3, F0, F3
FMULD F3, F4, F4
FNMSUBD F5, F3, F10, F5
FSUBD F5, F4, F6
FMULD F6, F6, F7
// compute c
MOV $expmultirodata<>+0(SB), X6
MOVD 32(X6), F13
MOVD 24(X6), F9
FMADDD F7, F13, F9, F13
MOVD 16(X6), F10
FMADDD F7, F13, F10, F13
MOVD 8(X6), F11
FMADDD F7, F13, F11, F13
MOVD 0(X6), F12
FMADDD F7, F13, F12, F13
FNMSUBD F7, F13, F6, F13
// compute y
MOVD 24(X5), F14
FSUBD F13, F14, F14
FMULD F6, F13, F15
FDIVD F14, F15, F15
MOVD 16(X5), F17
FSUBD F15, F5, F15
FSUBD F4, F15, F15
FSUBD F15, F17, F16
// inline Ldexp(y, k), benefit:
// 1, no parameter pass overhead.
// 2, skip unnecessary checks for Inf/NaN/Zero
MOVD F16, X15
MOV $FracMask, X20
SRL $52, X15, X18 // exponent
AND X20, X15, X17 // fraction
ADD X16, X18
MOV $1, X21
BGE X18, X21, normal
ADD $52, X18 // denormal
MOV $C1, X19
MOVD X19, F17
normal:
SLL $52, X18
OR X18, X17, X15
MOVD X15, F0
FMULD F17, F0, F0
isNaN:
MOVD F0, ret+8(FP)
RET
underflow:
MOV X0, ret+8(FP)
RET
overflow:
MOV $PosInf, X15
MOV X15, ret+8(FP)
RET

View File

@@ -558,6 +558,11 @@ const defaultUserAgent = "Go-http-client/1.1"
// If Body is present, Content-Length is <= 0 and [Request.TransferEncoding]
// hasn't been set to "identity", Write adds "Transfer-Encoding:
// chunked" to the header. Body is closed after it is sent.
//
// Header values for Host, Content-Length, Transfer-Encoding,
// and Trailer are not used; these are derived from other Request fields.
// If the Header does not contain a User-Agent value, Write uses
// "Go-http-client/1.1".
func (r *Request) Write(w io.Writer) error {
return r.write(w, false, nil, nil)
}

View File

@@ -388,9 +388,8 @@ type dialClientConner interface {
// If HTTP/3 proxies are not supported, DialClientConn should return
// an error wrapping [errors.ErrUnsupported].
//
// The RoundTripper returned by DialClientConn may implement
// any of the following methods to support the [ClientConn]
// method of the same name:
// The RoundTripper returned by DialClientConn must also implement the
// following methods to support [ClientConn] methods of the same name:
// Close() error
// Err() error
// Reserve() error
@@ -411,6 +410,16 @@ type dialClientConner interface {
DialClientConn(ctx context.Context, address string, proxy *url.URL, internalStateHook func()) (RoundTripper, error)
}
type closeIdleConnectionser interface {
// CloseIdleConnections is called by Transport.CloseIdleConnections.
//
// The transport will close idle connections created with DialClientConn
// before calling this method. The HTTP/3 transport should not attempt to
// close idle connections, but may clean up shared resources such as UDP
// sockets if no connections remain.
CloseIdleConnections()
}
// h2Transport is the interface we expect to be able to call from
// net/http against an *http2.Transport that's either bundled into
// h2_bundle.go or supplied by the user via x/net/http2.
@@ -956,6 +965,9 @@ func (t *Transport) CloseIdleConnections() {
if t2 := t.h2transport; t2 != nil {
t2.CloseIdleConnections()
}
if cc, ok := t.h3transport.(closeIdleConnectionser); ok {
cc.CloseIdleConnections()
}
}
// prepareTransportCancel sets up state to convert Transport.CancelRequest into context cancelation.
@@ -3088,11 +3100,16 @@ func (pc *persistConn) closeLocked(err error) {
pc.t.decConnsPerHost(pc.cacheKey)
// Close HTTP/1 (pc.alt == nil) connection.
// HTTP/2 closes its connection itself.
// Close HTTP/3 connection if it implements io.Closer.
if pc.alt == nil {
if err != errCallerOwnsConn {
pc.conn.Close()
}
close(pc.closech)
} else {
if cc, ok := pc.alt.(io.Closer); ok {
cc.Close()
}
}
}
pc.mutateHeaderFunc = nil

View File

@@ -132,6 +132,10 @@ func (ip IP) IsLoopback() bool {
// IsPrivate reports whether ip is a private address, according to
// RFC 1918 (IPv4 addresses) and RFC 4193 (IPv6 addresses).
// That is, it reports whether ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7.
//
// IsPrivate does not describe a security property of addresses,
// and should not be used for access control.
func (ip IP) IsPrivate() bool {
if ip4 := ip.To4(); ip4 != nil {
// Following RFC 1918, Section 3. Private Address Space which says:

View File

@@ -637,6 +637,9 @@ func (ip Addr) IsGlobalUnicast() bool {
// (IPv4 addresses) and RFC 4193 (IPv6 addresses). That is, it reports whether
// ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the
// same as [net.IP.IsPrivate].
//
// IsPrivate does not describe a security property of addresses,
// and should not be used for access control.
func (ip Addr) IsPrivate() bool {
if ip.Is4In6() {
ip = ip.Unmap()

View File

@@ -12,6 +12,8 @@ import (
"syscall"
)
var testHookSupportsSendfile func() bool
// sendFile copies the contents of r to c using the sendfile
// system call to minimize copies.
//

View File

@@ -8,6 +8,8 @@ package net
import "io"
var testHookSupportsSendfile func() bool
func supportsSendfile() bool {
return false
}

View File

@@ -28,6 +28,16 @@ const (
newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
)
func hookSupportsSendfile(t *testing.T) {
if runtime.GOOS == "windows" {
origHook := testHookSupportsSendfile
testHookSupportsSendfile = func() bool { return true }
t.Cleanup(func() {
testHookSupportsSendfile = origHook
})
}
}
// expectSendfile runs f, and verifies that internal/poll.SendFile successfully handles
// a write to wantConn during f's execution.
//
@@ -35,6 +45,7 @@ const (
// expect a call to SendFile.
func expectSendfile(t *testing.T, wantConn Conn, f func()) {
t.Helper()
hookSupportsSendfile(t)
if !supportsSendfile() {
f()
return

View File

@@ -12,5 +12,8 @@ import "internal/syscall/windows"
// https://learn.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile
// https://golang.org/issue/73746
func supportsSendfile() bool {
if testHookSupportsSendfile != nil {
return testHookSupportsSendfile()
}
return windows.SupportUnlimitedTransmitFile()
}

View File

@@ -20,8 +20,6 @@ package cgo
#cgo netbsd LDFLAGS: -lpthread
#cgo openbsd LDFLAGS: -lpthread
#cgo aix LDFLAGS: -Wl,-berok
#cgo solaris LDFLAGS: -lxnet
#cgo solaris LDFLAGS: -lsocket
// Use -fno-stack-protector to avoid problems locating the
// proper support functions. See issues #52919, #54313, #58385.

View File

@@ -97,6 +97,9 @@ import (
// func main() {
// val := "hello Go"
// h := cgo.NewHandle(val)
// // In this example, unsafe.Pointer(&h) is valid because myprint
// // does not keep a copy of the pointer. If the C code keeps the
// // pointer after the call returns, use runtime.Pinner to pin it.
// C.myprint(unsafe.Pointer(&h))
// // Output: hello Go
// }

View File

@@ -71,6 +71,9 @@ func Pipe2(p []int, flags int) error {
return err
}
//go:cgo_ldflag "-lxnet"
//go:cgo_ldflag "-lsocket"
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = libsocket.accept4
func Accept4(fd int, flags int) (int, Sockaddr, error) {

View File

@@ -85,6 +85,28 @@ func TestTBHelperParallel(t *testing.T) {
}
}
// Issue 72794.
func TestHelperRange(t *testing.T) {
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
rangeHelperHelper(t)
return
}
t.Parallel()
cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestHelperRange$")
cmd = testenv.CleanCmdEnv(cmd)
cmd.Env = append(cmd.Env, "GO_WANT_HELPER_PROCESS=1")
out, _ := cmd.CombinedOutput()
want := `--- FAIL: TestHelperRange \([^)]+\)
helperfuncs_test.go:139: range
helperfuncs_test.go:139: range
`
if !regexp.MustCompile(want).Match(out) {
t.Errorf("got output:\n\n%s\nwant matching:\n\n%s", out, want)
}
}
func BenchmarkTBHelper(b *testing.B) {
f1 := func() {
b.Helper()

View File

@@ -122,3 +122,19 @@ func doPanic(t *testing.T, msg string) {
t.Helper()
panic(msg)
}
func rangeHelper(t *testing.T, msg string) {
t.Helper()
iter := func(yield func(int) bool) {
if yield(0) {
yield(1)
}
}
for range iter {
t.Error(msg)
}
}
func rangeHelperHelper(t *testing.T) {
rangeHelper(t, "range")
}

View File

@@ -816,8 +816,15 @@ func (c *common) frameSkip(skip int) runtime.Frame {
}
frames := runtime.CallersFrames(pc[:n])
var firstFrame, prevFrame, frame runtime.Frame
skipRange := false
for more := true; more; prevFrame = frame {
frame, more = frames.Next()
if skipRange {
// Skip the iterator function when a helper
// functions does a range over function.
skipRange = false
continue
}
if frame.Function == "runtime.gopanic" {
continue
}
@@ -861,7 +868,25 @@ func (c *common) frameSkip(skip int) runtime.Frame {
c.helperNames[pcToName(pc)] = struct{}{}
}
}
if _, ok := c.helperNames[frame.Function]; !ok {
fnName := frame.Function
// Ignore trailing -rangeN used for iterator functions.
const rangeSuffix = "-range"
if suffixIdx := strings.LastIndex(fnName, rangeSuffix); suffixIdx > 0 {
ok := true
for i := suffixIdx + len(rangeSuffix); i < len(fnName); i++ {
if fnName[i] < '0' || fnName[i] > '9' {
ok = false
break
}
}
if ok {
fnName = fnName[:suffixIdx]
skipRange = true
}
}
if _, ok := c.helperNames[fnName]; !ok {
// Found a frame that wasn't inside a helper function.
return frame
}