1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 03:18:11 +00:00

Kernel: Snooze the NetworkTask until there are incoming packets to process.

This is accomplished using a new Alarm class and a BlockedSnoozing state.
Basically, you call Process::snooze_until(some_alarm) and then the scheduler
won't wake up the process until some_alarm.is_ringing() returns true.
This commit is contained in:
Andreas Kling 2019-03-20 17:09:46 +01:00
parent 93aa4d581d
commit bc1da7f1fd
6 changed files with 51 additions and 6 deletions

View file

@ -25,6 +25,7 @@ NetworkAdapter* NetworkAdapter::from_ipv4_address(const IPv4Address& address)
}
NetworkAdapter::NetworkAdapter()
: m_packet_queue_alarm(*this)
{
// FIXME: I wanna lock :(
ASSERT_INTERRUPTS_DISABLED();
@ -90,3 +91,8 @@ void NetworkAdapter::set_ipv4_address(const IPv4Address& address)
{
m_ipv4_address = address;
}
bool PacketQueueAlarm::is_ringing() const
{
return m_adapter.has_queued_packets();
}

View file

@ -7,6 +7,18 @@
#include <Kernel/IPv4.h>
#include <Kernel/ARP.h>
#include <Kernel/ICMP.h>
#include <Kernel/Alarm.h>
class NetworkAdapter;
class PacketQueueAlarm final : public Alarm {
public:
PacketQueueAlarm(NetworkAdapter& adapter) : m_adapter(adapter) { }
virtual ~PacketQueueAlarm() override { }
virtual bool is_ringing() const override;
private:
NetworkAdapter& m_adapter;
};
class NetworkAdapter {
public:
@ -24,6 +36,10 @@ public:
ByteBuffer dequeue_packet();
Alarm& packet_queue_alarm() { return m_packet_queue_alarm; }
bool has_queued_packets() const { return !m_packet_queue.is_empty(); }
protected:
NetworkAdapter();
void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; }
@ -33,5 +49,6 @@ protected:
private:
MACAddress m_mac_address;
IPv4Address m_ipv4_address;
PacketQueueAlarm m_packet_queue_alarm;
SinglyLinkedList<ByteBuffer> m_packet_queue;
};

View file

@ -34,16 +34,16 @@ Lockable<HashMap<IPv4Address, MACAddress>>& arp_table()
void NetworkTask_main()
{
auto* e1000_ptr = E1000NetworkAdapter::the();
ASSERT(e1000_ptr);
auto& e1000 = *e1000_ptr;
e1000.set_ipv4_address(IPv4Address(192, 168, 5, 2));
auto* adapter_ptr = E1000NetworkAdapter::the();
ASSERT(adapter_ptr);
auto& adapter = *adapter_ptr;
adapter.set_ipv4_address(IPv4Address(192, 168, 5, 2));
kprintf("NetworkTask: Enter main loop.\n");
for (;;) {
auto packet = e1000.dequeue_packet();
auto packet = adapter.dequeue_packet();
if (packet.is_null()) {
sleep(100);
current->snooze_until(adapter.packet_queue_alarm());
continue;
}
if (packet.size() < (int)(sizeof(EthernetFrameHeader))) {

View file

@ -1735,6 +1735,13 @@ void Process::unblock()
m_state = Process::Runnable;
}
void Process::snooze_until(Alarm& alarm)
{
m_snoozing_alarm = &alarm;
block(Process::BlockedSnoozing);
Scheduler::yield();
}
void Process::block(Process::State new_state)
{
if (state() != Process::Running) {
@ -2871,6 +2878,7 @@ const char* to_string(Process::State state)
case Process::BlockedConnect: return "Connect";
case Process::BlockedReceive: return "Receive";
case Process::BeingInspected: return "Inspect";
case Process::BlockedSnoozing: return "Snoozing";
}
kprintf("to_string(Process::State): Invalid state: %u\n", state);
ASSERT_NOT_REACHED();

View file

@ -14,6 +14,7 @@
#include <AK/Weakable.h>
#include <Kernel/Lock.h>
class Alarm;
class FileDescriptor;
class PageDirectory;
class Region;
@ -78,6 +79,7 @@ public:
BlockedSelect,
BlockedConnect,
BlockedReceive,
BlockedSnoozing,
};
enum Priority {
@ -139,6 +141,8 @@ public:
void set_wakeup_time(dword t) { m_wakeup_time = t; }
dword wakeup_time() const { return m_wakeup_time; }
void snooze_until(Alarm&);
template<typename Callback> static void for_each(Callback);
template<typename Callback> static void for_each_in_pgrp(pid_t, Callback);
template<typename Callback> static void for_each_in_state(State, Callback);
@ -382,6 +386,7 @@ private:
dword m_pending_signals { 0 };
dword m_signal_mask { 0 };
RetainPtr<Socket> m_blocked_socket;
Alarm* m_snoozing_alarm { nullptr };
byte m_termination_status { 0 };
byte m_termination_signal { 0 };

View file

@ -4,6 +4,7 @@
#include "RTC.h"
#include "i8253.h"
#include <AK/TemporaryChange.h>
#include <Kernel/Alarm.h>
//#define LOG_EVERY_CONTEXT_SWITCH
//#define SCHEDULER_DEBUG
@ -136,6 +137,14 @@ bool Scheduler::pick_next()
return true;
}
if (process.state() == Process::BlockedSnoozing) {
if (process.m_snoozing_alarm->is_ringing()) {
process.m_snoozing_alarm = nullptr;
process.unblock();
}
return true;
}
if (process.state() == Process::Skip1SchedulerPass) {
process.set_state(Process::Skip0SchedulerPasses);
return true;