diff --git a/kernel/include/kernel/Networking/ARPTable.h b/kernel/include/kernel/Networking/ARPTable.h index 3a24d290..7df13abb 100644 --- a/kernel/include/kernel/Networking/ARPTable.h +++ b/kernel/include/kernel/Networking/ARPTable.h @@ -52,6 +52,7 @@ namespace Kernel private: SpinLock m_table_lock; + SpinLock m_pending_lock; BAN::HashMap m_arp_table; diff --git a/kernel/include/kernel/Networking/E1000/E1000.h b/kernel/include/kernel/Networking/E1000/E1000.h index 55a3b380..9a32f635 100644 --- a/kernel/include/kernel/Networking/E1000/E1000.h +++ b/kernel/include/kernel/Networking/E1000/E1000.h @@ -71,6 +71,7 @@ namespace Kernel BAN::UniqPtr m_tx_buffer_region; BAN::UniqPtr m_rx_descriptor_region; BAN::UniqPtr m_tx_descriptor_region; + SpinLock m_lock; BAN::MACAddress m_mac_address {}; bool m_link_up { false }; diff --git a/kernel/include/kernel/Networking/IPv4Layer.h b/kernel/include/kernel/Networking/IPv4Layer.h index f7136e4b..83aa4b1a 100644 --- a/kernel/include/kernel/Networking/IPv4Layer.h +++ b/kernel/include/kernel/Networking/IPv4Layer.h @@ -76,6 +76,7 @@ namespace Kernel BAN::UniqPtr m_pending_packet_buffer; BAN::CircularQueue m_pending_packets; Semaphore m_pending_semaphore; + SpinLock m_pending_lock; size_t m_pending_total_size { 0 }; BAN::HashMap> m_bound_sockets; diff --git a/kernel/kernel/Networking/ARPTable.cpp b/kernel/kernel/Networking/ARPTable.cpp index 19aacaf5..bdf62f88 100644 --- a/kernel/kernel/Networking/ARPTable.cpp +++ b/kernel/kernel/Networking/ARPTable.cpp @@ -145,24 +145,22 @@ namespace Kernel { for (;;) { - BAN::Optional 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(); + SpinLockGuard _(m_pending_lock); + if (m_pending_packets.full()) { dprintln("arp packet queue full"); diff --git a/kernel/kernel/Networking/E1000/E1000.cpp b/kernel/kernel/Networking/E1000/E1000.cpp index 31f07f6b..24e7f0f6 100644 --- a/kernel/kernel/Networking/E1000/E1000.cpp +++ b/kernel/kernel/Networking/E1000/E1000.cpp @@ -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; diff --git a/kernel/kernel/Networking/IPv4Layer.cpp b/kernel/kernel/Networking/IPv4Layer.cpp index fbe3ca88..055ad25a 100644 --- a/kernel/kernel/Networking/IPv4Layer.cpp +++ b/kernel/kernel/Networking/IPv4Layer.cpp @@ -287,30 +287,28 @@ namespace Kernel { for (;;) { - BAN::Optional 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(m_pending_packet_buffer->vaddr()); const size_t ipv4_packet_size = reinterpret_cast(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");