// // Copyright 2017 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Most users requiring mutual exclusion should use Mutex. // SpinLock is provided for use in two situations: // - for use by Abseil internal code that Mutex itself depends on // - for async signal safety (see below) // SpinLock with a base_internal::SchedulingMode::SCHEDULE_KERNEL_ONLY is async // signal safe. If a spinlock is used within a signal handler, all code that // acquires the lock must ensure that the signal cannot arrive while they are // holding the lock. Typically, this is done by blocking the signal. // // Threads waiting on a SpinLock may be woken in an arbitrary order. #ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_ #define ABSL_BASE_INTERNAL_SPINLOCK_H_ #include <atomic> #include <cstdint> #include "absl/base/attributes.h" #include "absl/base/const_init.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/low_level_scheduling.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/tsan_mutex_interface.h" #include "absl/base/thread_annotations.h" namespace tcmalloc { namespace tcmalloc_internal { class AllocationGuardSpinLockHolder; } // namespace tcmalloc_internal } // namespace tcmalloc namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock { … }; // Corresponding locker object that arranges to acquire a spinlock for // the duration of a C++ scope. // // TODO(b/176172494): Use only [[nodiscard]] when baseline is raised. // TODO(b/6695610): Remove forward declaration when #ifdef is no longer needed. #if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) class [[nodiscard]] SpinLockHolder; #else class ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI SpinLockHolder; #endif class ABSL_SCOPED_LOCKABLE SpinLockHolder { … }; // Register a hook for profiling support. // // The function pointer registered here will be called whenever a spinlock is // contended. The callback is given an opaque handle to the contended spinlock // and the number of wait cycles. This is thread-safe, but only a single // profiler can be registered. It is an error to call this function multiple // times with different arguments. void RegisterSpinLockProfiler(void (*fn)(const void* lock, int64_t wait_cycles)); //------------------------------------------------------------------------------ // Public interface ends here. //------------------------------------------------------------------------------ // If (result & kSpinLockHeld) == 0, then *this was successfully locked. // Otherwise, returns last observed value for lockword_. inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value, uint32_t wait_cycles) { … } } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_BASE_INTERNAL_SPINLOCK_H_