Fixes #18: lrand48() is not thread-safe
and LP#1412488: lrand48() doesn't scale well on highly concurrent platforms Use re-entrant versions of standard RNG functions with thread-local states. Seed thread-local RNGs from the RNG of the thread invoking sb_thread_create() (i.e. the main thread). The main thread RNG is now always seeded from timer, unless --rand-seed is specified. Which obsoletes --rand-init, so it has been removed.
This commit is contained in:
@ -73,7 +73,6 @@ The table below lists the supported common options, their descriptions and defau
|
||||
| `--max-requests` | Limit for total number of requests. 0 means unlimited | 10000 |
|
||||
| `--max-time` | Limit for total execution time in seconds. 0 (default) means unlimited | 0 |
|
||||
| `--thread-stack-size` | Size of stack for each thread | 32K |
|
||||
| `--init-rng` | Specifies if random numbers generator should be initialized from timer before the test start | off |
|
||||
| `--report-interval` | Periodically report intermediate statistics with a specified interval in seconds. Note that statistics produced by this option is per-interval rather than cumulative. 0 disables intermediate reports | 0 |
|
||||
| `--test` | Name of the test mode to run | *Required* |
|
||||
| `--debug` | Print more debug info | off |
|
||||
|
||||
@ -264,6 +264,9 @@ AC_C_INLINE
|
||||
AC_TYPE_OFF_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
AX_TLS([], [
|
||||
AC_MSG_ERROR([Thread-local storage is not suppored by the target platform!])
|
||||
])
|
||||
|
||||
if test "$enable_largefile" = yes; then
|
||||
AC_SYS_LARGEFILE
|
||||
@ -295,8 +298,8 @@ alarm \
|
||||
directio \
|
||||
fdatasync \
|
||||
gettimeofday \
|
||||
lrand48 \
|
||||
drand48 \
|
||||
lrand48_r
|
||||
rand_r \
|
||||
memalign \
|
||||
memset \
|
||||
mkstemp \
|
||||
|
||||
74
m4/ax_tls.m4
Normal file
74
m4/ax_tls.m4
Normal file
@ -0,0 +1,74 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_tls.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_TLS([action-if-found], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Provides a test for the compiler support of thread local storage (TLS)
|
||||
# extensions. Defines TLS if it is found. Currently knows about GCC/ICC
|
||||
# and MSVC. I think SunPro uses the same as GCC, and Borland apparently
|
||||
# supports either.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
|
||||
# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 11
|
||||
|
||||
AC_DEFUN([AX_TLS], [
|
||||
AC_MSG_CHECKING([for thread local storage (TLS) class])
|
||||
AC_CACHE_VAL([ac_cv_tls],
|
||||
[for ax_tls_keyword in __thread '__declspec(thread)' none; do
|
||||
AS_CASE([$ax_tls_keyword],
|
||||
[none], [ac_cv_tls=none ; break],
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <stdlib.h>
|
||||
static void
|
||||
foo(void) {
|
||||
static ] $ax_tls_keyword [ int bar;
|
||||
exit(1);
|
||||
}],
|
||||
[],
|
||||
[ac_cv_tls=$ax_tls_keyword ; break],
|
||||
ac_cv_tls=none
|
||||
)])
|
||||
done
|
||||
])
|
||||
AC_MSG_RESULT([$ac_cv_tls])
|
||||
|
||||
AS_IF([test "$ac_cv_tls" != "none"],
|
||||
[AC_DEFINE_UNQUOTED([TLS],[$ac_cv_tls],[If the compiler supports a TLS storage class define it to that here])
|
||||
m4_ifnblank([$1],[$1])],
|
||||
[m4_ifnblank([$2],[$2])])
|
||||
])
|
||||
@ -49,7 +49,8 @@ endif
|
||||
|
||||
sysbench_SOURCES = sysbench.c sysbench.h sb_timer.c sb_timer.h \
|
||||
sb_options.c sb_options.h sb_logger.c sb_logger.h sb_list.h db_driver.h \
|
||||
db_driver.c sb_percentile.c sb_percentile.h
|
||||
db_driver.c sb_percentile.c sb_percentile.h sb_rnd.c sb_rnd.h \
|
||||
sb_thread.c sb_thread.h
|
||||
|
||||
sysbench_LDADD = tests/fileio/libsbfileio.a tests/threads/libsbthreads.a \
|
||||
tests/memory/libsbmemory.a tests/cpu/libsbcpu.a \
|
||||
|
||||
27
sysbench/sb_rnd.c
Normal file
27
sysbench/sb_rnd.c
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LRAND48_R
|
||||
TLS struct drand48_data sb_rng_state;
|
||||
#elif defined(HAVE_RAND_R)
|
||||
TLS unsigned int sb_rng_state;
|
||||
#endif
|
||||
56
sysbench/sb_rnd.h
Normal file
56
sysbench/sb_rnd.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SB_RND_H
|
||||
#define SB_RND_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Pick the best available re-entrant PRNG */
|
||||
#if defined(HAVE_LRAND48_R)
|
||||
extern TLS struct drand48_data sb_rng_state;
|
||||
|
||||
static inline long sb_rnd(void)
|
||||
{
|
||||
long result;
|
||||
|
||||
lrand48_r(&sb_rng_state, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
static inline double sb_rnd_double(void)
|
||||
{
|
||||
double result;
|
||||
|
||||
drand48_r(&sb_rng_state, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
#define sb_srnd(seed) srand48_r(seed, &sb_rng_state)
|
||||
|
||||
#elif defined(HAVE_RAND_R)
|
||||
extern TLS unsigned int sb_rng_state;
|
||||
# define sb_rnd() (rand_r(&sb_rng_state))
|
||||
# define sb_srnd(seed) do { sb_rng_state = seed; } while(0)
|
||||
/* On some platforms rand() may return values larger than RAND_MAX */
|
||||
# define sb_rnd_double() ((double) (sb_rnd() % RAND_MAX) / RAND_MAX)
|
||||
#else
|
||||
# error No re-entrant PRNG function found.
|
||||
#endif
|
||||
|
||||
#endif /* SB_RND_H */
|
||||
56
sysbench/sb_thread.c
Normal file
56
sysbench/sb_thread.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
Wrappers around pthread_create() and friends to provide necessary
|
||||
(de-)initialization.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "sb_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "sb_thread.h"
|
||||
#include "sb_rnd.h"
|
||||
|
||||
int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg)
|
||||
{
|
||||
/* Initialize thread-local RNG state */
|
||||
sb_srnd(sb_rnd());
|
||||
|
||||
return pthread_create(thread, attr, start_routine, arg);
|
||||
}
|
||||
|
||||
int sb_thread_join(pthread_t thread, void **retval)
|
||||
{
|
||||
return pthread_join(thread, retval);
|
||||
}
|
||||
|
||||
int sb_thread_cancel(pthread_t thread)
|
||||
{
|
||||
return pthread_cancel(thread);
|
||||
}
|
||||
46
sysbench/sb_thread.h
Normal file
46
sysbench/sb_thread.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
Wrappers around pthread_create() and friends to provide necessary
|
||||
(de-)initialization.
|
||||
*/
|
||||
|
||||
#ifndef SB_THREAD_H
|
||||
#define SB_THREAD_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "sb_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine) (void *), void *arg);
|
||||
|
||||
int sb_thread_join(pthread_t thread, void **retval);
|
||||
|
||||
int sb_thread_cancel(pthread_t thread);
|
||||
|
||||
#endif /* SB_THREAD_H */
|
||||
@ -223,6 +223,11 @@ int pthread_join(pthread_t pthread, void **value_ptr)
|
||||
|
||||
}
|
||||
|
||||
pthread_t pthread_self(void)
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
/*
|
||||
One time initialization. For simplicity, we assume initializer thread
|
||||
does not exit within init_routine().
|
||||
|
||||
@ -100,6 +100,7 @@ extern int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
|
||||
extern int pthread_cancel(pthread_t thread);
|
||||
extern int pthread_attr_setstacksize( pthread_attr_t *attr, size_t stacksize);
|
||||
extern int pthread_join(pthread_t thread, void **value_ptr);
|
||||
extern int pthread_self(void);
|
||||
extern int gettimeofday(struct timeval * tp, void * tzp);
|
||||
extern int random();
|
||||
|
||||
|
||||
@ -26,8 +26,8 @@
|
||||
#include "lauxlib.h"
|
||||
|
||||
#include "sb_script.h"
|
||||
|
||||
#include "db_driver.h"
|
||||
#include "sb_rnd.h"
|
||||
|
||||
#define EVENT_FUNC "event"
|
||||
#define PREPARE_FUNC "prepare"
|
||||
|
||||
@ -68,6 +68,8 @@
|
||||
#include "sb_options.h"
|
||||
#include "scripting/sb_script.h"
|
||||
#include "db_driver.h"
|
||||
#include "sb_rnd.h"
|
||||
#include "sb_thread.h"
|
||||
|
||||
#define VERSION_STRING PACKAGE" "PACKAGE_VERSION
|
||||
|
||||
@ -92,8 +94,6 @@ typedef struct {
|
||||
sb_list_item_t listitem;
|
||||
} event_queue_elem_t;
|
||||
|
||||
/* If we should initialize random numbers generator */
|
||||
static int rand_init;
|
||||
static rand_dist_t rand_type;
|
||||
static int (*rand_func)(int, int); /* pointer to random numbers generator */
|
||||
static unsigned int rand_iter;
|
||||
@ -138,7 +138,6 @@ sb_arg_t general_args[] =
|
||||
{"validate", "perform validation checks where possible", SB_ARG_TYPE_FLAG, "off"},
|
||||
{"help", "print help and exit", SB_ARG_TYPE_FLAG, NULL},
|
||||
{"version", "print version and exit", SB_ARG_TYPE_FLAG, "off"},
|
||||
{"rand-init", "initialize random number generator", SB_ARG_TYPE_FLAG, "off"},
|
||||
{"rand-type", "random numbers distribution {uniform,gaussian,special,pareto}",
|
||||
SB_ARG_TYPE_STRING, "special"},
|
||||
{"rand-spec-iter", "number of iterations used for numbers generation", SB_ARG_TYPE_INT, "12"},
|
||||
@ -429,12 +428,6 @@ void print_run_mode(sb_test_t *test)
|
||||
if (sb_globals.validate)
|
||||
log_text(LOG_NOTICE, "Additional request validation enabled.\n");
|
||||
|
||||
if (rand_init)
|
||||
{
|
||||
log_text(LOG_NOTICE, "Initializing random number generator from timer.\n");
|
||||
sb_srnd(time(NULL));
|
||||
}
|
||||
|
||||
if (rand_seed)
|
||||
{
|
||||
log_text(LOG_NOTICE, "Initializing random number generator from seed (%d).\n", rand_seed);
|
||||
@ -442,7 +435,9 @@ void print_run_mode(sb_test_t *test)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_text(LOG_NOTICE, "Random number generator seed is 0 and will be ignored\n");
|
||||
log_text(LOG_NOTICE,
|
||||
"Initializing random number generator from current time\n");
|
||||
sb_srnd(time(NULL));
|
||||
}
|
||||
|
||||
if (sb_globals.force_shutdown)
|
||||
@ -578,7 +573,7 @@ static void *eventgen_thread_proc(void *arg)
|
||||
|
||||
curr_ns = sb_timer_value(&sb_globals.exec_timer);
|
||||
/* emulate exponential distribution with Lambda = tx_rate */
|
||||
intr_ns = (long) (log(1 - (double) sb_rnd() / (double) SB_MAX_RND) /
|
||||
intr_ns = (long) (log(1 - sb_rnd_double()) /
|
||||
(-(double) sb_globals.tx_rate)*1000000);
|
||||
next_ns = curr_ns + intr_ns*1000;
|
||||
|
||||
@ -587,7 +582,7 @@ static void *eventgen_thread_proc(void *arg)
|
||||
curr_ns = sb_timer_value(&sb_globals.exec_timer);
|
||||
|
||||
/* emulate exponential distribution with Lambda = tx_rate */
|
||||
intr_ns = (long) (log(1 - (double)sb_rnd() / (double)SB_MAX_RND) /
|
||||
intr_ns = (long) (log(1 - sb_rnd_double()) /
|
||||
(-(double)sb_globals.tx_rate)*1000000);
|
||||
|
||||
next_ns = next_ns + intr_ns*1000;
|
||||
@ -794,10 +789,11 @@ static int run_test(sb_test_t *test)
|
||||
if (sb_globals.report_interval > 0)
|
||||
{
|
||||
/* Create a thread for intermediate statistic reports */
|
||||
if ((err = pthread_create(&report_thread, &thread_attr, &report_thread_proc,
|
||||
NULL)) != 0)
|
||||
if ((err = sb_thread_create(&report_thread, &thread_attr, &report_thread_proc,
|
||||
NULL)) != 0)
|
||||
{
|
||||
log_errno(LOG_FATAL, "pthread_create() for the reporting thread failed.");
|
||||
log_errno(LOG_FATAL,
|
||||
"sb_thread_create() for the reporting thread failed.");
|
||||
return 1;
|
||||
}
|
||||
report_thread_created = 1;
|
||||
@ -805,10 +801,11 @@ static int run_test(sb_test_t *test)
|
||||
|
||||
if (sb_globals.tx_rate > 0)
|
||||
{
|
||||
if ((err = pthread_create(&eventgen_thread, &thread_attr, &eventgen_thread_proc,
|
||||
NULL)) != 0)
|
||||
if ((err = sb_thread_create(&eventgen_thread, &thread_attr, &eventgen_thread_proc,
|
||||
NULL)) != 0)
|
||||
{
|
||||
log_errno(LOG_FATAL, "pthread_create() for the reporting thread failed.");
|
||||
log_errno(LOG_FATAL,
|
||||
"sb_thread_create() for the reporting thread failed.");
|
||||
return 1;
|
||||
}
|
||||
eventgen_thread_created = 1;
|
||||
@ -817,11 +814,11 @@ static int run_test(sb_test_t *test)
|
||||
if (sb_globals.n_checkpoints > 0)
|
||||
{
|
||||
/* Create a thread for checkpoint statistic reports */
|
||||
if ((err = pthread_create(&checkpoints_thread, &thread_attr,
|
||||
&checkpoints_thread_proc, NULL)) != 0)
|
||||
if ((err = sb_thread_create(&checkpoints_thread, &thread_attr,
|
||||
&checkpoints_thread_proc, NULL)) != 0)
|
||||
{
|
||||
log_errno(LOG_FATAL, "pthread_create() for the checkpoint thread "
|
||||
"failed.");
|
||||
log_errno(LOG_FATAL,
|
||||
"sb_thread_create() for the checkpoint thread failed.");
|
||||
return 1;
|
||||
}
|
||||
checkpoints_thread_created = 1;
|
||||
@ -832,10 +829,10 @@ static int run_test(sb_test_t *test)
|
||||
{
|
||||
if (sb_globals.error)
|
||||
return 1;
|
||||
if ((err = pthread_create(&(threads[i].thread), &thread_attr,
|
||||
&runner_thread, (void*)(threads + i))) != 0)
|
||||
if ((err = sb_thread_create(&(threads[i].thread), &thread_attr,
|
||||
&runner_thread, (void*)(threads + i))) != 0)
|
||||
{
|
||||
log_errno(LOG_FATAL, "pthread_create() for thread #%d failed.", i);
|
||||
log_errno(LOG_FATAL, "sb_thread_create() for thread #%d failed.", i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -855,8 +852,8 @@ static int run_test(sb_test_t *test)
|
||||
log_text(LOG_NOTICE, "Threads started!\n");
|
||||
for(i = 0; i < sb_globals.num_threads; i++)
|
||||
{
|
||||
if((err = pthread_join(threads[i].thread, NULL)) != 0)
|
||||
log_errno(LOG_FATAL, "pthread_join() for thread #%d failed.", i);
|
||||
if((err = sb_thread_join(threads[i].thread, NULL)) != 0)
|
||||
log_errno(LOG_FATAL, "sb_thread_join() for thread #%d failed.", i);
|
||||
}
|
||||
|
||||
sb_timer_stop(&sb_globals.exec_timer);
|
||||
@ -895,7 +892,7 @@ static int run_test(sb_test_t *test)
|
||||
/* Delay killing the reporting threads to avoid mutex lock leaks */
|
||||
if (report_thread_created)
|
||||
{
|
||||
if (pthread_cancel(report_thread) || pthread_join(report_thread, NULL))
|
||||
if (sb_thread_cancel(report_thread) || sb_thread_join(report_thread, NULL))
|
||||
log_errno(LOG_FATAL, "Terminating the reporting thread failed.");
|
||||
}
|
||||
|
||||
@ -903,14 +900,15 @@ static int run_test(sb_test_t *test)
|
||||
|
||||
if (eventgen_thread_created)
|
||||
{
|
||||
if (pthread_cancel(eventgen_thread) || pthread_join(eventgen_thread, NULL))
|
||||
if (sb_thread_cancel(eventgen_thread) ||
|
||||
sb_thread_join(eventgen_thread, NULL))
|
||||
log_text(LOG_FATAL, "Terminating the event generator thread failed.");
|
||||
}
|
||||
|
||||
if (checkpoints_thread_created)
|
||||
{
|
||||
if (pthread_cancel(checkpoints_thread) ||
|
||||
pthread_join(checkpoints_thread, NULL))
|
||||
if (sb_thread_cancel(checkpoints_thread) ||
|
||||
sb_thread_join(checkpoints_thread, NULL))
|
||||
log_errno(LOG_FATAL, "Terminating the checkpoint thread failed.");
|
||||
}
|
||||
|
||||
@ -1018,13 +1016,7 @@ static int init(void)
|
||||
|
||||
sb_globals.validate = sb_get_value_flag("validate");
|
||||
|
||||
rand_init = sb_get_value_flag("rand-init");
|
||||
rand_seed = sb_get_value_int("rand-seed");
|
||||
if (rand_init && rand_seed)
|
||||
{
|
||||
log_text(LOG_FATAL, "Cannot set both --rand-init and --rand-seed");
|
||||
return 1;
|
||||
}
|
||||
rand_seed = sb_get_value_int("rand-seed");
|
||||
|
||||
s = sb_get_value_string("rand-type");
|
||||
if (!strcmp(s, "uniform"))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* Copyright (C) 2004 MySQL AB
|
||||
Copyright (C) 2004-2015 Alexey Kopytov <akopytov@gmail.com>
|
||||
Copyright (C) 2004-2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -51,25 +51,9 @@
|
||||
#define SB_THREAD_MUTEX_LOCK() pthread_mutex_lock(&sb_globals.exec_mutex)
|
||||
#define SB_THREAD_MUTEX_UNLOCK() pthread_mutex_unlock(&sb_globals.exec_mutex)
|
||||
|
||||
#define SB_MAX_RND 0x3fffffffu
|
||||
|
||||
/* Maximum number of elements in --report-checkpoints list */
|
||||
#define MAX_CHECKPOINTS 256
|
||||
|
||||
/* random() is not thread-safe on most platforms, use lrand48() if available */
|
||||
#ifdef HAVE_LRAND48
|
||||
# define sb_rnd() (lrand48() % SB_MAX_RND)
|
||||
# define sb_srnd(seed) srand48(seed)
|
||||
#else
|
||||
# define sb_rnd() (random() % SB_MAX_RND)
|
||||
# define sb_srnd(seed) srandom((unsigned int)seed)
|
||||
#endif
|
||||
#ifdef HAVE_DRAND48
|
||||
# define sb_rnd_double() drand48()
|
||||
#else
|
||||
# define sb_rnd_double() (((double) sb_rnd()) / SB_MAX_RND)
|
||||
#endif
|
||||
|
||||
/* Sysbench commands */
|
||||
typedef enum
|
||||
{
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
#include "sysbench.h"
|
||||
#include "crc32.h"
|
||||
#include "sb_percentile.h"
|
||||
#include "sb_rnd.h"
|
||||
|
||||
/* Lengths of the checksum and the offset fields in a block */
|
||||
#define FILE_CHECKSUM_LENGTH sizeof(int)
|
||||
@ -532,7 +533,6 @@ sb_request_t file_get_rnd_request(int thread_id)
|
||||
{
|
||||
sb_request_t sb_req;
|
||||
sb_file_request_t *file_req = &sb_req.u.file_request;
|
||||
unsigned int randnum;
|
||||
unsigned long long tmppos;
|
||||
int real_mode = test_mode;
|
||||
int mode = test_mode;
|
||||
@ -608,9 +608,7 @@ sb_request_t file_get_rnd_request(int thread_id)
|
||||
file_req->operation = FILE_OP_TYPE_READ;
|
||||
|
||||
retry:
|
||||
randnum = sb_rnd();
|
||||
|
||||
tmppos = (long long) ((double) randnum / SB_MAX_RND * total_size);
|
||||
tmppos = (long long) (sb_rnd_double() * total_size);
|
||||
tmppos = tmppos - (tmppos % (long long) file_block_size);
|
||||
file_req->file_id = (int) (tmppos / (long long) file_size);
|
||||
file_req->pos = (long long) (tmppos % (long long) file_size);
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#endif
|
||||
|
||||
#include "sysbench.h"
|
||||
#include "sb_rnd.h"
|
||||
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
# include <sys/ipc.h>
|
||||
@ -252,8 +253,7 @@ int memory_execute_request(sb_request_t *sb_req, int thread_id)
|
||||
log_msg_t msg;
|
||||
log_msg_oper_t op_msg;
|
||||
long i;
|
||||
unsigned int rand;
|
||||
|
||||
|
||||
/* Prepare log message */
|
||||
msg.type = LOG_MSG_TYPE_OPER;
|
||||
msg.data = &op_msg;
|
||||
@ -266,22 +266,19 @@ int memory_execute_request(sb_request_t *sb_req, int thread_id)
|
||||
|
||||
if (memory_access_rnd)
|
||||
{
|
||||
rand = sb_rnd();
|
||||
LOG_EVENT_START(msg, thread_id);
|
||||
switch (mem_req->type) {
|
||||
case SB_MEM_OP_WRITE:
|
||||
for (i = 0; i < memory_block_size; i++)
|
||||
{
|
||||
idx = (int)((double)rand / (double)SB_MAX_RND *
|
||||
(double)(memory_block_size / sizeof(int)));
|
||||
idx = (int)(sb_rnd_double() * (memory_block_size / sizeof(int)));
|
||||
buf[idx] = tmp;
|
||||
}
|
||||
break;
|
||||
case SB_MEM_OP_READ:
|
||||
for (i = 0; i < memory_block_size; i++)
|
||||
{
|
||||
idx = (int)((double)rand / (double)SB_MAX_RND *
|
||||
(double)(memory_block_size / sizeof(int)));
|
||||
idx = (int)(sb_rnd_double() * (memory_block_size / sizeof(int)));
|
||||
tmp = buf[idx];
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user