diff --git a/base/runtime/core.odin b/base/runtime/core.odin index a4a433d94..550daed3b 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -400,6 +400,7 @@ Logger :: struct { Random_Generator_Mode :: enum { Read, + Reset, Query_Info, } @@ -407,6 +408,7 @@ Random_Generator_Query_Info_Flag :: enum u32 { Cryptographic, Uniform, External_Entropy, + Resettable, } Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32] diff --git a/base/runtime/random_generator.odin b/base/runtime/random_generator.odin index 7746f1429..43d7ffd0c 100644 --- a/base/runtime/random_generator.odin +++ b/base/runtime/random_generator.odin @@ -29,7 +29,6 @@ random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Gener } -@(private="file") Default_Random_State :: struct { state: u64, inc: u64, @@ -48,18 +47,24 @@ default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, @(thread_local) global_rand_seed: Default_Random_State + init :: proc "contextless" (r: ^Default_Random_State, seed: u64) { + seed := seed + if seed == 0 { + seed = u64(intrinsics.read_cycle_counter()) + } + r.state = 0 + r.inc = (seed << 1) | 1 + _ = read_u64(r) + r.state += seed + _ = read_u64(r) + } + + r := &global_rand_seed + switch mode { case .Read: - r := &global_rand_seed - - if r.state == 0 && - r.inc == 0 { - seed := u64(intrinsics.read_cycle_counter()) - r.state = 0 - r.inc = (seed << 1) | 1 - _ = read_u64(r) - r.state += seed - _ = read_u64(r) + if r.state == 0 && r.inc == 0 { + init(r, 0) } pos := i8(0) @@ -73,13 +78,18 @@ default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, val >>= 8 pos -= 1 } - return + + case .Reset: + seed: u64 + mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p))) + init(r, seed) + case .Query_Info: if len(p) != size_of(Random_Generator_Query_Info) { return } info := (^Random_Generator_Query_Info)(raw_data(p)) - info^ += {.Uniform} + info^ += {.Uniform, .Resettable} } } diff --git a/core/crypto/crypto.odin b/core/crypto/crypto.odin index 99835e66f..d995ecf7d 100644 --- a/core/crypto/crypto.odin +++ b/core/crypto/crypto.odin @@ -67,6 +67,8 @@ to_random_generator :: proc() -> runtime.Random_Generator { switch mode { case .Read: rand_bytes(p) + case .Reset: + // do nothing case .Query_Info: if len(p) != size_of(runtime.Random_Generator_Query_Info) { return diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 552af6b8d..3f85277e8 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -23,6 +23,16 @@ to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator { switch mode { case .Read: _ = read(p, r) + + case .Reset: + if r.is_system { + return + } + seed: u64 + runtime.mem_copy_non_overlapping(&seed, raw_data(p), min(size_of(seed), len(p))) + init(r, seed) + + case .Query_Info: if len(p) != size_of(runtime.Random_Generator_Query_Info) { return @@ -31,6 +41,8 @@ to_random_generator :: proc(r: ^Rand) -> runtime.Random_Generator { info^ += {.Uniform} if r.is_system { info^ += {.External_Entropy} + } else { + info^ += {.Resettable} } } },