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:
parent
93aa4d581d
commit
bc1da7f1fd
6 changed files with 51 additions and 6 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue