diff --git a/README.md b/README.md index f0546bc..e973f44 100644 --- a/README.md +++ b/README.md @@ -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 | diff --git a/configure.ac b/configure.ac index 8d79041..79afa5d 100644 --- a/configure.ac +++ b/configure.ac @@ -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 \ diff --git a/m4/ax_tls.m4 b/m4/ax_tls.m4 new file mode 100644 index 0000000..809b761 --- /dev/null +++ b/m4/ax_tls.m4 @@ -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 +# Copyright (c) 2010 Diego Elio Petteno` +# +# 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 . +# +# 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 + 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])]) +]) diff --git a/sysbench/Makefile.am b/sysbench/Makefile.am index 6e30194..73c2d10 100644 --- a/sysbench/Makefile.am +++ b/sysbench/Makefile.am @@ -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 \ diff --git a/sysbench/sb_rnd.c b/sysbench/sb_rnd.c new file mode 100644 index 0000000..f534c81 --- /dev/null +++ b/sysbench/sb_rnd.c @@ -0,0 +1,27 @@ +/* + Copyright (C) 2016 Alexey Kopytov + + 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 diff --git a/sysbench/sb_rnd.h b/sysbench/sb_rnd.h new file mode 100644 index 0000000..7ae1dee --- /dev/null +++ b/sysbench/sb_rnd.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2016 Alexey Kopytov + + 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 + +/* 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 */ diff --git a/sysbench/sb_thread.c b/sysbench/sb_thread.c new file mode 100644 index 0000000..d089a08 --- /dev/null +++ b/sysbench/sb_thread.c @@ -0,0 +1,56 @@ +/* + Copyright (C) 2016 Alexey Kopytov + + 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 +#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); +} diff --git a/sysbench/sb_thread.h b/sysbench/sb_thread.h new file mode 100644 index 0000000..e8e247d --- /dev/null +++ b/sysbench/sb_thread.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2016 Alexey Kopytov + + 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 +#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 */ diff --git a/sysbench/sb_win.c b/sysbench/sb_win.c index 8324d41..101bbec 100644 --- a/sysbench/sb_win.c +++ b/sysbench/sb_win.c @@ -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(). diff --git a/sysbench/sb_win.h b/sysbench/sb_win.h index c6aec92..85c6c02 100644 --- a/sysbench/sb_win.h +++ b/sysbench/sb_win.h @@ -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(); diff --git a/sysbench/scripting/script_lua.c b/sysbench/scripting/script_lua.c index 31a1aab..fdaa4f4 100644 --- a/sysbench/scripting/script_lua.c +++ b/sysbench/scripting/script_lua.c @@ -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" diff --git a/sysbench/sysbench.c b/sysbench/sysbench.c index c008037..6fa3adc 100644 --- a/sysbench/sysbench.c +++ b/sysbench/sysbench.c @@ -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")) diff --git a/sysbench/sysbench.h b/sysbench/sysbench.h index 0d165aa..a26a3f0 100644 --- a/sysbench/sysbench.h +++ b/sysbench/sysbench.h @@ -1,5 +1,5 @@ /* Copyright (C) 2004 MySQL AB - Copyright (C) 2004-2015 Alexey Kopytov + Copyright (C) 2004-2016 Alexey Kopytov 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 { diff --git a/sysbench/tests/fileio/sb_fileio.c b/sysbench/tests/fileio/sb_fileio.c index a7a1a57..4fe5857 100644 --- a/sysbench/tests/fileio/sb_fileio.c +++ b/sysbench/tests/fileio/sb_fileio.c @@ -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); diff --git a/sysbench/tests/memory/sb_memory.c b/sysbench/tests/memory/sb_memory.c index eace821..50f042c 100644 --- a/sysbench/tests/memory/sb_memory.c +++ b/sysbench/tests/memory/sb_memory.c @@ -24,6 +24,7 @@ #endif #include "sysbench.h" +#include "sb_rnd.h" #ifdef HAVE_SYS_IPC_H # include @@ -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;