Kernel: Replace CriticalScopes with SpinLocks in networking code

This commit is contained in:
Bananymous 2024-02-29 12:02:09 +02:00
parent 7f028f70d5
commit 90878a7c2b
6 changed files with 35 additions and 30 deletions

View File

@ -52,6 +52,7 @@ namespace Kernel
private:
SpinLock m_table_lock;
SpinLock m_pending_lock;
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;

View File

@ -71,6 +71,7 @@ namespace Kernel
BAN::UniqPtr<DMARegion> m_tx_buffer_region;
BAN::UniqPtr<DMARegion> m_rx_descriptor_region;
BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
SpinLock m_lock;
BAN::MACAddress m_mac_address {};
bool m_link_up { false };

View File

@ -76,6 +76,7 @@ namespace Kernel
BAN::UniqPtr<VirtualRange> m_pending_packet_buffer;
BAN::CircularQueue<PendingIPv4Packet, 128> m_pending_packets;
Semaphore m_pending_semaphore;
SpinLock m_pending_lock;
size_t m_pending_total_size { 0 };
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;

View File

@ -145,24 +145,22 @@ namespace Kernel
{
for (;;)
{
BAN::Optional<PendingArpPacket> pending;
{
CriticalScope _;
if (!m_pending_packets.empty())
PendingArpPacket pending = ({
auto state = m_pending_lock.lock();
while (m_pending_packets.empty())
{
pending = m_pending_packets.front();
m_pending_packets.pop();
m_pending_lock.unlock(state);
m_pending_semaphore.block_indefinite();
state = m_pending_lock.lock();
}
}
auto packet = m_pending_packets.front();
m_pending_packets.pop();
m_pending_lock.unlock(state);
if (!pending.has_value())
{
m_pending_semaphore.block_indefinite();
continue;
}
packet;
});
if (auto ret = handle_arp_packet(pending->interface, pending->packet); ret.is_error())
if (auto ret = handle_arp_packet(pending.interface, pending.packet); ret.is_error())
dwarnln("{}", ret.error());
}
}
@ -171,6 +169,8 @@ namespace Kernel
{
auto& arp_packet = buffer.as<const ARPPacket>();
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dprintln("arp packet queue full");

View File

@ -261,7 +261,7 @@ namespace Kernel
{
ASSERT_LTE(buffer.size() + sizeof(EthernetHeader), E1000_TX_BUFFER_SIZE);
CriticalScope _;
SpinLockGuard _(m_lock);
size_t tx_current = read32(REG_TDT) % E1000_TX_DESCRIPTOR_COUNT;
@ -291,6 +291,8 @@ namespace Kernel
if (read32(REG_ICR) & ICR_RxQ0)
return;
SpinLockGuard _(m_lock);
for (;;) {
uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;

View File

@ -287,30 +287,28 @@ namespace Kernel
{
for (;;)
{
BAN::Optional<PendingIPv4Packet> pending;
{
CriticalScope _;
if (!m_pending_packets.empty())
PendingIPv4Packet pending = ({
auto state = m_pending_lock.lock();
while (m_pending_packets.empty())
{
pending = m_pending_packets.front();
m_pending_packets.pop();
m_pending_lock.unlock(state);
m_pending_semaphore.block_indefinite();
state = m_pending_lock.lock();
}
}
auto packet = m_pending_packets.front();
m_pending_packets.pop();
m_pending_lock.unlock(state);
if (!pending.has_value())
{
m_pending_semaphore.block_indefinite();
continue;
}
packet;
});
uint8_t* buffer_start = reinterpret_cast<uint8_t*>(m_pending_packet_buffer->vaddr());
const size_t ipv4_packet_size = reinterpret_cast<const IPv4Header*>(buffer_start)->total_length;
if (auto ret = handle_ipv4_packet(pending->interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
if (auto ret = handle_ipv4_packet(pending.interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
dwarnln("{}", ret.error());
CriticalScope _;
SpinLockGuard _(m_pending_lock);
m_pending_total_size -= ipv4_packet_size;
if (m_pending_total_size)
memmove(buffer_start, buffer_start + ipv4_packet_size, m_pending_total_size);
@ -319,6 +317,8 @@ namespace Kernel
void IPv4Layer::add_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln("IPv4 packet queue full");