summaryrefslogtreecommitdiff
path: root/Kernel/Locking
diff options
context:
space:
mode:
authorJean-Baptiste Boric <jblbeurope@gmail.com>2021-07-24 16:42:39 +0200
committerAndreas Kling <kling@serenityos.org>2021-08-07 11:48:00 +0200
commit019ad8a507aaed2475aa179da3ffeecbf57feac7 (patch)
tree485a7e3378cfd6b80fc33cd70385608569011f9e /Kernel/Locking
parent3d684316c2d2361730e1f546971a94107a1f13ea (diff)
downloadserenity-019ad8a507aaed2475aa179da3ffeecbf57feac7.zip
Kernel: Introduce spin-locked contended and locked resource concepts
Diffstat (limited to 'Kernel/Locking')
-rw-r--r--Kernel/Locking/SpinLockProtectedValue.h64
-rw-r--r--Kernel/Locking/SpinLockResource.h53
2 files changed, 117 insertions, 0 deletions
diff --git a/Kernel/Locking/SpinLockProtectedValue.h b/Kernel/Locking/SpinLockProtectedValue.h
new file mode 100644
index 0000000000..e4af19d8a3
--- /dev/null
+++ b/Kernel/Locking/SpinLockProtectedValue.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/Locking/SpinLockResource.h>
+
+namespace Kernel {
+
+template<typename T>
+class SpinLockProtectedValue : private T
+ , public SpinLockContendedResource {
+ AK_MAKE_NONCOPYABLE(SpinLockProtectedValue);
+ AK_MAKE_NONMOVABLE(SpinLockProtectedValue);
+
+protected:
+ using LockedConst = SpinLockLockedResource<T const>;
+ using LockedMutable = SpinLockLockedResource<T>;
+
+ LockedConst lock_const() const { return LockedConst(static_cast<T const*>(this), this->SpinLockContendedResource::m_spinlock); }
+ LockedMutable lock_mutable() { return LockedMutable(static_cast<T*>(this), this->SpinLockContendedResource::m_spinlock); }
+
+public:
+ using T::T;
+
+ SpinLockProtectedValue() = default;
+
+ template<typename Callback>
+ decltype(auto) with(Callback callback) const
+ {
+ auto lock = lock_const();
+ return callback(*lock);
+ }
+
+ template<typename Callback>
+ decltype(auto) with(Callback callback)
+ {
+ auto lock = lock_mutable();
+ return callback(*lock);
+ }
+
+ template<typename Callback>
+ void for_each_const(Callback callback) const
+ {
+ with([&](const auto& value) {
+ for (auto& item : value)
+ callback(item);
+ });
+ }
+
+ template<typename Callback>
+ void for_each(Callback callback)
+ {
+ with([&](auto& value) {
+ for (auto& item : value)
+ callback(item);
+ });
+ }
+};
+
+}
diff --git a/Kernel/Locking/SpinLockResource.h b/Kernel/Locking/SpinLockResource.h
new file mode 100644
index 0000000000..f8d23b5da0
--- /dev/null
+++ b/Kernel/Locking/SpinLockResource.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2021, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/StdLibExtras.h>
+#include <Kernel/Locking/SpinLock.h>
+
+namespace Kernel {
+
+template<typename T>
+class SpinLockLockedResource {
+ AK_MAKE_NONCOPYABLE(SpinLockLockedResource);
+
+public:
+ SpinLockLockedResource(T* value, RecursiveSpinLock& spinlock)
+ : m_value(value)
+ , m_scoped_spinlock(spinlock)
+ {
+ }
+
+ ALWAYS_INLINE T const* operator->() const { return m_value; }
+ ALWAYS_INLINE T const& operator*() const { return *m_value; }
+
+ ALWAYS_INLINE T* operator->() { return m_value; }
+ ALWAYS_INLINE T& operator*() { return *m_value; }
+
+ ALWAYS_INLINE T const* get() const { return m_value; }
+ ALWAYS_INLINE T* get() { return m_value; }
+
+private:
+ T* m_value;
+ ScopedSpinLock<RecursiveSpinLock> m_scoped_spinlock;
+};
+
+class SpinLockContendedResource {
+ template<typename>
+ friend class SpinLockLockedResource;
+
+ AK_MAKE_NONCOPYABLE(SpinLockContendedResource);
+ AK_MAKE_NONMOVABLE(SpinLockContendedResource);
+
+public:
+ SpinLockContendedResource() = default;
+
+protected:
+ mutable RecursiveSpinLock m_spinlock;
+};
+
+}