diff options
author | Alex Gorrod <alexander.gorrod@mongodb.com> | 2015-06-02 15:05:54 +1000 |
---|---|---|
committer | Alex Gorrod <alexander.gorrod@mongodb.com> | 2015-06-02 15:05:54 +1000 |
commit | 42db5bae706130666452915fd204d60101d24950 (patch) | |
tree | 72ba3960d0eedb2cf291b02385cf4b1725bc62ba | |
parent | b342030efe3ce392ec36577cd732630821f02dd0 (diff) | |
parent | 7bece7ab57f5d957fb9df318e4492937ff92108b (diff) | |
download | mongo-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.c | 18 | ||||
-rw-r--r-- | bench/wtperf/wtperf.h | 2 | ||||
-rw-r--r-- | dist/s_string.ok | 1 | ||||
-rw-r--r-- | src/btree/row_srch.c | 4 | ||||
-rw-r--r-- | src/conn/conn_api.c | 2 | ||||
-rw-r--r-- | src/include/btree.i | 2 | ||||
-rw-r--r-- | src/include/extern.h | 4 | ||||
-rw-r--r-- | src/include/session.h | 4 | ||||
-rw-r--r-- | src/log/log_slot.c | 2 | ||||
-rw-r--r-- | src/lsm/lsm_work_unit.c | 2 | ||||
-rw-r--r-- | src/session/session_api.c | 2 | ||||
-rw-r--r-- | src/support/rand.c | 67 | ||||
-rw-r--r-- | src/txn/txn_ckpt.c | 2 | ||||
-rw-r--r-- | test/checkpoint/workers.c | 6 | ||||
-rw-r--r-- | test/fops/fops.c | 12 | ||||
-rw-r--r-- | test/format/format.h | 14 | ||||
-rw-r--r-- | test/format/ops.c | 40 | ||||
-rw-r--r-- | test/format/t.c | 2 | ||||
-rw-r--r-- | test/format/util.c | 12 | ||||
-rw-r--r-- | test/suite/suite_random.py | 24 | ||||
-rw-r--r-- | test/thread/rw.c | 10 |
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, ¬found)) @@ -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); |