diff options
Diffstat (limited to 'Kernel/Arch/x86/ScopedCritical.h')
-rw-r--r-- | Kernel/Arch/x86/ScopedCritical.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/Kernel/Arch/x86/ScopedCritical.h b/Kernel/Arch/x86/ScopedCritical.h new file mode 100644 index 0000000000..e6be3829a0 --- /dev/null +++ b/Kernel/Arch/x86/ScopedCritical.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Types.h> + +#include <Kernel/Arch/x86/Processor.h> + +namespace Kernel { + +class ScopedCritical { + AK_MAKE_NONCOPYABLE(ScopedCritical); + +public: + ScopedCritical() + { + enter(); + } + + ~ScopedCritical() + { + if (m_valid) + leave(); + } + + ScopedCritical(ScopedCritical&& from) + : m_prev_flags(exchange(from.m_prev_flags, 0)) + , m_valid(exchange(from.m_valid, false)) + { + } + + ScopedCritical& operator=(ScopedCritical&& from) + { + if (&from != this) { + m_prev_flags = exchange(from.m_prev_flags, 0); + m_valid = exchange(from.m_valid, false); + } + return *this; + } + + void leave() + { + VERIFY(m_valid); + m_valid = false; + Processor::current().leave_critical(m_prev_flags); + } + + void enter() + { + VERIFY(!m_valid); + m_valid = true; + Processor::current().enter_critical(m_prev_flags); + } + +private: + u32 m_prev_flags { 0 }; + bool m_valid { false }; +}; + +} |