Skip to content

Commit dca2ef2

Browse files
rscgopherbot
authored andcommitted
runtime: put runtime.fastrand back temporarily
Callers should be using math/rand/v2.Uint64 instead, but there are lots of linkname references to runtime.fastrand in public code. If we break it all now, that will require people to use //go:build tags to use rand/v2.Uint64 with Go 1.22 and keep using the linkname for earlier versions. Instead, leave the linkname working and then we can remove it in Go 1.24, at which point everyone should be able to use math/rand/v2.Uint64 unconditionally. Change-Id: I7287ca4f67c270b009562313661cc28a4c2219a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/548235 Reviewed-by: Michael Pratt <[email protected]> Reviewed-by: David Chase <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Auto-Submit: Russ Cox <[email protected]>
1 parent e1c0349 commit dca2ef2

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

src/runtime/rand.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,25 @@ func cheaprandn(n uint32) uint32 {
223223
// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
224224
return uint32((uint64(cheaprand()) * uint64(n)) >> 32)
225225
}
226+
227+
// Too much legacy code has go:linkname references
228+
// to runtime.fastrand and friends, so keep these around for now.
229+
// Code should migrate to math/rand/v2.Uint64,
230+
// which is just as fast, but that's only available in Go 1.22+.
231+
// It would be reasonable to remove these in Go 1.24.
232+
// Do not call these from package runtime.
233+
234+
//go:linkname legacy_fastrand runtime.fastrand
235+
func legacy_fastrand() uint32 {
236+
return uint32(rand())
237+
}
238+
239+
//go:linkname legacy_fastrandn runtime.fastrandn
240+
func legacy_fastrandn(n uint32) uint32 {
241+
return randn(n)
242+
}
243+
244+
//go:linkname legacy_fastrand64 runtime.fastrand64
245+
func legacy_fastrand64() uint64 {
246+
return rand()
247+
}

src/runtime/rand_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
. "runtime"
99
"strconv"
1010
"testing"
11+
_ "unsafe" // for go:linkname
1112
)
1213

1314
func TestReadRandom(t *testing.T) {
@@ -62,3 +63,35 @@ func BenchmarkFastrandn(b *testing.B) {
6263
})
6364
}
6465
}
66+
67+
//go:linkname fastrand runtime.fastrand
68+
func fastrand() uint32
69+
70+
//go:linkname fastrandn runtime.fastrandn
71+
func fastrandn(uint32) uint32
72+
73+
//go:linkname fastrand64 runtime.fastrand64
74+
func fastrand64() uint64
75+
76+
func TestLegacyFastrand(t *testing.T) {
77+
// Testing mainly that the calls work at all,
78+
// but check that all three don't return the same number (1 in 2^64 chance)
79+
{
80+
x, y, z := fastrand(), fastrand(), fastrand()
81+
if x == y && y == z {
82+
t.Fatalf("fastrand three times = %#x, %#x, %#x, want different numbers", x, y, z)
83+
}
84+
}
85+
{
86+
x, y, z := fastrandn(1e9), fastrandn(1e9), fastrandn(1e9)
87+
if x == y && y == z {
88+
t.Fatalf("fastrandn three times = %#x, %#x, %#x, want different numbers", x, y, z)
89+
}
90+
}
91+
{
92+
x, y, z := fastrand64(), fastrand64(), fastrand64()
93+
if x == y && y == z {
94+
t.Fatalf("fastrand64 three times = %#x, %#x, %#x, want different numbers", x, y, z)
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)