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
This commit is contained in:
2026-06-28 22:12:59 +03:00
parent 17e6e53948
commit 8f4e15b78e
2 changed files with 14 additions and 8 deletions

View File

@@ -46,7 +46,7 @@ namespace Kernel
}; };
private: private:
Mutex m_buffer_lock; SpinLock m_buffer_lock;
BAN::UniqPtr<VirtualRange> m_buffer; BAN::UniqPtr<VirtualRange> m_buffer;
uint32_t m_buffer_tail { 0 }; uint32_t m_buffer_tail { 0 };

View File

@@ -1,4 +1,4 @@
#include <kernel/Lock/LockGuard.h> #include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Networking/Loopback.h> #include <kernel/Networking/Loopback.h>
#include <kernel/Networking/NetworkManager.h> #include <kernel/Networking/NetworkManager.h>
@@ -56,10 +56,13 @@ namespace Kernel
BAN::ErrorOr<void> LoopbackInterface::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers) BAN::ErrorOr<void> LoopbackInterface::send_raw_bytes(BAN::Span<const BAN::ConstByteSpan> buffers)
{ {
const auto interrupt_state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
auto& descriptor = auto& descriptor =
[&]() -> Descriptor& [&]() -> Descriptor&
{ {
LockGuard _(m_buffer_lock); SpinLockGuard guard(m_buffer_lock);
for (;;) for (;;)
{ {
auto& descriptor = m_descriptors[m_buffer_head]; auto& descriptor = m_descriptors[m_buffer_head];
@@ -69,7 +72,8 @@ namespace Kernel
descriptor.state = 1; descriptor.state = 1;
return descriptor; 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(); packet_size += buffer.size();
} }
LockGuard _(m_buffer_lock); m_buffer_lock.lock();
descriptor.size = packet_size; descriptor.size = packet_size;
descriptor.state = 2; descriptor.state = 2;
m_thread_blocker.unblock(); m_thread_blocker.unblock();
m_buffer_lock.unlock(interrupt_state);
return {}; return {};
} }
void LoopbackInterface::receive_thread() void LoopbackInterface::receive_thread()
{ {
LockGuard _(m_buffer_lock); SpinLockGuard guard(m_buffer_lock);
while (!m_thread_should_die) while (!m_thread_should_die)
{ {
@@ -102,7 +107,7 @@ namespace Kernel
break; break;
m_buffer_tail = (m_buffer_tail + 1) % buffer_count; m_buffer_tail = (m_buffer_tail + 1) % buffer_count;
m_buffer_lock.unlock(); m_buffer_lock.unlock(InterruptState::Enabled);
NetworkManager::get().on_receive(*this, { NetworkManager::get().on_receive(*this, {
descriptor.addr, descriptor.addr,
@@ -116,7 +121,8 @@ namespace Kernel
m_thread_blocker.unblock(); 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; m_thread_is_dead = true;