177 lines
4.7 KiB
Plaintext
177 lines
4.7 KiB
Plaintext
/*****************************************************************************
|
|
|
|
Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License, version 2.0, as published by the
|
|
Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including but not
|
|
limited to OpenSSL) that is licensed under separate terms, as designated in a
|
|
particular file or component or in included license documentation. The authors
|
|
of MySQL hereby grant you an additional permission to link the program and
|
|
your derivative works with the separately licensed software that they have
|
|
included with MySQL.
|
|
|
|
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, version 2.0,
|
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/** @file include/ut0ut.ic
|
|
Various utilities
|
|
|
|
Created 5/30/1994 Heikki Tuuri
|
|
*******************************************************************/
|
|
|
|
#include <algorithm>
|
|
|
|
#include "os0thread.h"
|
|
#include "ut0dbg.h"
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/** Calculate the minimum of two pairs.
|
|
@param[out] min_hi MSB of the minimum pair
|
|
@param[out] min_lo LSB of the minimum pair
|
|
@param[in] a_hi MSB of the first pair
|
|
@param[in] a_lo LSB of the first pair
|
|
@param[in] b_hi MSB of the second pair
|
|
@param[in] b_lo LSB of the second pair */
|
|
UNIV_INLINE
|
|
void ut_pair_min(ulint *min_hi, ulint *min_lo, ulint a_hi, ulint a_lo,
|
|
ulint b_hi, ulint b_lo) {
|
|
if (a_hi == b_hi) {
|
|
*min_hi = a_hi;
|
|
*min_lo = std::min(a_lo, b_lo);
|
|
} else if (a_hi < b_hi) {
|
|
*min_hi = a_hi;
|
|
*min_lo = a_lo;
|
|
} else {
|
|
*min_hi = b_hi;
|
|
*min_lo = b_lo;
|
|
}
|
|
}
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/** Compares two ulints.
|
|
@return 1 if a > b, 0 if a == b, -1 if a < b */
|
|
UNIV_INLINE
|
|
int ut_ulint_cmp(ulint a, /*!< in: ulint */
|
|
ulint b) /*!< in: ulint */
|
|
{
|
|
if (a < b) {
|
|
return (-1);
|
|
} else if (a == b) {
|
|
return (0);
|
|
} else {
|
|
return (1);
|
|
}
|
|
}
|
|
|
|
/** Compare two pairs of integers.
|
|
@param[in] a_h more significant part of first pair
|
|
@param[in] a_l less significant part of first pair
|
|
@param[in] b_h more significant part of second pair
|
|
@param[in] b_l less significant part of second pair
|
|
@return comparison result of (a_h,a_l) and (b_h,b_l)
|
|
@retval -1 if (a_h,a_l) is less than (b_h,b_l)
|
|
@retval 0 if (a_h,a_l) is equal to (b_h,b_l)
|
|
@retval 1 if (a_h,a_l) is greater than (b_h,b_l) */
|
|
UNIV_INLINE
|
|
int ut_pair_cmp(ulint a_h, ulint a_l, ulint b_h, ulint b_l) {
|
|
if (a_h < b_h) {
|
|
return (-1);
|
|
}
|
|
if (a_h > b_h) {
|
|
return (1);
|
|
}
|
|
return (ut_ulint_cmp(a_l, b_l));
|
|
}
|
|
|
|
/** Calculates fast the 2-logarithm of a number, rounded upward to an
|
|
integer.
|
|
@return logarithm in the base 2, rounded upward */
|
|
UNIV_INLINE
|
|
ulint ut_2_log(ulint n) /*!< in: number != 0 */
|
|
{
|
|
ulint res;
|
|
|
|
res = 0;
|
|
|
|
ut_ad(n > 0);
|
|
|
|
n = n - 1;
|
|
|
|
for (;;) {
|
|
n = n / 2;
|
|
|
|
if (n == 0) {
|
|
break;
|
|
}
|
|
|
|
res++;
|
|
}
|
|
|
|
return (res + 1);
|
|
}
|
|
|
|
/** Calculates 2 to power n.
|
|
@param[in] n power of 2
|
|
@return 2 to power n */
|
|
UNIV_INLINE
|
|
uint32_t ut_2_exp(uint32_t n) { return (1 << n); }
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/** Waits in loop until given condition is satisfied. It starts waiting
|
|
using spin loop with pauses and after reaching maximum iterations, it
|
|
switches to loop with sleeps. The sleep time is multiplied by two after
|
|
every k-sleeps, until it reaches 100ms (starting at provided value).
|
|
@param[in] spins_limit maximum iterations without sleep
|
|
@param[in] sleep initial sleep time in microseconds
|
|
@param[in] condition returns true when condition is
|
|
satisfied
|
|
@return number of loops with sleep that have been used */
|
|
template <typename Condition>
|
|
inline static Wait_stats ut_wait_for(uint64_t spins_limit, uint64_t sleep,
|
|
Condition condition = {}) {
|
|
uint64_t sleeps = 0, spins = 0;
|
|
#ifdef _WIN32
|
|
uint64_t next_level = 64;
|
|
#else
|
|
uint64_t next_level = 4;
|
|
#endif
|
|
|
|
while (!condition(spins == spins_limit)) {
|
|
if (spins == spins_limit) {
|
|
++sleeps;
|
|
|
|
if (sleeps == next_level) {
|
|
sleep = std::min(sleep * 2, uint64_t{100 * 1000});
|
|
|
|
#ifdef _WIN32
|
|
next_level += 64;
|
|
#else
|
|
next_level += 4;
|
|
#endif
|
|
}
|
|
|
|
os_thread_sleep(sleep);
|
|
|
|
} else {
|
|
++spins;
|
|
|
|
UT_RELAX_CPU();
|
|
}
|
|
}
|
|
|
|
return (Wait_stats{sleeps});
|
|
}
|
|
|
|
#endif /* !UNIV_HOTBACKUP */
|