#Core Random PRNG
An optionally-deterministic 128-bit pseudo-random number generator defined by a macro. It is a low-level building block for hash functions, test harnesses, and other internals that need an optionally repeatable, fast stream of bits.
For the high-level random module — fio_rand64, secure bytes, hashing, etc. — see ./002 random.h.
The implementation is in ./000 core.h.
#fio_cycle_counter
uint64_t fio_cycle_counter(void);Returns a hardware cycle counter when one is available, or 0 otherwise.
- On x86/x86_64 it reads
rdtsc. - On AArch64 it reads
cntvct_el0. - On other platforms it returns
0.
In non-deterministic mode, the PRNG uses this for timing-based jitter during reseeding.
#FIO_DEFINE_RANDOM128_FN
#define FIO_DEFINE_RANDOM128_FN(extern, name, reseed_log, seed_offset)Defines a named PRNG instance and its API. The most common deterministic form looks like:
FIO_DEFINE_RANDOM128_FN(static, my_rng, 0, 0x1234)Parameters:
extern— linkage prefix, e.g.staticorFIO_SFUNC.name— base name for all generated functions and internal state.reseed_log— automatic reseed interval,2^reseed_logcalls. Set to0for a fully deterministic stream.seed_offset— arbitrary offset added to the default seed constants.
#Non-Deterministic Mode
FIO_DEFINE_RANDOM128_FN(static, my_rng, 5, 0x1234)When reseed_log is non-zero (and less than 64), the generator calls name_reseed() automatically every 2^reseed_log calls, mixing in timing data and the cycle counter. This makes the stream non-deterministic, and improves entropy.
In this example, reseeding is set to 5, resulting in reseeding every 32 calls (collecting new entropy every 4,096 bytes).
#Generated API
For a definition FIO_DEFINE_RANDOM128_FN(static, my_rng, 0, 0) the following functions are generated:
#my_rng128
fio_u128 my_rng128(void);Returns 128 pseudo-random bits. The return type is fio_u128, so the result can also be read through .u64[0], .u64[1], .u8, etc.
#my_rng64
uint64_t my_rng64(void);Returns 64 pseudo-random bits. Each call consumes half of a 128-bit result; a new 128-bit value is generated only every other call.
#my_rng_bytes
void my_rng_bytes(void *dest, size_t len);Fills dest with len pseudo-random bytes. Does nothing if dest is NULL or len is zero.
#my_rng_reset
void my_rng_reset(void);Resets the generator to its initial seeded state.
#my_rng_reseed
void my_rng_reseed(void);Re-seeds the generator using CLOCK_MONOTONIC, address/bits of local state, and fio_cycle_counter(). Useful after fork() or when you want to de-correlate separate processes.
#my_rng_on_fork
void my_rng_on_fork(void *is_null);Calls my_rng_reseed(). Fork-handler helper that takes an ignored void * argument.
#Example
FIO_DEFINE_RANDOM128_FN(static, my_rng, 0, 0)
void roll_die(int n) {
my_rng_reset();
for (int i = 0; i < n; ++i) {
uint64_t r = my_rng64();
printf("roll %d: %llu\n", i, (unsigned long long)(r % 6 + 1));
}
}Because reseed_log is 0, the same seed always produces the same sequence.
#Determinism and fork safety
- Set
reseed_log = 0for deterministic, repeatable output. - Set
reseed_logto a practical value such as31for a non-deterministic stream that reseeds automatically. - After
fork(), callname_reseed()or register a wrapper that callsname_on_fork()withpthread_atfork()to avoid duplicated sequences in child processes.
#Testing
Test results for this generator are recorded in ./721 rand128 macro.md.
#See also
./002 random.h— high-level random/hashing module../001 vector math.md— thefio_u128return type../000 core.h— source of truth.