From 01d245ef4392152dbdc78a6ba4dfa0a6e8b08e6f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 11 Jun 2012 11:47:59 +0200 Subject: random_seed: Rewrite the generic clock() based seed code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new code is faster and reuses the previous state in case of multiple calls. The previous code could easily end up in near-infinite loops, if the difference between two clock() calls never was larger than 1. This makes fate-parseutils finish in finite time when run in wine, if CryptGenRandom isn't available (which e.g. isn't available if targeting Windows RT/metro). Patch originally by Michael Niedermayer but with some modifications by Martin Storsjö. Signed-off-by: Martin Storsjö --- libavutil/random_seed.c | 51 +++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 21 deletions(-) (limited to 'libavutil/random_seed.c') diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c index 4680081b10..26884cbcd6 100644 --- a/libavutil/random_seed.c +++ b/libavutil/random_seed.c @@ -31,8 +31,11 @@ #include #include #include "internal.h" +#include "intreadwrite.h" +#include "mem.h" #include "timer.h" #include "random_seed.h" +#include "sha.h" static int read_random(uint32_t *dst, const char *file) { @@ -53,34 +56,40 @@ static int read_random(uint32_t *dst, const char *file) static uint32_t get_generic_seed(void) { + struct AVSHA *sha = av_sha_alloc(); clock_t last_t = 0; - int bits = 0; - uint64_t random = 0; - unsigned i; - float s = 0.000000000001; + static uint64_t i = 0; + static uint32_t buffer[512] = { 0 }; + unsigned char digest[20]; + uint64_t last_i = i; - for (i = 0; bits < 64; i++) { + for (;;) { clock_t t = clock(); - if (last_t && fabs(t - last_t) > s || t == (clock_t) -1) { - if (i < 10000 && s < (1 << 24)) { - s += s; - i = t = 0; - } else { - random = 2 * random + (i & 1); - bits++; - } + + if (last_t == t) { + buffer[i & 511]++; + } else { + buffer[++i & 511] += (t - last_t) % 3294638521U; + if (last_i && i - last_i > 4 || i - last_i > 64) + break; } last_t = t; } -#ifdef AV_READ_TIME - random ^= AV_READ_TIME(); -#else - random ^= clock(); -#endif - random += random >> 32; - - return random; + if (!sha) { + uint32_t seed = 0; + int j; + // Unable to allocate an sha context, just xor the buffer together + // to create something hopefully unique. + for (j = 0; j < 512; j++) + seed ^= buffer[j]; + return seed; + } + av_sha_init(sha, 160); + av_sha_update(sha, (const uint8_t *) buffer, sizeof(buffer)); + av_sha_final(sha, digest); + av_free(sha); + return AV_RB32(digest) + AV_RB32(digest + 16); } uint32_t av_get_random_seed(void) -- cgit v1.2.1