diff --git a/configure b/configure index 0e537d9..f11cccf 100755 --- a/configure +++ b/configure @@ -18923,7 +18923,8 @@ fi -for ac_func in cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l + +for ac_func in cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat random_r readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 150f9a5..fc1e73a 100644 --- a/configure.in +++ b/configure.in @@ -1192,7 +1192,7 @@ PGAC_VAR_INT_TIMEZONE AC_FUNC_ACCEPT_ARGTYPES PGAC_FUNC_GETTIMEOFDAY_1ARG -AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l]) +AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getifaddrs getpeerucred getrlimit memmove poll pstat random_r readlink scandir setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs wcstombs_l]) AC_REPLACE_FUNCS(fseeko) case $host_os in diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index 9892f4c..751deb1 100644 --- a/contrib/pgbench/pgbench.c +++ b/contrib/pgbench/pgbench.c @@ -104,6 +104,8 @@ extern int optind; #define DEFAULT_NXACTS 10 /* default nxacts */ +#define RAND_STATE_BYTES 128 /* glibc supports powers of 2, 8 .. 256 */ + int nxacts = 0; /* number of transactions per client */ int duration = 0; /* duration in seconds */ @@ -198,6 +200,10 @@ typedef struct instr_time start_time; /* thread start time */ instr_time *exec_elapsed; /* time spent executing cmds (per Command) */ int *exec_count; /* number of cmd executions (per Command) */ +#ifdef HAVE_RANDOM_R + char randstate[RAND_STATE_BYTES]; /* random state */ + struct random_data randbuf; /* random data buffer */ +#endif } TState; #define INVALID_THREAD ((pthread_t) 0) @@ -380,13 +386,21 @@ usage(const char *progname) /* random number generator: uniform distribution from min to max inclusive */ static int -getrand(int min, int max) +getrand(TState *thread, int min, int max) { +#ifdef HAVE_RANDOM_R + int32_t raw; + random_r(&thread->randbuf, &raw); +#else + long raw; + raw = random(); +#endif + /* * Odd coding is so that min and max have approximately the same chance of * being selected as do numbers between them. */ - return min + (int) (((max - min + 1) * (double) random()) / (MAX_RANDOM_VALUE + 1.0)); + return min + (int) (((max - min + 1) * (double) raw) / (MAX_RANDOM_VALUE + 1.0)); } /* call PQexec() and exit() on failure */ @@ -901,7 +915,7 @@ top: if (commands[st->state] == NULL) { st->state = 0; - st->use_file = getrand(0, num_files - 1); + st->use_file = getrand(thread, 0, num_files - 1); commands = sql_files[st->use_file]; } } @@ -1068,9 +1082,9 @@ top: } #ifdef DEBUG - printf("min: %d max: %d random: %d\n", min, max, getrand(min, max)); + printf("min: %d max: %d random: %d\n", min, max, getrand(thread, min, max)); #endif - snprintf(res, sizeof(res), "%d", getrand(min, max)); + snprintf(res, sizeof(res), "%d", getrand(thread, min, max)); if (!putVariable(st, argv[0], argv[1], res)) { @@ -2242,6 +2256,15 @@ main(int argc, char **argv) thread->tid = i; thread->state = &state[nclients / nthreads * i]; thread->nstate = nclients / nthreads; +#ifdef HAVE_RANDOM_R + /* glibc gets confused if we don't zero these */ + memset(thread->randstate, 0, RAND_STATE_BYTES); + memset(&thread->randbuf, 0, sizeof(thread->randbuf)); + initstate_r(((unsigned int) INSTR_TIME_GET_MICROSEC(start_time)) + + ((unsigned int) i), + thread->randstate, RAND_STATE_BYTES, + &thread->randbuf); +#endif if (is_latencies) { @@ -2384,7 +2407,7 @@ threadRun(void *arg) Command **commands = sql_files[st->use_file]; int prev_ecnt = st->ecnt; - st->use_file = getrand(0, num_files - 1); + st->use_file = getrand(thread, 0, num_files - 1); if (!doCustom(thread, st, &result->conn_time, logfile)) remains--; /* I've aborted */ @@ -2590,9 +2613,11 @@ pthread_create(pthread_t *thread, * output of a single random() sequence, which should be okay for our * purposes.) */ +#ifndef HAVE_RANDOM_R INSTR_TIME_SET_CURRENT(start_time); srandom(((unsigned int) INSTR_TIME_GET_MICROSEC(start_time)) + ((unsigned int) getpid())); +#endif ret = start_routine(arg); write(th->pipes[1], ret, sizeof(TResult)); diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 24b951e..8e87667 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -405,6 +405,9 @@ /* Define to 1 if you have the `random' function. */ #undef HAVE_RANDOM +/* Define to 1 if you have the `random_r' function. */ +#undef HAVE_RANDOM_R + /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_H