diff --git a/kernel/include/thread/Spinlock.h b/kernel/include/thread/Spinlock.h new file mode 100644 index 00000000..8678e69a --- /dev/null +++ b/kernel/include/thread/Spinlock.h @@ -0,0 +1,15 @@ +#pragma once +#include + +struct Spinlock +{ + public: + void acquire(); + void release(); + bool locked(); + + private: + volatile uint64_t m_lock = 0; +}; + +void lock(Spinlock& lock, void (*action)(void)); \ No newline at end of file diff --git a/kernel/src/thread/Spinlock.asm b/kernel/src/thread/Spinlock.asm new file mode 100644 index 00000000..9b520861 --- /dev/null +++ b/kernel/src/thread/Spinlock.asm @@ -0,0 +1,26 @@ +global spinlock_lock_acquire +spinlock_lock_acquire: + lock bts qword [rdi], 0 + jc .spin + ret +.spin: + pause + test qword [rdi], 1 + jnz .spin + jmp spinlock_lock_acquire + +global spinlock_lock_release +spinlock_lock_release: + mov qword [rdi], 0 + ret + +global spinlock_lock_is_locked +spinlock_lock_is_locked: + cmp qword [rdi], 0 + je .free +.locked: + mov rax, 1 + ret +.free: + mov rax, 0 + ret \ No newline at end of file diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp new file mode 100644 index 00000000..d2f819d4 --- /dev/null +++ b/kernel/src/thread/Spinlock.cpp @@ -0,0 +1,27 @@ +#include "thread/Spinlock.h" + +extern "C" void spinlock_lock_acquire(uint64_t* lock); +extern "C" void spinlock_lock_release(uint64_t* lock); +extern "C" int spinlock_lock_is_locked(uint64_t* lock); + +void Spinlock::acquire() +{ + spinlock_lock_acquire(&m_lock); +} + +void Spinlock::release() +{ + spinlock_lock_release(&m_lock); +} + +bool Spinlock::locked() +{ + return spinlock_lock_is_locked(&m_lock); +} + +void lock(Spinlock& lock, void (*action)(void)) +{ + lock.acquire(); + action(); + lock.release(); +} \ No newline at end of file