diff --git a/base/Base.jl b/base/Base.jl index a3fe44a2add86..2deeb6978125c 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -292,9 +292,6 @@ include("process.jl") include("ttyhascolor.jl") include("secretbuffer.jl") -# RandomDevice support -include("randomdevice.jl") - # core math functions include("floatfuncs.jl") include("math.jl") diff --git a/base/libc.jl b/base/libc.jl index 38b62847eaeb4..8cce4ce2a259b 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -400,7 +400,7 @@ rand(::Type{Float64}) = rand(UInt32) * 2.0^-32 Interface to the C `srand(seed)` function. """ -srand(seed=Base._make_uint_seed()) = ccall(:srand, Cvoid, (Cuint,), seed) +srand(seed=floor(Int, time()) % Cuint) = ccall(:srand, Cvoid, (Cuint,), seed) struct Cpasswd username::Cstring diff --git a/base/randomdevice.jl b/base/randomdevice.jl deleted file mode 100644 index d63ff7edc1647..0000000000000 --- a/base/randomdevice.jl +++ /dev/null @@ -1,77 +0,0 @@ -# This file is a part of Julia. License is MIT: https://julialang.org/license - -# This file contains the minimal support of RandomDevice for Base's own usage. -# The actual RandomDevice type that makes use of this infrastructure is defined -# in the Random stdlib. - -module DevRandomState - if !Sys.iswindows() - mutable struct FileRef - @atomic file::Union{IOStream, Nothing} - end - const DEV_RANDOM = FileRef(nothing) - const DEV_URANDOM = FileRef(nothing) - end - function __init__() - if !Sys.iswindows() - @atomic DEV_RANDOM.file = nothing - @atomic DEV_URANDOM.file = nothing - end - end -end - -if Sys.iswindows() - function RtlGenRandom!(A::Union{Array, Ref}) - Base.windowserror("SystemFunction036 (RtlGenRandom)", 0 == ccall( - (:SystemFunction036, :Advapi32), stdcall, UInt8, (Ptr{Cvoid}, UInt32), - A, sizeof(A))) - end - - # Manually implemented to work without the Random machinery - function _rand_uint() - r = Ref{Cuint}() - RtlGenRandom!(r) - return r[] - end -else # !windows - function _get_dev_random_fd(unlimited::Bool) - ref = unlimited ? DevRandomState.DEV_URANDOM : DevRandomState.DEV_RANDOM - fd = ref.file - if fd === nothing - fd = open(unlimited ? "/dev/urandom" : "/dev/random") - old, ok = @atomicreplace ref.file nothing => fd - if !ok - close(fd) - fd = old::IOStream - end - end - return fd - end - - # Manually implemented to work without the Random machinery - function _rand_uint() - return read(_get_dev_random_fd(true), Cuint) - end -end # os-test - -function _ad_hoc_entropy() - println(stderr, - "Entropy pool not available to seed RNG; using ad-hoc entropy sources.") - seed = reinterpret(UInt64, time()) - seed = hash(seed, getpid() % UInt) - try - seed = hash(seed, parse(UInt64, - read(pipeline(`ifconfig`, `sha1sum`), String)[1:40], - base = 16) % UInt) - catch - end - return seed -end - -function _make_uint_seed() - try - _rand_uint() - catch - return _ad_hoc_entropy() % Cuint - end -end \ No newline at end of file diff --git a/stdlib/Random/src/RNGs.jl b/stdlib/Random/src/RNGs.jl index a50f633e68a9c..13e5a8c778b16 100644 --- a/stdlib/Random/src/RNGs.jl +++ b/stdlib/Random/src/RNGs.jl @@ -23,20 +23,42 @@ else # !windows RandomDevice(; unlimited::Bool=true) = new(unlimited) end - getfile(rd::RandomDevice) = Base._get_dev_random_fd(rd.unlimited) - rand(rd::RandomDevice, sp::SamplerBoolBitInteger) = read(getfile(rd), sp[]) rand(rd::RandomDevice, ::SamplerType{Bool}) = read(getfile(rd), UInt8) % Bool + mutable struct FileRef + @atomic file::Union{IOStream, Nothing} + end + + const DEV_RANDOM = FileRef(nothing) + const DEV_URANDOM = FileRef(nothing) + + function getfile(rd::RandomDevice) + ref = rd.unlimited ? DEV_URANDOM : DEV_RANDOM + fd = ref.file + if fd === nothing + fd = open(rd.unlimited ? "/dev/urandom" : "/dev/random") + old, ok = @atomicreplace ref.file nothing => fd + if !ok + close(fd) + fd = old::IOStream + end + end + return fd + end + show(io::IO, rd::RandomDevice) = print(io, RandomDevice, rd.unlimited ? "()" : "(unlimited=false)") + end # os-test # NOTE: this can't be put within the if-else block above for T in (Bool, BitInteger_types...) if Sys.iswindows() @eval function rand!(rd::RandomDevice, A::Array{$T}, ::SamplerType{$T}) - Base.RtlGenRandom!(A) + Base.windowserror("SystemFunction036 (RtlGenRandom)", 0 == ccall( + (:SystemFunction036, :Advapi32), stdcall, UInt8, (Ptr{Cvoid}, UInt32), + A, sizeof(A))) A end else @@ -310,7 +332,14 @@ function make_seed() catch println(stderr, "Entropy pool not available to seed RNG; using ad-hoc entropy sources.") - Base._ad_hoc_entropy_source() + seed = reinterpret(UInt64, time()) + seed = hash(seed, getpid() % UInt) + try + seed = hash(seed, parse(UInt64, + read(pipeline(`ifconfig`, `sha1sum`), String)[1:40], + base = 16) % UInt) + catch + end return make_seed(seed) end end @@ -399,6 +428,10 @@ for T in BitInteger_types end function __init__() + @static if !Sys.iswindows() + @atomic DEV_RANDOM.file = nothing + @atomic DEV_URANDOM.file = nothing + end seed!(GLOBAL_RNG) end