Commit 133360ca by Chris Kennelly Committed by Copybara-Service

Add internal interface to determine if a SpinLock is cooperative.

Some use cases of SpinLock need to verify that it is configured for
non-cooperative scheduling.

PiperOrigin-RevId: 575278400
Change-Id: Ic49f57a989a3f7f67e346a1ec545f4cd5b94f849
parent 3bc08b81
...@@ -41,6 +41,14 @@ ...@@ -41,6 +41,14 @@
#include "absl/base/internal/tsan_mutex_interface.h" #include "absl/base/internal/tsan_mutex_interface.h"
#include "absl/base/thread_annotations.h" #include "absl/base/thread_annotations.h"
namespace tcmalloc {
namespace tcmalloc_internal {
class AllocationGuardSpinLockHolder;
} // namespace tcmalloc_internal
} // namespace tcmalloc
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
namespace base_internal { namespace base_internal {
...@@ -137,6 +145,7 @@ class ABSL_LOCKABLE SpinLock { ...@@ -137,6 +145,7 @@ class ABSL_LOCKABLE SpinLock {
// Provide access to protected method above. Use for testing only. // Provide access to protected method above. Use for testing only.
friend struct SpinLockTest; friend struct SpinLockTest;
friend class tcmalloc::tcmalloc_internal::AllocationGuardSpinLockHolder;
private: private:
// lockword_ is used to store the following: // lockword_ is used to store the following:
...@@ -171,6 +180,10 @@ class ABSL_LOCKABLE SpinLock { ...@@ -171,6 +180,10 @@ class ABSL_LOCKABLE SpinLock {
return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL; return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
} }
bool IsCooperative() const {
return lockword_.load(std::memory_order_relaxed) & kSpinLockCooperative;
}
uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles); uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
void SlowLock() ABSL_ATTRIBUTE_COLD; void SlowLock() ABSL_ATTRIBUTE_COLD;
void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD; void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
......
...@@ -51,6 +51,8 @@ struct SpinLockTest { ...@@ -51,6 +51,8 @@ struct SpinLockTest {
static int64_t DecodeWaitCycles(uint32_t lock_value) { static int64_t DecodeWaitCycles(uint32_t lock_value) {
return SpinLock::DecodeWaitCycles(lock_value); return SpinLock::DecodeWaitCycles(lock_value);
} }
static bool IsCooperative(const SpinLock& l) { return l.IsCooperative(); }
}; };
namespace { namespace {
...@@ -266,6 +268,17 @@ TEST(SpinLockWithThreads, DoesNotDeadlock) { ...@@ -266,6 +268,17 @@ TEST(SpinLockWithThreads, DoesNotDeadlock) {
base_internal::NumCPUs() * 2); base_internal::NumCPUs() * 2);
} }
TEST(SpinLockTest, IsCooperative) {
SpinLock default_constructor;
EXPECT_TRUE(SpinLockTest::IsCooperative(default_constructor));
SpinLock cooperative(base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
EXPECT_TRUE(SpinLockTest::IsCooperative(cooperative));
SpinLock kernel_only(base_internal::SCHEDULE_KERNEL_ONLY);
EXPECT_FALSE(SpinLockTest::IsCooperative(kernel_only));
}
} // namespace } // namespace
} // namespace base_internal } // namespace base_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment