summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2015-06-02 15:05:54 +1000
committerAlex Gorrod <alexander.gorrod@mongodb.com>2015-06-02 15:05:54 +1000
commit42db5bae706130666452915fd204d60101d24950 (patch)
tree72ba3960d0eedb2cf291b02385cf4b1725bc62ba
parentb342030efe3ce392ec36577cd732630821f02dd0 (diff)
parent7bece7ab57f5d957fb9df318e4492937ff92108b (diff)
downloadmongo-42db5bae706130666452915fd204d60101d24950.tar.gz
Merge pull request #2008 from wiredtiger/rand-8B
Avoid potential races in the PRNG. Found by inspection - no evidence there is a problem.
-rw-r--r--bench/wtperf/wtperf.c18
-rw-r--r--bench/wtperf/wtperf.h2
-rw-r--r--dist/s_string.ok1
-rw-r--r--src/btree/row_srch.c4
-rw-r--r--src/conn/conn_api.c2
-rw-r--r--src/include/btree.i2
-rw-r--r--src/include/extern.h4
-rw-r--r--src/include/session.h4
-rw-r--r--src/log/log_slot.c2
-rw-r--r--src/lsm/lsm_work_unit.c2
-rw-r--r--src/session/session_api.c2
-rw-r--r--src/support/rand.c67
-rw-r--r--src/txn/txn_ckpt.c2
-rw-r--r--test/checkpoint/workers.c6
-rw-r--r--test/fops/fops.c12
-rw-r--r--test/format/format.h14
-rw-r--r--test/format/ops.c40
-rw-r--r--test/format/t.c2
-rw-r--r--test/format/util.c12
-rw-r--r--test/suite/suite_random.py24
-rw-r--r--test/thread/rw.c10
21 files changed, 127 insertions, 105 deletions
diff --git a/bench/wtperf/wtperf.c b/bench/wtperf/wtperf.c
index ca2c37f5c72..1c9ce963c9a 100644
--- a/bench/wtperf/wtperf.c
+++ b/bench/wtperf/wtperf.c
@@ -120,13 +120,13 @@ randomize_value(CONFIG_THREAD *thread, char *value_buf)
* randomly chosen byte (other than the trailing NUL).
* Make sure we don't write a NUL: keep the value the same length.
*/
- i = __wt_random(thread->rnd) % (thread->cfg->value_sz - 1);
+ i = __wt_random(&thread->rnd) % (thread->cfg->value_sz - 1);
while (value_buf[i] == '\0' && i > 0)
--i;
if (i > 0) {
vb = (uint8_t *)value_buf;
- vb[0] = (__wt_random(thread->rnd) % 255) + 1;
- vb[i] = (__wt_random(thread->rnd) % 255) + 1;
+ vb[0] = (__wt_random(&thread->rnd) % 255) + 1;
+ vb[i] = (__wt_random(&thread->rnd) % 255) + 1;
}
}
@@ -2216,13 +2216,11 @@ start_threads(CONFIG *cfg,
* new RNG state further along in the sequence.
*/
if (i == 0)
- __wt_random_init(thread->rnd);
- else {
- thread->rnd[0] = (thread - 1)->rnd[0];
- thread->rnd[1] = (thread - 1)->rnd[1];
- }
+ __wt_random_init(&thread->rnd);
+ else
+ thread->rnd = (thread - 1)->rnd;
for (j = 0; j < 1000; ++j)
- (void)__wt_random(thread->rnd);
+ (void)__wt_random(&thread->rnd);
/*
* Every thread gets a key/data buffer because we don't bother
@@ -2380,7 +2378,7 @@ wtperf_rand(CONFIG_THREAD *thread)
* Use WiredTiger's random number routine: it's lock-free and fairly
* good.
*/
- rval = (uint64_t)__wt_random(thread->rnd);
+ rval = __wt_random(&thread->rnd);
/* Use Pareto distribution to give 80/20 hot/cold values. */
if (cfg->pareto != 0) {
diff --git a/bench/wtperf/wtperf.h b/bench/wtperf/wtperf.h
index 750c0d6246e..874cdc499b1 100644
--- a/bench/wtperf/wtperf.h
+++ b/bench/wtperf/wtperf.h
@@ -211,7 +211,7 @@ typedef struct {
struct __config_thread { /* Per-thread structure */
CONFIG *cfg; /* Enclosing configuration */
- uint32_t rnd[2]; /* Random number generation state */
+ uint64_t rnd; /* Random number generation state */
pthread_t handle; /* Handle */
diff --git a/dist/s_string.ok b/dist/s_string.ok
index fa87c0086b6..e526b119282 100644
--- a/dist/s_string.ok
+++ b/dist/s_string.ok
@@ -219,6 +219,7 @@ PARAM
POSIX
PREDEFINE
PRIu
+PRNG
PTHREAD
PTR
Pandis
diff --git a/src/btree/row_srch.c b/src/btree/row_srch.c
index 6d65a89c15a..9803b924355 100644
--- a/src/btree/row_srch.c
+++ b/src/btree/row_srch.c
@@ -486,7 +486,7 @@ restart:
WT_INTL_INDEX_GET(session, page, pindex);
descent = pindex->index[
- __wt_random(session->rnd) % pindex->entries];
+ __wt_random(&session->rnd) % pindex->entries];
/*
* Swap the parent page for the child page; return on error,
@@ -520,7 +520,7 @@ restart:
cbt->compare = 0;
WT_INTL_INDEX_GET(session, btree->root.page, pindex);
cbt->slot = pindex->entries < 2 ?
- __wt_random(session->rnd) % page->pg_row_entries : 0;
+ __wt_random(&session->rnd) % page->pg_row_entries : 0;
return (__wt_row_leaf_key(session,
page, page->pg_row_d + cbt->slot, cbt->tmp, 0));
diff --git a/src/conn/conn_api.c b/src/conn/conn_api.c
index 18166b98e5e..24759b4a40a 100644
--- a/src/conn/conn_api.c
+++ b/src/conn/conn_api.c
@@ -1819,7 +1819,7 @@ wiredtiger_open(const char *home, WT_EVENT_HANDLER *event_handler,
session = conn->default_session = &conn->dummy_session;
session->iface.connection = &conn->iface;
session->name = "wiredtiger_open";
- __wt_random_init(session->rnd);
+ __wt_random_init(&session->rnd);
__wt_event_handler_set(session, event_handler);
/* Remaining basic initialization of the connection structure. */
diff --git a/src/include/btree.i b/src/include/btree.i
index 06d41b89036..b099d16b8b7 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -1314,7 +1314,7 @@ __wt_skip_choose_depth(WT_SESSION_IMPL *session)
u_int d;
for (d = 1; d < WT_SKIP_MAXDEPTH &&
- __wt_random(session->rnd) < WT_SKIP_PROBABILITY; d++)
+ __wt_random(&session->rnd) < WT_SKIP_PROBABILITY; d++)
;
return (d);
}
diff --git a/src/include/extern.h b/src/include/extern.h
index 3d3c851daad..2f2900322d9 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -639,8 +639,8 @@ extern uint32_t __wt_nlpo2(uint32_t v);
extern uint32_t __wt_log2_int(uint32_t n);
extern int __wt_ispo2(uint32_t v);
extern uint32_t __wt_rduppo2(uint32_t n, uint32_t po2);
-extern void __wt_random_init(uint32_t *rnd);
-extern uint32_t __wt_random(uint32_t *rnd);
+extern void __wt_random_init(uint64_t volatile *rnd_state);
+extern uint32_t __wt_random(uint64_t volatile *rnd_state);
extern int __wt_buf_grow_worker(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size);
extern int __wt_buf_fmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4)));
extern int __wt_buf_catfmt(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *fmt, ...) WT_GCC_FUNC_DECL_ATTRIBUTE((format (printf, 3, 4)));
diff --git a/src/include/session.h b/src/include/session.h
index 8a8b229dbc0..b9a55f924de 100644
--- a/src/include/session.h
+++ b/src/include/session.h
@@ -146,9 +146,9 @@ struct WT_COMPILER_TYPE_ALIGN(WT_CACHE_LINE_ALIGNMENT) __wt_session_impl {
* to clear everything but the fields that persist.
*/
#define WT_SESSION_CLEAR_SIZE(s) \
- (WT_PTRDIFF(&(s)->rnd[0], s))
+ (WT_PTRDIFF(&(s)->rnd, s))
- uint32_t rnd[2]; /* Random number generation state */
+ uint64_t rnd; /* Random number generation state */
/* Hashed handle reference list array */
SLIST_HEAD(__dhandles_hash, __wt_data_handle_cache) *dhhash;
diff --git a/src/log/log_slot.c b/src/log/log_slot.c
index 45455b59e6b..d6abdf9e33b 100644
--- a/src/log/log_slot.c
+++ b/src/log/log_slot.c
@@ -108,7 +108,7 @@ __wt_log_slot_join(WT_SESSION_IMPL *session, uint64_t mysize,
slot_grow_attempts = 0;
find_slot:
allocated_slot = WT_SLOT_ACTIVE == 1 ? 0 :
- __wt_random(session->rnd) % WT_SLOT_ACTIVE;
+ __wt_random(&session->rnd) % WT_SLOT_ACTIVE;
/*
* Get the selected slot. Use a barrier to prevent the compiler from
* caching this read.
diff --git a/src/lsm/lsm_work_unit.c b/src/lsm/lsm_work_unit.c
index 7a2c0ebb190..547a4096260 100644
--- a/src/lsm/lsm_work_unit.c
+++ b/src/lsm/lsm_work_unit.c
@@ -109,7 +109,7 @@ __wt_lsm_get_chunk_to_flush(WT_SESSION_IMPL *session,
* enough to trigger checkpoints.
*/
if (evict_chunk != NULL && flush_chunk != NULL) {
- chunk = (__wt_random(session->rnd) & 1) ?
+ chunk = (__wt_random(&session->rnd) & 1) ?
evict_chunk : flush_chunk;
WT_ERR(__wt_lsm_manager_push_entry(
session, WT_LSM_WORK_FLUSH, 0, lsm_tree));
diff --git a/src/session/session_api.c b/src/session/session_api.c
index 46490cb1ff5..9301fb24ea0 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -1166,7 +1166,7 @@ __wt_open_session(WT_CONNECTION_IMPL *conn,
WT_ERR(__wt_cond_alloc(session, "session", 0, &session_ret->cond));
if (WT_SESSION_FIRST_USE(session_ret))
- __wt_random_init(session_ret->rnd);
+ __wt_random_init(&session_ret->rnd);
__wt_event_handler_set(session_ret,
event_handler == NULL ? session->event_handler : event_handler);
diff --git a/src/support/rand.c b/src/support/rand.c
index bd51b2ea0d5..0d5cd034cea 100644
--- a/src/support/rand.c
+++ b/src/support/rand.c
@@ -28,43 +28,68 @@
#include "wt_internal.h"
+/*
+ * This is an implementation of George Marsaglia's multiply-with-carry pseudo-
+ * random number generator. Computationally fast, with reasonable randomness
+ * properties.
+ *
+ * Be very careful about races here. Multiple threads can call __wt_random
+ * concurrently, and it is okay if those concurrent calls get the same return
+ * value. What is *not* okay is if reading/writing the shared state races and
+ * uses two different values for m_w or m_z. That can result in a stored value
+ * of zero, in which case they will be stuck on zero forever. Take a local copy
+ * of the values to avoid that, and read/write in atomic, 8B chunks.
+ */
#undef M_W
-#define M_W (rnd)[0]
+#define M_W(p) ((uint32_t *)&(p))[0]
#undef M_Z
-#define M_Z (rnd)[1]
+#define M_Z(p) ((uint32_t *)&(p))[1]
/*
* __wt_random_init --
* Initialize return of a 32-bit pseudo-random number.
*/
void
-__wt_random_init(uint32_t *rnd)
+__wt_random_init(uint64_t volatile * rnd_state)
{
- M_W = 521288629;
- M_Z = 362436069;
+ uint64_t rnd;
+
+ M_W(rnd) = 521288629;
+ M_Z(rnd) = 362436069;
+ *rnd_state = rnd;
}
/*
* __wt_random --
* Return a 32-bit pseudo-random number.
- *
- * This is an implementation of George Marsaglia's multiply-with-carry pseudo-
- * random number generator. Computationally fast, with reasonable randomness
- * properties.
- *
- * We have to be very careful about races here. Multiple threads can call
- * __wt_random concurrently, and it is okay if those concurrent calls get the
- * same return value. What is *not* okay is if reading the shared state races
- * with an update and uses two different values for m_w or m_z. That could
- * result in a value of zero, in which case they would be stuck on zero
- * forever. Take local copies of the shared values to avoid this.
*/
uint32_t
-__wt_random(uint32_t *rnd)
+__wt_random(uint64_t volatile * rnd_state)
{
- uint32_t w = M_W, z = M_Z;
+ uint64_t rnd;
+ uint32_t w, z;
+
+ /*
+ * Take a copy of the random state so we can ensure that the
+ * calculation operates on the state consistently regardless of
+ * concurrent calls with the same random state.
+ */
+ rnd = *rnd_state;
+ w = M_W(rnd);
+ z = M_Z(rnd);
+
+ /*
+ * I don't know the period of this PRNG. Do a cheap check, if the value
+ * goes to 0 (from which we won't recover), reset to the initial state.
+ * This has additional value if a caller fails to initialize the state,
+ * or initializes with a seed that results in a short period.
+ */
+ if (z == 0 || w == 0)
+ __wt_random_init(rnd_state);
+
+ M_Z(rnd) = z = 36969 * (z & 65535) + (z >> 16);
+ M_W(rnd) = w = 18000 * (w & 65535) + (w >> 16);
+ *rnd_state = rnd;
- M_Z = z = 36969 * (z & 65535) + (z >> 16);
- M_W = w = 18000 * (w & 65535) + (w >> 16);
- return (z << 16) + (w & 65535);
+ return ((z << 16) + (w & 65535));
}
diff --git a/src/txn/txn_ckpt.c b/src/txn/txn_ckpt.c
index 78767d1a468..9dc4fca223e 100644
--- a/src/txn/txn_ckpt.c
+++ b/src/txn/txn_ckpt.c
@@ -371,7 +371,7 @@ __wt_txn_checkpoint(WT_SESSION_IMPL *session, const char *cfg[])
WT_RET(__checkpoint_apply_all(session, cfg, NULL, &full));
/* Configure logging only if doing a full checkpoint. */
- fullckpt_logging =
+ fullckpt_logging =
full && FLD_ISSET(conn->log_flags, WT_CONN_LOG_ENABLED);
/*
diff --git a/test/checkpoint/workers.c b/test/checkpoint/workers.c
index 393532f8e22..664acd6183d 100644
--- a/test/checkpoint/workers.c
+++ b/test/checkpoint/workers.c
@@ -172,13 +172,13 @@ real_worker(void)
{
WT_CURSOR **cursors;
WT_SESSION *session;
- uint32_t rnd[2];
+ uint64_t rnd;
u_int i, keyno;
int j, ret, t_ret;
ret = t_ret = 0;
- __wt_random_init(rnd);
+ __wt_random_init(&rnd);
if ((cursors = calloc(
(size_t)(g.ntables), sizeof(WT_CURSOR *))) == NULL)
@@ -203,7 +203,7 @@ real_worker(void)
"real_worker:begin_transaction", ret, 1);
goto err;
}
- keyno = __wt_random(rnd) % g.nkeys + 1;
+ keyno = __wt_random(&rnd) % g.nkeys + 1;
for (j = 0; j < g.ntables; j++) {
if ((ret = worker_op(cursors[j], keyno, i)) != 0)
break;
diff --git a/test/fops/fops.c b/test/fops/fops.c
index 0b44ccab366..e86795c4fc0 100644
--- a/test/fops/fops.c
+++ b/test/fops/fops.c
@@ -98,17 +98,17 @@ fop(void *arg)
{
STATS *s;
uintptr_t id;
- uint32_t rnd[2];
+ uint64_t rnd;
u_int i;
id = (uintptr_t)arg;
sched_yield(); /* Get all the threads created. */
s = &run_stats[id];
- __wt_random_init(rnd);
+ __wt_random_init(&rnd);
for (i = 0; i < nops; ++i, sched_yield())
- switch (__wt_random(rnd) % 9) {
+ switch (__wt_random(&rnd) % 9) {
case 0:
++s->bulk;
obj_bulk();
@@ -123,7 +123,7 @@ fop(void *arg)
break;
case 3:
++s->drop;
- obj_drop(__wt_random(rnd) & 1);
+ obj_drop(__wt_random(&rnd) & 1);
break;
case 4:
++s->ckpt;
@@ -139,11 +139,11 @@ fop(void *arg)
break;
case 7:
++s->bulk_unique;
- obj_bulk_unique(__wt_random(rnd) & 1);
+ obj_bulk_unique(__wt_random(&rnd) & 1);
break;
case 8:
++s->create_unique;
- obj_create_unique(__wt_random(rnd) & 1);
+ obj_create_unique(__wt_random(&rnd) & 1);
break;
}
diff --git a/test/format/format.h b/test/format/format.h
index a136278bb5b..ef35126045e 100644
--- a/test/format/format.h
+++ b/test/format/format.h
@@ -151,7 +151,7 @@ typedef struct {
pthread_rwlock_t backup_lock; /* Hot backup running */
- uint32_t rnd[2]; /* Global RNG state */
+ uint64_t rnd; /* Global RNG state */
/*
* We have a list of records that are appended, but not yet "resolved",
@@ -266,7 +266,7 @@ typedef struct {
extern GLOBAL g;
typedef struct {
- uint32_t rnd[2]; /* thread RNG state */
+ uint64_t rnd; /* thread RNG state */
uint64_t search; /* operations */
uint64_t insert;
@@ -309,14 +309,14 @@ void config_setup(void);
void config_single(const char *, int);
void fclose_and_clear(FILE **);
void key_gen(uint8_t *, size_t *, uint64_t);
-void key_gen_insert(uint32_t *, uint8_t *, size_t *, uint64_t);
+void key_gen_insert(uint64_t *, uint8_t *, size_t *, uint64_t);
void key_gen_setup(uint8_t **);
void key_len_setup(void);
void path_setup(const char *);
-uint32_t rng(uint32_t *);
+uint32_t rng(uint64_t *);
void track(const char *, uint64_t, TINFO *);
-void val_gen(uint32_t *, uint8_t *, size_t *, uint64_t);
-void val_gen_setup(uint32_t *, uint8_t **);
+void val_gen(uint64_t *, uint8_t *, size_t *, uint64_t);
+void val_gen_setup(uint64_t *, uint8_t **);
void wts_close(void);
void wts_create(void);
void wts_dump(const char *, int);
@@ -339,7 +339,7 @@ __attribute__((__noreturn__))
* Return a random value between a min/max pair.
*/
static inline uint32_t
-mmrand(uint32_t *rnd, u_int min, u_int max)
+mmrand(uint64_t *rnd, u_int min, u_int max)
{
return (rng(rnd) % (((max) + 1) - (min)) + (min));
}
diff --git a/test/format/ops.c b/test/format/ops.c
index bbb57b4d8c3..3b344b009b0 100644
--- a/test/format/ops.c
+++ b/test/format/ops.c
@@ -194,7 +194,7 @@ wts_ops(int lastrun)
* Return the current session configuration.
*/
static const char *
-ops_session_config(uint32_t *rnd)
+ops_session_config(uint64_t *rnd)
{
u_int v;
@@ -232,7 +232,7 @@ ops(void *arg)
tinfo = arg;
/* Initialize the per-thread random number generator. */
- __wt_random_init(tinfo->rnd);
+ __wt_random_init(&tinfo->rnd);
conn = g.wts_conn;
keybuf = valbuf = NULL;
@@ -240,7 +240,7 @@ ops(void *arg)
/* Set up the default key and value buffers. */
key_gen_setup(&keybuf);
- val_gen_setup(tinfo->rnd, &valbuf);
+ val_gen_setup(&tinfo->rnd, &valbuf);
/* Set the first operation where we'll create sessions and cursors. */
session_op = 0;
@@ -248,7 +248,7 @@ ops(void *arg)
cursor = cursor_insert = NULL;
/* Set the first operation where we'll perform checkpoint operations. */
- ckpt_op = g.c_checkpoints ? mmrand(tinfo->rnd, 100, 10000) : 0;
+ ckpt_op = g.c_checkpoints ? mmrand(&tinfo->rnd, 100, 10000) : 0;
ckpt_available = 0;
for (intxn = 0; !tinfo->quit; ++tinfo->ops) {
@@ -273,7 +273,7 @@ ops(void *arg)
die(ret, "session.close");
if ((ret = conn->open_session(conn, NULL,
- ops_session_config(tinfo->rnd), &session)) != 0)
+ ops_session_config(&tinfo->rnd), &session)) != 0)
die(ret, "connection.open_session");
/*
@@ -288,7 +288,7 @@ ops(void *arg)
* checkpoints.
*/
if (!SINGLETHREADED && !DATASOURCE("lsm") &&
- ckpt_available && mmrand(tinfo->rnd, 1, 10) == 1) {
+ ckpt_available && mmrand(&tinfo->rnd, 1, 10) == 1) {
if ((ret = session->open_cursor(session,
g.uri, NULL, ckpt_name, &cursor)) != 0)
die(ret, "session.open_cursor");
@@ -321,7 +321,7 @@ ops(void *arg)
die(ret, "session.open_cursor");
/* Pick the next session/cursor close/open. */
- session_op += mmrand(tinfo->rnd, 100, 5000);
+ session_op += mmrand(&tinfo->rnd, 100, 5000);
/* Updates supported. */
readonly = 0;
@@ -338,7 +338,7 @@ ops(void *arg)
*/
if (DATASOURCE("helium") || DATASOURCE("kvsbdb") ||
DATASOURCE("lsm") ||
- readonly || mmrand(tinfo->rnd, 1, 5) == 1)
+ readonly || mmrand(&tinfo->rnd, 1, 5) == 1)
ckpt_config = NULL;
else {
(void)snprintf(ckpt_name, sizeof(ckpt_name),
@@ -373,7 +373,7 @@ ops(void *arg)
ckpt_available = 1;
/* Pick the next checkpoint operation. */
- ckpt_op += mmrand(tinfo->rnd, 5000, 20000);
+ ckpt_op += mmrand(&tinfo->rnd, 5000, 20000);
}
/*
@@ -381,7 +381,7 @@ ops(void *arg)
* start a transaction 20% of the time.
*/
if (!SINGLETHREADED &&
- !intxn && mmrand(tinfo->rnd, 1, 10) >= 8) {
+ !intxn && mmrand(&tinfo->rnd, 1, 10) >= 8) {
if ((ret =
session->begin_transaction(session, NULL)) != 0)
die(ret, "session.begin_transaction");
@@ -390,7 +390,7 @@ ops(void *arg)
insert = notfound = 0;
- keyno = mmrand(tinfo->rnd, 1, (u_int)g.rows);
+ keyno = mmrand(&tinfo->rnd, 1, (u_int)g.rows);
key.data = keybuf;
value.data = valbuf;
@@ -401,7 +401,7 @@ ops(void *arg)
* of deletes will mean fewer inserts and writes. Modifications
* are always followed by a read to confirm it worked.
*/
- op = readonly ? UINT32_MAX : mmrand(tinfo->rnd, 1, 100);
+ op = readonly ? UINT32_MAX : mmrand(&tinfo->rnd, 1, 100);
if (op < g.c_delete_pct) {
++tinfo->remove;
switch (g.type) {
@@ -479,8 +479,8 @@ skip_insert: if (col_update(tinfo,
* a random direction.
*/
if (!insert) {
- dir = (int)mmrand(tinfo->rnd, 0, 1);
- for (np = 0; np < mmrand(tinfo->rnd, 1, 8); ++np) {
+ dir = (int)mmrand(&tinfo->rnd, 0, 1);
+ for (np = 0; np < mmrand(&tinfo->rnd, 1, 8); ++np) {
if (notfound)
break;
if (nextprev(cursor, dir, &notfound))
@@ -502,7 +502,7 @@ skip_insert: if (col_update(tinfo,
* rollback 10% of the time.
*/
if (intxn)
- switch (mmrand(tinfo->rnd, 1, 10)) {
+ switch (mmrand(&tinfo->rnd, 1, 10)) {
case 1: case 2: case 3: case 4: /* 40% */
if ((ret = session->commit_transaction(
session, NULL)) != 0)
@@ -807,7 +807,7 @@ row_update(TINFO *tinfo,
session = cursor->session;
key_gen((uint8_t *)key->data, &key->size, keyno);
- val_gen(tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
+ val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
/* Log the operation */
if (g.logging == LOG_OPS)
@@ -851,7 +851,7 @@ col_update(TINFO *tinfo,
session = cursor->session;
- val_gen(tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
+ val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
/* Log the operation */
if (g.logging == LOG_OPS) {
@@ -1010,8 +1010,8 @@ row_insert(TINFO *tinfo,
session = cursor->session;
- key_gen_insert(tinfo->rnd, (uint8_t *)key->data, &key->size, keyno);
- val_gen(tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
+ key_gen_insert(&tinfo->rnd, (uint8_t *)key->data, &key->size, keyno);
+ val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, keyno);
/* Log the operation */
if (g.logging == LOG_OPS)
@@ -1056,7 +1056,7 @@ col_insert(TINFO *tinfo,
session = cursor->session;
- val_gen(tinfo->rnd, (uint8_t *)value->data, &value->size, g.rows + 1);
+ val_gen(&tinfo->rnd, (uint8_t *)value->data, &value->size, g.rows + 1);
if (g.type == FIX)
cursor->set_value(cursor, *(uint8_t *)value->data);
diff --git a/test/format/t.c b/test/format/t.c
index c31d86f073d..8e8a627235f 100644
--- a/test/format/t.c
+++ b/test/format/t.c
@@ -106,7 +106,7 @@ main(int argc, char *argv[])
argv += __wt_optind;
/* Initialize the global random number generator. */
- __wt_random_init(g.rnd);
+ __wt_random_init(&g.rnd);
/* Set up paths. */
path_setup(home);
diff --git a/test/format/util.c b/test/format/util.c
index 20511a6fe49..8d077f6caa7 100644
--- a/test/format/util.c
+++ b/test/format/util.c
@@ -33,7 +33,7 @@
#endif
static inline uint32_t
-kv_len(uint32_t *rnd, uint64_t keyno, uint32_t min, uint32_t max)
+kv_len(uint64_t *rnd, uint64_t keyno, uint32_t min, uint32_t max)
{
/*
* Focus on relatively small key/value items, admitting the possibility
@@ -116,7 +116,7 @@ key_gen(uint8_t *key, size_t *sizep, uint64_t keyno)
}
void
-key_gen_insert(uint32_t *rnd, uint8_t *key, size_t *sizep, uint64_t keyno)
+key_gen_insert(uint64_t *rnd, uint8_t *key, size_t *sizep, uint64_t keyno)
{
key_gen_common(key, sizep, keyno, (int)mmrand(rnd, 1, 15));
}
@@ -124,7 +124,7 @@ key_gen_insert(uint32_t *rnd, uint8_t *key, size_t *sizep, uint64_t keyno)
static uint32_t val_dup_data_len; /* Length of duplicate data items */
void
-val_gen_setup(uint32_t *rnd, uint8_t **valp)
+val_gen_setup(uint64_t *rnd, uint8_t **valp)
{
uint8_t *val;
size_t i, len;
@@ -151,7 +151,7 @@ val_gen_setup(uint32_t *rnd, uint8_t **valp)
}
void
-val_gen(uint32_t *rnd, uint8_t *val, size_t *sizep, uint64_t keyno)
+val_gen(uint64_t *rnd, uint8_t *val, size_t *sizep, uint64_t keyno)
{
/*
* Fixed-length records: take the low N bits from the last digit of
@@ -361,7 +361,7 @@ path_setup(const char *home)
* Return a random number.
*/
uint32_t
-rng(uint32_t *rnd)
+rng(uint64_t *rnd)
{
char buf[64];
uint32_t r;
@@ -371,7 +371,7 @@ rng(uint32_t *rnd)
* use the default.
*/
if (rnd == NULL)
- rnd = g.rnd;
+ rnd = &g.rnd;
/*
* We can reproduce a single-threaded run based on the random numbers
diff --git a/test/suite/suite_random.py b/test/suite/suite_random.py
index 114b50ba915..edb59b80e15 100644
--- a/test/suite/suite_random.py
+++ b/test/suite/suite_random.py
@@ -39,19 +39,13 @@ class suite_random:
arglen = len(args)
if arglen == 1:
self.seedw = int(args[0]) & 0xffffffff
- self.seedz = int(args[0]) & 0Xffffffff
+ self.seedz = int(args[0]) & 0xffffffff
elif arglen == 2:
self.seedw = int(args[0]) & 0xffffffff
- self.seedz = int(args[1]) & 0Xffffffff
+ self.seedz = int(args[1]) & 0xffffffff
else:
- self.seedw = 0
- self.seedz = 0
-
- # The seeds cannot be 0
- if self.seedw == 0:
- self.seedw += 22233
- if self.seedz == 0:
- self.seedz += 11133
+ self.seedw = 521288629
+ self.seedz = 362436069
def rand32(self):
"""
@@ -59,9 +53,13 @@ class suite_random:
"""
w = self.seedw
z = self.seedz
- self.seedw = (18000 * (w & 0xffff) + (w >> 16)) & 0xffffffff
- self.seedz = (36969 * (z & 0xffff) + (z >> 16)) & 0xffffffff
- return ((z << 16) + w) & 0xffffffff
+ if w == 0 or z == 0:
+ self.seedw = 521288629
+ self.seedz = 362436069
+
+ self.seedz = (36969 * (z & 65535) + (z >> 16)) & 0xffffffff
+ self.seedw = (18000 * (w & 65535) + (w >> 16)) & 0xffffffff
+ return ((z << 16) + w & 65535) & 0xffffffff
def rand_range(self, n, m):
"""
diff --git a/test/thread/rw.c b/test/thread/rw.c
index 35733e7d647..402789dd2a5 100644
--- a/test/thread/rw.c
+++ b/test/thread/rw.c
@@ -36,7 +36,7 @@ typedef struct {
char *name; /* object name */
u_int nops; /* Thread op count */
- uint32_t rnd[2]; /* RNG */
+ uint64_t rnd; /* RNG */
int remove; /* cursor.remove */
int update; /* cursor.update */
@@ -168,7 +168,7 @@ reader_op(WT_SESSION *session, WT_CURSOR *cursor, INFO *s)
key = &_key;
- keyno = __wt_random(s->rnd) % nkeys + 1;
+ keyno = __wt_random(&s->rnd) % nkeys + 1;
if (ftype == ROW) {
key->data = keybuf;
key->size = (uint32_t)
@@ -200,7 +200,7 @@ reader(void *arg)
id = (int)(uintptr_t)arg;
s = &run_info[id];
__wt_thread_id(tid, sizeof(tid));
- __wt_random_init(s->rnd);
+ __wt_random_init(&s->rnd);
printf(" read thread %2d starting: tid: %s, file: %s\n",
id, tid, s->name);
@@ -253,7 +253,7 @@ writer_op(WT_SESSION *session, WT_CURSOR *cursor, INFO *s)
key = &_key;
value = &_value;
- keyno = __wt_random(s->rnd) % nkeys + 1;
+ keyno = __wt_random(&s->rnd) % nkeys + 1;
if (ftype == ROW) {
key->data = keybuf;
key->size = (uint32_t)
@@ -301,7 +301,7 @@ writer(void *arg)
id = (int)(uintptr_t)arg;
s = &run_info[id];
__wt_thread_id(tid, sizeof(tid));
- __wt_random_init(s->rnd);
+ __wt_random_init(&s->rnd);
printf("write thread %2d starting: tid: %s, file: %s\n",
id, tid, s->name);