From c35fe2ecfe1eba2911d155ad5ade41ca18a765ff Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 29 Sep 2026 10:43:50 +0200 Subject: kapi/interrupts: implement IRQ lock --- kapi/kapi/interrupts.hpp | 2 + kapi/kapi/interrupts/irq_lock.hpp | 108 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 kapi/kapi/interrupts/irq_lock.hpp (limited to 'kapi') diff --git a/kapi/kapi/interrupts.hpp b/kapi/kapi/interrupts.hpp index f9ff22f9..f5b992e2 100644 --- a/kapi/kapi/interrupts.hpp +++ b/kapi/kapi/interrupts.hpp @@ -1,5 +1,7 @@ #ifndef TEACHOS_KAPI_INTERRUPTS_HPP #define TEACHOS_KAPI_INTERRUPTS_HPP + +#include #include #include diff --git a/kapi/kapi/interrupts/irq_lock.hpp b/kapi/kapi/interrupts/irq_lock.hpp new file mode 100644 index 00000000..1b6f6987 --- /dev/null +++ b/kapi/kapi/interrupts/irq_lock.hpp @@ -0,0 +1,108 @@ +#ifndef TEACHOS_KAPI_INTERRUPTS_IRQ_LOCK_HPP +#define TEACHOS_KAPI_INTERRUPTS_IRQ_LOCK_HPP + +// IWYU pragma: private, include + +#include + +#include + +namespace kapi::interrupts +{ + + template + struct irq_lock; + + //! @name Kernel-defined API + //! @{ + + //! A lock to temporarily disable IRQs. + template<> + struct irq_lock + { + constexpr irq_lock() = default; + constexpr irq_lock(irq_lock const &) = delete; + constexpr irq_lock(irq_lock &&) = delete; + + constexpr auto operator=(irq_lock const &) = delete; + constexpr auto operator=(irq_lock &&) = delete; + + //! Save the current IRQ state and disable further IRQs. + auto lock() -> void + { + m_old_irq_state = enabled(); + enabled(false); + } + + //! Restore the previously saved IRQ state. + auto unlock() -> void + { + enabled(m_old_irq_state); + } + + //! Save the current IRQ state and disable further IRQs. + auto try_lock() -> bool + { + lock(); + return true; + } + + private: + bool m_old_irq_state{}; + }; + + //! A lock to temporarily disable IRQs while also acquiring a further lock. + template + struct irq_lock : irq_lock + { + using lockable_type = BasicLockable; + + explicit irq_lock(BasicLockable & lockable) + : m_lockable{lockable} + {} + + //! Save the current IRQ state, disable further IRQs, and lock this lock's lockable object. + auto lock() -> void + { + irq_lock<>::lock(); + m_lockable.lock(); + } + + //! Unlock this lock's lockable objects and restore the previously saved IRQ state. + auto unlock() -> void + { + m_lockable.unlock(); + irq_lock<>::unlock(); + } + + //! Save the current IRQ state, disable further IRQs, and attempt to lock this lock's lockable object. + //! + //! This function will restore the previous IRQ state if this lock's lockable object cannot be locked. + //! + //! @return @p true iff. this lock's lockable object could successfully be locked, @p false otherwise. + [[nodiscard]] auto try_lock() -> bool + requires(kstd::lockable) + { + irq_lock<>::lock(); + if (m_lockable.try_lock()) + { + return true; + } + irq_lock<>::unlock(); + return false; + } + + private: + lockable_type & m_lockable; + }; + + //! @} + + irq_lock() -> irq_lock; + + template + irq_lock(Lockable &) -> irq_lock; + +} // namespace kapi::interrupts + +#endif \ No newline at end of file -- cgit v1.2.3