From 8f4e15b78ed5aced307e55f4783fb9c945e3b10f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 28 Jun 2026 22:12:59 +0300 Subject: [PATCH] Kernel: Use spinlocks and disable interrupts with loopback interface This makes sure we don't get pre-empted after acquiring a descriptor but before finishing marking it ready --- kernel/include/kernel/Networking/Loopback.h | 2 +- kernel/kernel/Networking/Loopback.cpp | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/kernel/include/kernel/Networking/Loopback.h b/kernel/include/kernel/Networking/Loopback.h index dfdbe41c..eb6f0fdd 100644 --- a/kernel/include/kernel/Networking/Loopback.h +++ b/kernel/include/kernel/Networking/Loopback.h @@ -46,7 +46,7 @@ namespace Kernel }; private: - Mutex m_buffer_lock; + SpinLock m_buffer_lock; BAN::UniqPtr m_buffer; uint32_t m_buffer_tail { 0 }; diff --git a/kernel/kernel/Networking/Loopback.cpp b/kernel/kernel/Networking/Loopback.cpp index 4596fb26..c76f8a11 100644 --- a/kernel/kernel/Networking/Loopback.cpp +++ b/kernel/kernel/Networking/Loopback.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -56,10 +56,13 @@ namespace Kernel BAN::ErrorOr LoopbackInterface::send_raw_bytes(BAN::Span buffers) { + const auto interrupt_state = Processor::get_interrupt_state(); + Processor::set_interrupt_state(InterruptState::Disabled); + auto& descriptor = [&]() -> Descriptor& { - LockGuard _(m_buffer_lock); + SpinLockGuard guard(m_buffer_lock); for (;;) { auto& descriptor = m_descriptors[m_buffer_head]; @@ -69,7 +72,8 @@ namespace Kernel descriptor.state = 1; return descriptor; } - m_thread_blocker.block_indefinite(&m_buffer_lock); + SpinLockGuardAsMutex smutex(guard); + m_thread_blocker.block_indefinite(&smutex); } }(); @@ -81,17 +85,18 @@ namespace Kernel packet_size += buffer.size(); } - LockGuard _(m_buffer_lock); + m_buffer_lock.lock(); descriptor.size = packet_size; descriptor.state = 2; m_thread_blocker.unblock(); + m_buffer_lock.unlock(interrupt_state); return {}; } void LoopbackInterface::receive_thread() { - LockGuard _(m_buffer_lock); + SpinLockGuard guard(m_buffer_lock); while (!m_thread_should_die) { @@ -102,7 +107,7 @@ namespace Kernel break; m_buffer_tail = (m_buffer_tail + 1) % buffer_count; - m_buffer_lock.unlock(); + m_buffer_lock.unlock(InterruptState::Enabled); NetworkManager::get().on_receive(*this, { descriptor.addr, @@ -116,7 +121,8 @@ namespace Kernel m_thread_blocker.unblock(); } - m_thread_blocker.block_indefinite(&m_buffer_lock); + SpinLockGuardAsMutex smutex(guard); + m_thread_blocker.block_indefinite(&smutex); } m_thread_is_dead = true;