diff --git a/cmdline/mingw.c b/cmdline/mingw.c index baf54662..32756bc1 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -163,13 +163,10 @@ void os_init(int opt) /* check for Wine presence */ is_wine = GetProcAddress(ntdll, "wine_get_version") != 0; - /* setup the standard random generator used as fallback */ - srand(GetTickCount()); - /* get pointer to RtlGenRandom, note that it was reported missing in some cases */ ptr_RtlGenRandom = (void*)GetProcAddress(dll_advapi32, "SystemFunction036"); - /* get pointer to RtlGenRandom, note that it was reported missing in some cases */ + /* get pointer to ptr_GetTickCount64 */ ptr_GetTickCount64 = (void*)GetProcAddress(kernel32, "GetTickCount64"); /* set the thread execution level to avoid sleep */ @@ -2239,21 +2236,9 @@ int randomize(void* void_ptr, size_t size) if (ptr_RtlGenRandom != 0 && ptr_RtlGenRandom(ptr, size) != 0) return 0; - /* try rand_s */ - for (i = 0; i < size; ++i) { - unsigned v = 0; - - if (rand_s(&v) != 0) - break; - - ptr[i] = v; - } - if (i == size) - return 0; - /* fallback to standard rand */ for (i = 0; i < size; ++i) - ptr[i] = rand(); + ptr[i] = random_u8(); return 0; } diff --git a/cmdline/portable.h b/cmdline/portable.h index ab2d36c0..12608a4a 100644 --- a/cmdline/portable.h +++ b/cmdline/portable.h @@ -46,11 +46,6 @@ */ #define _WIN32_WINNT 0x600 -/** - * Enable the rand_s() function.l - */ -#define _CRT_RAND_S - #include #endif diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index 1ed26d4b..e16619bf 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -1360,6 +1360,7 @@ int snapraid_main(int argc, char* argv[]) os_init(opt.force_scan_winfind); raid_init(); crc32c_init(); + random_reseed(); if (speedtest != 0) { speed(period); diff --git a/cmdline/support.c b/cmdline/support.c index 8dd1603b..a0514929 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -28,6 +28,7 @@ #if HAVE_THREAD static thread_mutex_t msg_lock; static thread_mutex_t memory_lock; +static thread_mutex_t random_lock; #endif void lock_msg(void) @@ -58,12 +59,28 @@ void unlock_memory(void) #endif } +void lock_random(void) +{ +#if HAVE_THREAD + thread_mutex_lock(&random_lock); +#endif +} + +void unlock_random(void) +{ +#if HAVE_THREAD + thread_mutex_unlock(&random_lock); +#endif +} + + void lock_init(void) { #if HAVE_THREAD /* initialize the locks as first operation as log_fatal depends on them */ thread_mutex_init(&msg_lock); thread_mutex_init(&memory_lock); + thread_mutex_init(&random_lock); #endif } @@ -72,9 +89,50 @@ void lock_done(void) #if HAVE_THREAD thread_mutex_destroy(&msg_lock); thread_mutex_destroy(&memory_lock); + thread_mutex_destroy(&random_lock); #endif } +/****************************************************************************/ +/* random */ + +static uint64_t random_state = 1; + +void random_reseed(void) +{ + random_state = tick(); +} + +unsigned char random_u8(void) +{ + return random_u64() & 0xFF; +} + +/* + * SplitMix64 + * + * - Zero-safe: Any 64-bit seed is valid (even 0). + * - Full period: Guaranteed to visit every 2^64 value. + * - Logic: Uses a Weyl sequence + MurmurHash3-style finalizer. + * + * See: https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64 + */ +uint64_t random_u64(void) +{ + uint64_t z; + + lock_random(); + + z = random_state += 0x9E3779B97F4A7C15ULL; + + unlock_random(); + + z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL; + z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL; + + return z ^ (z >> 31); +} + /****************************************************************************/ /* print */ diff --git a/cmdline/support.h b/cmdline/support.h index cfd7fa22..2372221b 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -52,6 +52,24 @@ void unlock_msg(void); void lock_memory(void); void unlock_memory(void); +/****************************************************************************/ +/* random */ + +/** + * Reseed the random pseudo random number generator + */ +void random_reseed(void); + +/** + * Return a pseudo random number of 8 bits + */ +unsigned char random_u8(void); + +/** + * Return a pseudo random number of 64 bits + */ +uint64_t random_u64(void); + /****************************************************************************/ /* log */ diff --git a/cmdline/unix.c b/cmdline/unix.c index 6a49433a..f9204925 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -1622,16 +1622,6 @@ static int devup(dev_t device, const char* name) void* buf; uint64_t size; uint64_t offset; - uint64_t pseudo_random; - - /* get a pseudo random number */ - ret = randomize(&pseudo_random, sizeof(pseudo_random)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Failed to retrieve random values.\n"); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } if (devresolve(device, file, sizeof(file)) != 0) { /* LCOV_EXCL_START */ @@ -1669,7 +1659,7 @@ static int devup(dev_t device, const char* name) } /* select a random offset */ - offset = (pseudo_random % (size / 4096)) * 4096; + offset = (random_u64() % (size / 4096)) * 4096; #if HAVE_POSIX_FADVISE /* clear cache */