Export of internal Abseil changes

--
4e789887c5e2d3e531499c6c761a10bf60272969 by Abseil Team <absl-team@google.com>:

Remove a branch from MutexDelay.

Store the mutex sleep limit in the static so that it's not calculated every
time. Remove num_cpus from the static data because it's not used anymore. The
size of static data is 2 QWORDS after this change.

PiperOrigin-RevId: 350069849
GitOrigin-RevId: 4e789887c5e2d3e531499c6c761a10bf60272969
Change-Id: Ic374c63c8a7011b5f8931459e44a7841d4b2a2e6
pull/772/merge
Abseil Team 4 years ago committed by Derek Mauro
parent 384af0e914
commit bb7fb2c7bf
  1. 41
      absl/synchronization/mutex.cc

@ -124,35 +124,44 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) {
symbolizer.Store(fn);
}
namespace {
// Represents the strategy for spin and yield.
// See the comment in GetMutexGlobals() for more information.
enum DelayMode { AGGRESSIVE, GENTLE };
struct ABSL_CACHELINE_ALIGNED MutexGlobals {
absl::once_flag once;
int num_cpus = 0;
int spinloop_iterations = 0;
int32_t mutex_sleep_limit[2] = {};
};
static const MutexGlobals& GetMutexGlobals() {
const MutexGlobals &GetMutexGlobals() {
ABSL_CONST_INIT static MutexGlobals data;
absl::base_internal::LowLevelCallOnce(&data.once, [&]() {
data.num_cpus = absl::base_internal::NumCPUs();
data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0;
const int num_cpus = absl::base_internal::NumCPUs();
data.spinloop_iterations = num_cpus > 1 ? 1500 : 0;
// If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
// aggressive then spin many times before yielding. If the mode is
// gentle then spin only a few times before yielding. Aggressive spinning
// is used to ensure that an Unlock() call, which must get the spin lock
// for any thread to make progress gets it without undue delay.
if (num_cpus > 1) {
data.mutex_sleep_limit[AGGRESSIVE] = 5000;
data.mutex_sleep_limit[GENTLE] = 250;
} else {
data.mutex_sleep_limit[AGGRESSIVE] = 0;
data.mutex_sleep_limit[GENTLE] = 0;
}
});
return data;
}
// Spinlock delay on iteration c. Returns new c.
namespace {
enum DelayMode { AGGRESSIVE, GENTLE };
};
} // namespace
namespace synchronization_internal {
// Returns the Mutex delay on iteration `c` depending on the given `mode`.
// The returned value should be used as `c` for the next call to `MutexDelay`.
int MutexDelay(int32_t c, int mode) {
// If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
// aggressive then spin many times before yielding. If the mode is
// gentle then spin only a few times before yielding. Aggressive spinning is
// used to ensure that an Unlock() call, which must get the spin lock for
// any thread to make progress gets it without undue delay.
const int32_t limit =
GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0;
const int32_t limit = GetMutexGlobals().mutex_sleep_limit[mode];
if (c < limit) {
// Spin.
c++;

Loading…
Cancel
Save