Source File
rand.go
Belonging Package
runtime
// Copyright 2023 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.// Random number generationpackage runtimeimport (_ // for go:linkname)// OS-specific startup can set startupRand if the OS passes// random data to the process at startup time.// For example Linux passes 16 bytes in the auxv vector.var startupRand []byte// globalRand holds the global random state.// It is only used at startup and for creating new m's.// Otherwise the per-m random state should be used// by calling goodrand.var globalRand struct {lock mutexseed [32]bytestate chacha8rand.Stateinit bool}var readRandomFailed bool// randinit initializes the global random state.// It must be called before any use of grand.func () {lock(&globalRand.lock)if globalRand.init {fatal("randinit twice")}:= &globalRand.seedif startupRand != nil {for , := range startupRand {[%len()] ^=}clear(startupRand)startupRand = nil} else {if readRandom([:]) != len() {// readRandom should never fail, but if it does we'd rather// not make Go binaries completely unusable, so make up// some random data based on the current time.readRandomFailed = truereadTimeRandom([:])}}globalRand.state.Init(*)clear([:])globalRand.init = trueunlock(&globalRand.lock)}// readTimeRandom stretches any entropy in the current time// into entropy the length of r and XORs it into r.// This is a fallback for when readRandom does not read// the full requested amount.// Whatever entropy r already contained is preserved.func ( []byte) {// Inspired by wyrand.// An earlier version of this code used getg().m.procid as well,// but note that this is called so early in startup that procid// is not initialized yet.:= uint64(nanotime())for len() > 0 {^= 0xa0761d6478bd642f*= 0xe7037ed1a0b428db:= 8if len() < 8 {= len()}for := 0; < ; ++ {[] ^= byte( >> (8 * ))}= [:]= >>32 | <<32}}// bootstrapRand returns a random uint64 from the global random generator.func () uint64 {lock(&globalRand.lock)if !globalRand.init {fatal("randinit missed")}for {if , := globalRand.state.Next(); {unlock(&globalRand.lock)return}globalRand.state.Refill()}}// bootstrapRandReseed reseeds the bootstrap random number generator,// clearing from memory any trace of previously returned random numbers.func () {lock(&globalRand.lock)if !globalRand.init {fatal("randinit missed")}globalRand.state.Reseed()unlock(&globalRand.lock)}// rand32 is uint32(rand()), called from compiler-generated code.////go:nosplitfunc () uint32 {return uint32(rand())}// rand returns a random uint64 from the per-m chacha8 state.// Do not change signature: used via linkname from other packages.////go:nosplit//go:linkname randfunc () uint64 {// Note: We avoid acquirem here so that in the fast path// there is just a getg, an inlined c.Next, and a return.// The performance difference on a 16-core AMD is// 3.7ns/call this way versus 4.3ns/call with acquirem (+16%).:= getg().m:= &.chacha8for {// Note: c.Next is marked nosplit,// so we don't need to use mp.locks// on the fast path, which is that the// first attempt succeeds., := .Next()if {return}.locks++ // hold m even though c.Refill may do stack split checks.Refill().locks--}}// mrandinit initializes the random state of an m.func ( *m) {var [4]uint64for := range {[] = bootstrapRand()}bootstrapRandReseed() // erase key we just extracted.chacha8.Init64().cheaprand = rand()}// randn is like rand() % n but faster.// Do not change signature: used via linkname from other packages.////go:nosplit//go:linkname randnfunc ( uint32) uint32 {// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/return uint32((uint64(uint32(rand())) * uint64()) >> 32)}// cheaprand is a non-cryptographic-quality 32-bit random generator// suitable for calling at very high frequency (such as during scheduling decisions)// and at sensitive moments in the runtime (such as during stack unwinding).// it is "cheap" in the sense of both expense and quality.//// cheaprand must not be exported to other packages:// the rule is that other packages using runtime-provided// randomness must always use rand.//// cheaprand should be an internal detail,// but widely used packages access it using linkname.// Notable members of the hall of shame include:// - github.com/bytedance/gopkg//// Do not remove or change the type signature.// See go.dev/issue/67401.////go:linkname cheaprand//go:nosplitfunc () uint32 {:= getg().m// Implement wyrand: https://github.com/wangyi-fudan/wyhash// Only the platform that math.Mul64 can be lowered// by the compiler should be in this list.if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|goarch.IsS390x|goarch.IsRiscv64|goarch.IsLoong64 == 1 {.cheaprand += 0xa0761d6478bd642f, := math.Mul64(.cheaprand, .cheaprand^0xe7037ed1a0b428db)return uint32( ^ )}// Implement xorshift64+: 2 32-bit xorshift sequences added together.// Shift triplet [17,7,16] was calculated as indicated in Marsaglia's// Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf// This generator passes the SmallCrush suite, part of TestU01 framework:// http://simul.iro.umontreal.ca/testu01/tu01.html:= (*[2]uint32)(unsafe.Pointer(&.cheaprand)), := [0], [1]^= << 17= ^ ^ >>7 ^ >>16[0], [1] = ,return +}// cheaprand64 is a non-cryptographic-quality 63-bit random generator// suitable for calling at very high frequency (such as during sampling decisions).// it is "cheap" in the sense of both expense and quality.//// cheaprand64 must not be exported to other packages:// the rule is that other packages using runtime-provided// randomness must always use rand.//// cheaprand64 should be an internal detail,// but widely used packages access it using linkname.// Notable members of the hall of shame include:// - github.com/zhangyunhao116/fastrand//// Do not remove or change the type signature.// See go.dev/issue/67401.////go:linkname cheaprand64//go:nosplitfunc () int64 {return int64(cheaprand())<<31 ^ int64(cheaprand())}// cheaprandn is like cheaprand() % n but faster.//// cheaprandn must not be exported to other packages:// the rule is that other packages using runtime-provided// randomness must always use randn.//// cheaprandn should be an internal detail,// but widely used packages access it using linkname.// Notable members of the hall of shame include:// - github.com/phuslu/log//// Do not remove or change the type signature.// See go.dev/issue/67401.////go:linkname cheaprandn//go:nosplitfunc ( uint32) uint32 {// See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/return uint32((uint64(cheaprand()) * uint64()) >> 32)}// Too much legacy code has go:linkname references// to runtime.fastrand and friends, so keep these around for now.// Code should migrate to math/rand/v2.Uint64,// which is just as fast, but that's only available in Go 1.22+.// It would be reasonable to remove these in Go 1.24.// Do not call these from package runtime.//go:linkname legacy_fastrand runtime.fastrandfunc () uint32 {return uint32(rand())}//go:linkname legacy_fastrandn runtime.fastrandnfunc ( uint32) uint32 {return randn()}//go:linkname legacy_fastrand64 runtime.fastrand64func () uint64 {return rand()}
![]() |
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |