mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-23 06:45:19 +00:00
Add rand.init_as_system to allow for system-level based random number generation
This commit is contained in:
@@ -5,6 +5,7 @@ import "core:intrinsics"
|
||||
Rand :: struct {
|
||||
state: u64,
|
||||
inc: u64,
|
||||
is_system: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +30,16 @@ init :: proc(r: ^Rand, seed: u64) {
|
||||
_random(r)
|
||||
}
|
||||
|
||||
init_as_system :: proc(r: ^Rand) {
|
||||
if !#defined(_system_random) {
|
||||
panic(#procedure + " is not supported on this platform yet")
|
||||
}
|
||||
r.state = 0
|
||||
r.inc = 0
|
||||
r.is_system = true
|
||||
}
|
||||
|
||||
@(private)
|
||||
_random :: proc(r: ^Rand) -> u32 {
|
||||
r := r
|
||||
if r == nil {
|
||||
@@ -36,6 +47,12 @@ _random :: proc(r: ^Rand) -> u32 {
|
||||
// enforce the global random state if necessary with `nil`
|
||||
r = &global_rand
|
||||
}
|
||||
when #defined(_system_random) {
|
||||
if r.is_system {
|
||||
return _system_random()
|
||||
}
|
||||
}
|
||||
|
||||
old_state := r.state
|
||||
r.state = old_state * 6364136223846793005 + (r.inc|1)
|
||||
xor_shifted := u32(((old_state>>18) ~ old_state) >> 27)
|
||||
|
||||
27
core/math/rand/system_linux.odin
Normal file
27
core/math/rand/system_linux.odin
Normal file
@@ -0,0 +1,27 @@
|
||||
package rand
|
||||
|
||||
import "core:sys/unix"
|
||||
|
||||
_system_random :: proc() -> u32 {
|
||||
for {
|
||||
value: u32
|
||||
ret := unix.sys_getrandom(([^]u8)(&value), 4, 0)
|
||||
if ret < 0 {
|
||||
switch ret {
|
||||
case -4: // EINTR
|
||||
// Call interupted by a signal handler, just retry the request.
|
||||
continue
|
||||
case -38: // ENOSYS
|
||||
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
||||
// and does not support getrandom.
|
||||
panic("getrandom not available in kernel")
|
||||
case:
|
||||
// All other failures are things that should NEVER happen
|
||||
// unless the kernel interface changes (ie: the Linux
|
||||
// developers break userland).
|
||||
panic("getrandom failed")
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
12
core/math/rand/system_windows.odin
Normal file
12
core/math/rand/system_windows.odin
Normal file
@@ -0,0 +1,12 @@
|
||||
package rand
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
_system_random :: proc() -> u32 {
|
||||
value: u32
|
||||
status := win32.BCryptGenRandom(nil, ([^]u8)(&value), 4, win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
|
||||
if status < 0 {
|
||||
panic("BCryptGenRandom failed")
|
||||
}
|
||||
return value
|
||||
}
|
||||
Reference in New Issue
Block a user