From c6d36c3e7c58a968cc0aaada0b5194cea8e85f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 5 Jun 2024 09:25:20 +0300 Subject: [PATCH] MDEV-34297 get_rnd_value() of ib_counter_t is unnecessarily complex The shared counter template ib_counter_t uses the function my_timer_cycles() as a source of pseudo-random numbers to pick a shard. On some platforms, my_timer_cycles() could return the constant value 0. get_rnd_value(): Remove. my_pseudo_random(): Implement as an alias of my_timer_cycles() or a wrapper for pthread_self(). Reviewed by: Vladislav Vaintroub --- include/my_rdtsc.h | 13 +++++++++++++ storage/innobase/include/sync0arr.inl | 2 +- storage/innobase/include/ut0counter.h | 26 +------------------------- 3 files changed, 15 insertions(+), 26 deletions(-) diff --git a/include/my_rdtsc.h b/include/my_rdtsc.h index e81015166d2..9729a47d4a5 100644 --- a/include/my_rdtsc.h +++ b/include/my_rdtsc.h @@ -177,10 +177,23 @@ static inline ulonglong my_timer_cycles(void) /* gethrtime may appear as either cycle or nanosecond counter */ return (ulonglong) gethrtime(); #else +# define MY_TIMER_CYCLES_IS_ZERO return 0; #endif } +#ifdef MY_TIMER_CYCLES_IS_ZERO +static inline size_t my_pseudo_random(void) +{ + /* In some platforms, pthread_self() might return a structure + that cannot be converted to a number like this. Possible alternatives + could include gettid() or sched_getcpu(). */ + return ((size_t) pthread_self()) / 16; +} +#else +# define my_pseudo_random my_timer_cycles +#endif + /** A nanosecond timer. @return the current timer value, in nanoseconds. diff --git a/storage/innobase/include/sync0arr.inl b/storage/innobase/include/sync0arr.inl index 962226b4934..e5eb126aea2 100644 --- a/storage/innobase/include/sync0arr.inl +++ b/storage/innobase/include/sync0arr.inl @@ -44,7 +44,7 @@ sync_array_get() return(sync_wait_array[0]); } - return(sync_wait_array[get_rnd_value() % sync_array_size]); + return(sync_wait_array[my_pseudo_random() % sync_array_size]); } /******************************************************************//** diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h index 646a5f367c2..0083627b91f 100644 --- a/storage/innobase/include/ut0counter.h +++ b/storage/innobase/include/ut0counter.h @@ -41,30 +41,6 @@ Created 2012/04/12 by Sunny Bains /** Default number of slots to use in ib_counter_t */ #define IB_N_SLOTS 64 -/** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles -as a random value. See the comments for my_timer_cycles() */ -/** @return result from RDTSC or similar functions. */ -static inline size_t -get_rnd_value() -{ - size_t c = static_cast(my_timer_cycles()); - - if (c != 0) { - return c; - } - - /* We may go here if my_timer_cycles() returns 0, - so we have to have the plan B for the counter. */ -#if !defined(_WIN32) - return (size_t)os_thread_get_curr_id(); -#else - LARGE_INTEGER cnt; - QueryPerformanceCounter(&cnt); - - return static_cast(cnt.QuadPart); -#endif /* !_WIN32 */ -} - /** Class for using fuzzy counters. The counter is multi-instance relaxed atomic so the results are not guaranteed to be 100% accurate but close enough. Creates an array of counters and separates each element by the @@ -80,7 +56,7 @@ struct ib_counter_t { /** Add to the counter. @param[in] n amount to be added */ - void add(Type n) { add(get_rnd_value(), n); } + void add(Type n) { add(my_pseudo_random(), n); } /** Add to the counter. @param[in] index a reasonably thread-unique identifier