diff --git a/server/core/random_jkiss.c b/server/core/random_jkiss.c index bfafd8054..feb0aa19a 100644 --- a/server/core/random_jkiss.c +++ b/server/core/random_jkiss.c @@ -18,6 +18,9 @@ /** * @file random_jkiss.c - Random number generator for the MariaDB Corporation MaxScale + * + * See http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf for discussion of random + * number generators (RNGs). * * @verbatim * Revision History @@ -35,15 +38,22 @@ #include #include -/* Public domain code for JKISS RNG - Comments added */ +/* Public domain code for JKISS RNG - Comment header added */ + +/* If possible, the seed variables will be set from /dev/urandom but + * should that fail, these arbitrary numbers will be used as a last resort. + */ static unsigned int x = 123456789,y = 987654321,z = 43219876,c = 6543217; /* Seed variables */ static bool init = false; -static void random_init_jkiss(); +static SPINLOCK random_jkiss_spinlock = SPINLOCK_INIT; + +static unsigned int random_jkiss_devrand(void); +static void random_init_jkiss(void); /*** * - * Return a random number + * Return a pseudo-random number that satisfies major tests for random sequences * * @return uint Random number * @@ -52,9 +62,13 @@ unsigned int random_jkiss(void) { unsigned long long t; + unsigned int result; + spinlock_acquire(&random_jkiss_spinlock); if (!init) { + /* Must set init first because initialisation calls this function */ init = true; + spinlock_release(&random_jkiss_spinlock); random_init_jkiss(); } x = 314527869 * x + 1234567; @@ -64,7 +78,9 @@ random_jkiss(void) t = 4294584393ULL * z + c; c = t >> 32; z = t; - return x + y + z; + result = x + y + z; + spinlock_release(&random_jkiss_spinlock); + return result; } /* Own code adapted from http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf */ @@ -72,19 +88,21 @@ random_jkiss(void) /*** * * Obtain a seed random number from /dev/urandom if available. - * Otherwise use constant values * * @return uint Random number * */ static unsigned int -random_devrand() +random_jkiss_devrand(void) { int fn; unsigned int r; - fn = open("/dev/urandom", O_RDONLY); - if (fn == -1) return 0; - if (read(fn, &r, 4) != 4) return 0; + if ((fn = open("/dev/urandom", O_RDONLY)) == -1) return 0; + if (read(fn, &r, 4) != 4) + { + close(fn); + return 0; + } close(fn); return r; } @@ -96,13 +114,15 @@ random_devrand() * */ static void -random_init_jkiss() +random_init_jkiss(void) { int newrand, i; - if ((newrand = random_devrand()) != 0) x = newrand; - if ((newrand = random_devrand()) != 0) y = newrand; - if ((newrand = random_devrand()) != 0) z = newrand; - if ((newrand = random_devrand()) != 0) + if ((newrand = random_jkiss_devrand()) != 0) x = newrand; + if ((newrand = random_jkiss_devrand()) != 0) y = newrand; + if ((newrand = random_jkiss_devrand()) != 0) z = newrand; + if ((newrand = random_jkiss_devrand()) != 0) c = newrand % 698769068 + 1; /* Should be less than 698769069 */ + + /* "Warm up" our random number generator */ for (i = 0; i < 100; i++) random_jkiss(); }