From 337569b0ca5d6621d0dfb514f828b0d5c21555ec Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 1 Feb 2023 01:51:25 +0200 Subject: [PATCH] Kernel: Implement basic SpinLock --- kernel/Makefile | 1 + kernel/arch/i386/SpinLock.S | 17 +++++++++++++++++ kernel/arch/i386/make.config | 1 + kernel/arch/x86_64/SpinLock.S | 17 +++++++++++++++++ kernel/arch/x86_64/make.config | 3 ++- kernel/include/kernel/LockGuard.h | 30 ++++++++++++++++++++++++++++++ kernel/include/kernel/SpinLock.h | 22 ++++++++++++++++++++++ kernel/kernel/SpinLock.cpp | 19 +++++++++++++++++++ 8 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 kernel/arch/i386/SpinLock.S create mode 100644 kernel/arch/x86_64/SpinLock.S create mode 100644 kernel/include/kernel/LockGuard.h create mode 100644 kernel/include/kernel/SpinLock.h create mode 100644 kernel/kernel/SpinLock.cpp diff --git a/kernel/Makefile b/kernel/Makefile index 1f8d43dae8..85e03d962c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -45,6 +45,7 @@ kernel/PIT.o \ kernel/RTC.o \ kernel/Serial.o \ kernel/Shell.o \ +kernel/SpinLock.o \ kernel/SSP.o \ kernel/TTY.o \ kernel/VesaTerminalDriver.o \ diff --git a/kernel/arch/i386/SpinLock.S b/kernel/arch/i386/SpinLock.S new file mode 100644 index 0000000000..b1ffc3717a --- /dev/null +++ b/kernel/arch/i386/SpinLock.S @@ -0,0 +1,17 @@ +.global spinlock_lock_asm +spinlock_lock_asm: + lock; btsl $0, (%edi) + jnc .done +.retry: + pause + testl $1, (%edi) + jne .retry + lock; btsl $0, (%edi) + jc .retry +.done: + ret + +.global spinlock_unlock_asm +spinlock_unlock_asm: + movl $0, (%edi) + ret \ No newline at end of file diff --git a/kernel/arch/i386/make.config b/kernel/arch/i386/make.config index ff9eac993b..ab57708aa2 100644 --- a/kernel/arch/i386/make.config +++ b/kernel/arch/i386/make.config @@ -7,4 +7,5 @@ KERNEL_ARCH_OBJS= \ $(ARCHDIR)/boot.o \ $(ARCHDIR)/IDT.o \ $(ARCHDIR)/MMU.o \ +$(ARCHDIR)/SpinLock.o \ \ No newline at end of file diff --git a/kernel/arch/x86_64/SpinLock.S b/kernel/arch/x86_64/SpinLock.S new file mode 100644 index 0000000000..4ab72a3dd3 --- /dev/null +++ b/kernel/arch/x86_64/SpinLock.S @@ -0,0 +1,17 @@ +.global spinlock_lock_asm +spinlock_lock_asm: + lock; btsq $0, (%rdi) + jnc .done +.retry: + pause + testq $1, (%rdi) + jne .retry + lock; btsq $0, (%rdi) + jc .retry +.done: + ret + +.global spinlock_unlock_asm +spinlock_unlock_asm: + movq $0, (%rdi) + ret \ No newline at end of file diff --git a/kernel/arch/x86_64/make.config b/kernel/arch/x86_64/make.config index 890a3181d2..cd4839a95d 100644 --- a/kernel/arch/x86_64/make.config +++ b/kernel/arch/x86_64/make.config @@ -6,6 +6,7 @@ KERNEL_ARCH_LIBS= KERNEL_ARCH_OBJS= \ $(ARCHDIR)/boot.o \ $(ARCHDIR)/IDT.o \ -$(ARCHDIR)/MMU.o \ $(ARCHDIR)/interrupts.o \ +$(ARCHDIR)/MMU.o \ +$(ARCHDIR)/SpinLock.o \ \ No newline at end of file diff --git a/kernel/include/kernel/LockGuard.h b/kernel/include/kernel/LockGuard.h new file mode 100644 index 0000000000..32016c40f4 --- /dev/null +++ b/kernel/include/kernel/LockGuard.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace Kernel +{ + + template + class LockGuard + { + BAN_NON_COPYABLE(LockGuard); + BAN_NON_MOVABLE(LockGuard); + + public: + LockGuard(Lock& lock) + : m_lock(lock) + { + m_lock.lock(); + } + + ~LockGuard() + { + m_lock.unlock(); + } + + private: + Lock& m_lock; + }; + +} \ No newline at end of file diff --git a/kernel/include/kernel/SpinLock.h b/kernel/include/kernel/SpinLock.h new file mode 100644 index 0000000000..19c2c69551 --- /dev/null +++ b/kernel/include/kernel/SpinLock.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace Kernel +{ + + class SpinLock + { + BAN_NON_COPYABLE(SpinLock); + BAN_NON_MOVABLE(SpinLock); + + public: + SpinLock() = default; + void lock(); + void unlock(); + + private: + int m_lock = 0; + }; + +} \ No newline at end of file diff --git a/kernel/kernel/SpinLock.cpp b/kernel/kernel/SpinLock.cpp new file mode 100644 index 0000000000..c1057cc4d1 --- /dev/null +++ b/kernel/kernel/SpinLock.cpp @@ -0,0 +1,19 @@ +#include + +namespace Kernel +{ + + extern "C" void spinlock_lock_asm(int*); + extern "C" void spinlock_unlock_asm(int*); + + void SpinLock::lock() + { + spinlock_lock_asm(&m_lock); + } + + void SpinLock::unlock() + { + spinlock_unlock_asm(&m_lock); + } + +} \ No newline at end of file