diff options
-rw-r--r-- | absl/base/internal/spinlock.cc | 37 | ||||
-rw-r--r-- | absl/base/internal/spinlock.h | 19 | ||||
-rw-r--r-- | absl/base/macros.h | 30 | ||||
-rw-r--r-- | absl/flags/flag.h | 1 | ||||
-rw-r--r-- | absl/hash/hash_test.cc | 2 | ||||
-rw-r--r-- | absl/synchronization/internal/mutex_nonprod.inc | 20 |
6 files changed, 14 insertions, 95 deletions
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc index 7cac72f97f28..a7d44f3eb091 100644 --- a/absl/base/internal/spinlock.cc +++ b/absl/base/internal/spinlock.cc @@ -79,29 +79,6 @@ SpinLock::SpinLock(base_internal::SchedulingMode mode) ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); } -SpinLock::SpinLock(base_internal::LinkerInitialized, - base_internal::SchedulingMode mode) { - ABSL_TSAN_MUTEX_CREATE(this, 0); - if (IsCooperative(mode)) { - InitLinkerInitializedAndCooperative(); - } - // Otherwise, lockword_ is already initialized. -} - -// Static (linker initialized) spinlocks always start life as functional -// non-cooperative locks. When their static constructor does run, it will call -// this initializer to augment the lockword with the cooperative bit. By -// actually taking the lock when we do this we avoid the need for an atomic -// operation in the regular unlock path. -// -// SlowLock() must be careful to re-test for this bit so that any outstanding -// waiters may be upgraded to cooperative status. -void SpinLock::InitLinkerInitializedAndCooperative() { - Lock(); - lockword_.fetch_or(kSpinLockCooperative, std::memory_order_relaxed); - Unlock(); -} - // Monitor the lock to see if its value changes within some time period // (adaptive_spin_count loop iterations). The last value read from the lock // is returned from the method. @@ -128,6 +105,14 @@ void SpinLock::SlowLock() { if ((lock_value & kSpinLockHeld) == 0) { return; } + + base_internal::SchedulingMode scheduling_mode; + if ((lock_value & kSpinLockCooperative) != 0) { + scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; + } else { + scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY; + } + // The lock was not obtained initially, so this thread needs to wait for // it. Record the current timestamp in the local variable wait_start_time // so the total wait time can be stored in the lockword once this thread @@ -158,12 +143,6 @@ void SpinLock::SlowLock() { } } - base_internal::SchedulingMode scheduling_mode; - if ((lock_value & kSpinLockCooperative) != 0) { - scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; - } else { - scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY; - } // SpinLockDelay() calls into fiber scheduler, we need to see // synchronization there to avoid false positives. ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0); diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index 2b08a2d6e2f1..2222398b16b4 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h @@ -56,27 +56,9 @@ class ABSL_LOCKABLE SpinLock { ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); } - // Special constructor for use with static SpinLock objects. E.g., - // - // static SpinLock lock(base_internal::kLinkerInitialized); - // - // When initialized using this constructor, we depend on the fact - // that the linker has already initialized the memory appropriately. The lock - // is initialized in non-cooperative mode. - // - // A SpinLock constructed like this can be freely used from global - // initializers without worrying about the order in which global - // initializers run. - explicit SpinLock(base_internal::LinkerInitialized) { - // Does nothing; lockword_ is already initialized - ABSL_TSAN_MUTEX_CREATE(this, 0); - } - // Constructors that allow non-cooperative spinlocks to be created for use // inside thread schedulers. Normal clients should not use these. explicit SpinLock(base_internal::SchedulingMode mode); - SpinLock(base_internal::LinkerInitialized, - base_internal::SchedulingMode mode); // Constructor for global SpinLock instances. See absl/base/const_init.h. constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode) @@ -168,7 +150,6 @@ class ABSL_LOCKABLE SpinLock { } uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles); - void InitLinkerInitializedAndCooperative(); void SlowLock() ABSL_ATTRIBUTE_COLD; void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD; uint32_t SpinLoop(); diff --git a/absl/base/macros.h b/absl/base/macros.h index 2c4e3570cd55..ea1da65ba272 100644 --- a/absl/base/macros.h +++ b/absl/base/macros.h @@ -55,36 +55,6 @@ auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; ABSL_NAMESPACE_END } // namespace absl -// kLinkerInitialized -// -// An enum used only as a constructor argument to indicate that a variable has -// static storage duration, and that the constructor should do nothing to its -// state. Use of this macro indicates to the reader that it is legal to -// declare a static instance of the class, provided the constructor is given -// the absl::base_internal::kLinkerInitialized argument. -// -// Normally, it is unsafe to declare a static variable that has a constructor or -// a destructor because invocation order is undefined. However, if the type can -// be zero-initialized (which the loader does for static variables) into a valid -// state and the type's destructor does not affect storage, then a constructor -// for static initialization can be declared. -// -// Example: -// // Declaration -// explicit MyClass(absl::base_internal:LinkerInitialized x) {} -// -// // Invocation -// static MyClass my_global(absl::base_internal::kLinkerInitialized); -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace base_internal { -enum LinkerInitialized { - kLinkerInitialized = 0, -}; -} // namespace base_internal -ABSL_NAMESPACE_END -} // namespace absl - // ABSL_FALLTHROUGH_INTENDED // // Annotates implicit fall-through between switch labels, allowing a case to diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 8dd1b9be7af8..ca7d581fce71 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -41,6 +41,7 @@ #include "absl/flags/internal/flag.h" #include "absl/flags/internal/registry.h" #include "absl/flags/marshalling.h" +#include "absl/strings/string_view.h" namespace absl { ABSL_NAMESPACE_BEGIN diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index 5e6a8b188b40..b38d46d47dd3 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc @@ -407,7 +407,7 @@ using IntSequenceTypes = INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes); // Private type that only supports AbslHashValue to make sure our chosen hash -// implentation is recursive within absl::Hash. +// implementation is recursive within absl::Hash. // It uses std::abs() on the value to provide different bitwise representations // of the same logical value. struct Private { diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc index a1502e727da4..d83bc8a94c75 100644 --- a/absl/synchronization/internal/mutex_nonprod.inc +++ b/absl/synchronization/internal/mutex_nonprod.inc @@ -209,31 +209,22 @@ class SynchronizationStorage { // Instances allocated on the heap or on the stack should use the default // constructor. SynchronizationStorage() - : is_dynamic_(true), once_() {} - - // Instances allocated in static storage (not on the heap, not on the - // stack) should use this constructor. - explicit SynchronizationStorage(base_internal::LinkerInitialized) {} + : destruct_(true), once_() {} constexpr explicit SynchronizationStorage(absl::ConstInitType) - : is_dynamic_(false), once_(), space_{{0}} {} + : destruct_(false), once_(), space_{{0}} {} SynchronizationStorage(SynchronizationStorage&) = delete; SynchronizationStorage& operator=(SynchronizationStorage&) = delete; ~SynchronizationStorage() { - if (is_dynamic_) { + if (destruct_) { get()->~T(); } } // Retrieve the object in storage. This is fast and thread safe, but does // incur the cost of absl::call_once(). - // - // For instances in static storage constructed with the - // LinkerInitialized constructor, may be called at any time without - // regard for order of dynamic initialization or destruction of objects - // in static storage. See the class comment for caveats. T* get() { absl::call_once(once_, SynchronizationStorage::Construct, this); return reinterpret_cast<T*>(&space_); @@ -245,10 +236,7 @@ class SynchronizationStorage { } // When true, T's destructor is run when this is destructed. - // - // The LinkerInitialized constructor assumes this value will be set - // false by static initialization. - bool is_dynamic_; + const bool destruct_; absl::once_flag once_; |