aboutsummaryrefslogtreecommitdiff
path: root/core/math/rand
diff options
context:
space:
mode:
authorYawning Angel <yawning@schwanenlied.me>2024-04-21 21:16:50 +0900
committerYawning Angel <yawning@schwanenlied.me>2024-04-23 11:47:43 +0900
commite2fa9be7e2c02ad950e4f3205f5e67c9ebd3a70c (patch)
treefd5df47d5968012bb4aaaeba57f3cce5f79085fb /core/math/rand
parenta6eb64df6cd136639d1234e5a157ad280a1a32a8 (diff)
core/math/rand: Use `core:crypto` for the system RNG
This removes some code duplication and expands support for the system RNG to all targets that `core:crypto` supports.
Diffstat (limited to 'core/math/rand')
-rw-r--r--core/math/rand/rand.odin39
-rw-r--r--core/math/rand/system_darwin.odin22
-rw-r--r--core/math/rand/system_js.odin14
-rw-r--r--core/math/rand/system_linux.odin29
-rw-r--r--core/math/rand/system_windows.odin13
5 files changed, 21 insertions, 96 deletions
diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin
index d6a20bd1e..664d6abc9 100644
--- a/core/math/rand/rand.odin
+++ b/core/math/rand/rand.odin
@@ -5,6 +5,7 @@ Package core:math/rand implements various random number generators
package rand
import "base:intrinsics"
+import "core:crypto"
import "core:math"
import "core:mem"
@@ -104,27 +105,30 @@ init :: proc(r: ^Rand, seed: u64) {
}
/*
-Initialises a random number generator to use the system random number generator.
-The system random number generator is platform specific.
-On `linux` refer to the `getrandom` syscall.
-On `darwin` refer to `getentropy`.
-On `windows` refer to `BCryptGenRandom`.
-
-All other platforms are not supported
+Initialises a random number generator to use the system random number generator.
+The system random number generator is platform specific, and not supported
+on all targets.
Inputs:
- r: The random number generator to use the system random number generator
-WARNING: Panics if the system is not either `windows`, `darwin` or `linux`
+WARNING: Panics if the system random number generator is not supported.
+Support can be determined via the `core:crypto.HAS_RAND_BYTES` constant.
Example:
+ import "core:crypto"
import "core:math/rand"
import "core:fmt"
init_as_system_example :: proc() {
my_rand: rand.Rand
- rand.init_as_system(&my_rand)
- fmt.println(rand.uint64(&my_rand))
+ switch crypto.HAS_RAND_BYTES {
+ case true:
+ rand.init_as_system(&my_rand)
+ fmt.println(rand.uint64(&my_rand))
+ case false:
+ fmt.println("system random not supported!")
+ }
}
Possible Output:
@@ -133,7 +137,7 @@ Possible Output:
*/
init_as_system :: proc(r: ^Rand) {
- if !#defined(_system_random) {
+ if !crypto.HAS_RAND_BYTES {
panic(#procedure + " is not supported on this platform yet")
}
r.state = 0
@@ -144,15 +148,14 @@ init_as_system :: proc(r: ^Rand) {
@(private)
_random_u64 :: proc(r: ^Rand) -> u64 {
r := r
- if r == nil {
+ switch {
+ case r == nil:
r = &global_rand
+ case r.is_system:
+ value: u64
+ crypto.rand_bytes((cast([^]u8)&value)[:size_of(u64)])
+ return value
}
- when #defined(_system_random) {
- if r.is_system {
- return _system_random()
- }
- }
-
old_state := r.state
r.state = old_state * 6364136223846793005 + (r.inc|1)
diff --git a/core/math/rand/system_darwin.odin b/core/math/rand/system_darwin.odin
deleted file mode 100644
index 756f7fcae..000000000
--- a/core/math/rand/system_darwin.odin
+++ /dev/null
@@ -1,22 +0,0 @@
-package rand
-
-import "core:sys/darwin"
-
-@(require_results)
-_system_random :: proc() -> u64 {
- for {
- value: u64
- ret := darwin.syscall_getentropy(([^]u8)(&value), size_of(value))
- if ret < 0 {
- switch ret {
- case -4: // EINTR
- continue
- case -78: // ENOSYS
- panic("getentropy not available in kernel")
- case:
- panic("getentropy failed")
- }
- }
- return value
- }
-} \ No newline at end of file
diff --git a/core/math/rand/system_js.odin b/core/math/rand/system_js.odin
deleted file mode 100644
index b9b71c4a6..000000000
--- a/core/math/rand/system_js.odin
+++ /dev/null
@@ -1,14 +0,0 @@
-package rand
-
-foreign import "odin_env"
-foreign odin_env {
- @(link_name = "rand_bytes")
- env_rand_bytes :: proc "contextless" (buf: []byte) ---
-}
-
-@(require_results)
-_system_random :: proc() -> u64 {
- buf: [8]u8
- env_rand_bytes(buf[:])
- return transmute(u64)buf
-}
diff --git a/core/math/rand/system_linux.odin b/core/math/rand/system_linux.odin
deleted file mode 100644
index 42c9f86fa..000000000
--- a/core/math/rand/system_linux.odin
+++ /dev/null
@@ -1,29 +0,0 @@
-package rand
-
-import "core:sys/linux"
-
-@(require_results)
-_system_random :: proc() -> u64 {
- for {
- value: u64
- value_buf := (cast([^]u8)&value)[:size_of(u64)]
- _, errno := linux.getrandom(value_buf, {})
- #partial switch errno {
- case .NONE:
- // Do nothing
- case .EINTR:
- // Call interupted by a signal handler, just retry the request.
- continue
- case .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
- }
-} \ No newline at end of file
diff --git a/core/math/rand/system_windows.odin b/core/math/rand/system_windows.odin
deleted file mode 100644
index c6d68816d..000000000
--- a/core/math/rand/system_windows.odin
+++ /dev/null
@@ -1,13 +0,0 @@
-package rand
-
-import win32 "core:sys/windows"
-
-@(require_results)
-_system_random :: proc() -> u64 {
- value: u64
- status := win32.BCryptGenRandom(nil, ([^]u8)(&value), size_of(value), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
- if status < 0 {
- panic("BCryptGenRandom failed")
- }
- return value
-} \ No newline at end of file