diff options
author | Abseil Team <absl-team@google.com> | 2021-01-04 20:13:45 -0800 |
---|---|---|
committer | Derek Mauro <dmauro@google.com> | 2021-01-05 13:49:24 -0500 |
commit | bb7fb2c7bf6ac33b243a880edfbdb21ad2b81281 (patch) | |
tree | 29a123a3c7601801573d367e7289101381e5e903 | |
parent | 384af0e9141283172e2bff3210dae79fb7130d9c (diff) |
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
-rw-r--r-- | absl/synchronization/mutex.cc | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 9e01393c..82b631af 100644 --- a/absl/synchronization/mutex.cc +++ b/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++; |