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:
Mutex m_buffer_lock;
SpinLock m_buffer_lock;
BAN::UniqPtr<VirtualRange> m_buffer;
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/NetworkManager.h>
@@ -56,10 +56,13 @@ namespace Kernel
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 =
[&]() -> 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;