summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/common/Spinlock.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/common/Spinlock.h')
-rw-r--r--gfx/angle/checkout/src/common/Spinlock.h71
1 files changed, 71 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/common/Spinlock.h b/gfx/angle/checkout/src/common/Spinlock.h
new file mode 100644
index 0000000000..494da0943e
--- /dev/null
+++ b/gfx/angle/checkout/src/common/Spinlock.h
@@ -0,0 +1,71 @@
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Spinlock.h:
+// Spinlock is a lock that loops actively until it gets the resource.
+// Only use it when the lock will be granted in reasonably short time.
+
+#ifndef COMMON_SPINLOCK_H_
+#define COMMON_SPINLOCK_H_
+
+#include <atomic>
+
+// TODO(jplate) Add pause for ARM, http://anglebug.com:6067
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+extern "C" void _mm_pause();
+# pragma intrinsic(_mm_pause)
+# define ANGLE_SMT_PAUSE() _mm_pause()
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# define ANGLE_SMT_PAUSE() __asm__ __volatile__("pause;")
+#else
+# define ANGLE_SMT_PAUSE() static_cast<void>(0)
+#endif
+
+namespace angle
+{
+
+class Spinlock
+{
+ public:
+ Spinlock() noexcept;
+
+ bool try_lock() noexcept;
+ void lock() noexcept;
+ void unlock() noexcept;
+
+ private:
+ std::atomic_bool mLock;
+};
+
+inline Spinlock::Spinlock() noexcept : mLock(false) {}
+
+inline bool Spinlock::try_lock() noexcept
+{
+ // Relaxed check first to prevent unnecessary cache misses.
+ return !mLock.load(std::memory_order_relaxed) &&
+ !mLock.exchange(true, std::memory_order_acquire);
+}
+
+inline void Spinlock::lock() noexcept
+{
+ while (mLock.exchange(true, std::memory_order_acquire))
+ {
+ // Relaxed wait to prevent unnecessary cache misses.
+ while (mLock.load(std::memory_order_relaxed))
+ {
+ // Optimization for simultaneous multithreading.
+ ANGLE_SMT_PAUSE();
+ }
+ }
+}
+
+inline void Spinlock::unlock() noexcept
+{
+ mLock.store(false, std::memory_order_release);
+}
+
+} // namespace angle
+
+#endif // COMMON_SPINLOCK_H_