mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 02:58:12 +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()
|
NetworkAdapter::NetworkAdapter()
|
||||||
|
: m_packet_queue_alarm(*this)
|
||||||
{
|
{
|
||||||
// FIXME: I wanna lock :(
|
// FIXME: I wanna lock :(
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
@ -90,3 +91,8 @@ void NetworkAdapter::set_ipv4_address(const IPv4Address& address)
|
||||||
{
|
{
|
||||||
m_ipv4_address = 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/IPv4.h>
|
||||||
#include <Kernel/ARP.h>
|
#include <Kernel/ARP.h>
|
||||||
#include <Kernel/ICMP.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 {
|
class NetworkAdapter {
|
||||||
public:
|
public:
|
||||||
|
@ -24,6 +36,10 @@ public:
|
||||||
|
|
||||||
ByteBuffer dequeue_packet();
|
ByteBuffer dequeue_packet();
|
||||||
|
|
||||||
|
Alarm& packet_queue_alarm() { return m_packet_queue_alarm; }
|
||||||
|
|
||||||
|
bool has_queued_packets() const { return !m_packet_queue.is_empty(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NetworkAdapter();
|
NetworkAdapter();
|
||||||
void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; }
|
void set_mac_address(const MACAddress& mac_address) { m_mac_address = mac_address; }
|
||||||
|
@ -33,5 +49,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
MACAddress m_mac_address;
|
MACAddress m_mac_address;
|
||||||
IPv4Address m_ipv4_address;
|
IPv4Address m_ipv4_address;
|
||||||
|
PacketQueueAlarm m_packet_queue_alarm;
|
||||||
SinglyLinkedList<ByteBuffer> m_packet_queue;
|
SinglyLinkedList<ByteBuffer> m_packet_queue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,16 +34,16 @@ Lockable<HashMap<IPv4Address, MACAddress>>& arp_table()
|
||||||
|
|
||||||
void NetworkTask_main()
|
void NetworkTask_main()
|
||||||
{
|
{
|
||||||
auto* e1000_ptr = E1000NetworkAdapter::the();
|
auto* adapter_ptr = E1000NetworkAdapter::the();
|
||||||
ASSERT(e1000_ptr);
|
ASSERT(adapter_ptr);
|
||||||
auto& e1000 = *e1000_ptr;
|
auto& adapter = *adapter_ptr;
|
||||||
e1000.set_ipv4_address(IPv4Address(192, 168, 5, 2));
|
adapter.set_ipv4_address(IPv4Address(192, 168, 5, 2));
|
||||||
|
|
||||||
kprintf("NetworkTask: Enter main loop.\n");
|
kprintf("NetworkTask: Enter main loop.\n");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto packet = e1000.dequeue_packet();
|
auto packet = adapter.dequeue_packet();
|
||||||
if (packet.is_null()) {
|
if (packet.is_null()) {
|
||||||
sleep(100);
|
current->snooze_until(adapter.packet_queue_alarm());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (packet.size() < (int)(sizeof(EthernetFrameHeader))) {
|
if (packet.size() < (int)(sizeof(EthernetFrameHeader))) {
|
||||||
|
|
|
@ -1735,6 +1735,13 @@ void Process::unblock()
|
||||||
m_state = Process::Runnable;
|
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)
|
void Process::block(Process::State new_state)
|
||||||
{
|
{
|
||||||
if (state() != Process::Running) {
|
if (state() != Process::Running) {
|
||||||
|
@ -2871,6 +2878,7 @@ const char* to_string(Process::State state)
|
||||||
case Process::BlockedConnect: return "Connect";
|
case Process::BlockedConnect: return "Connect";
|
||||||
case Process::BlockedReceive: return "Receive";
|
case Process::BlockedReceive: return "Receive";
|
||||||
case Process::BeingInspected: return "Inspect";
|
case Process::BeingInspected: return "Inspect";
|
||||||
|
case Process::BlockedSnoozing: return "Snoozing";
|
||||||
}
|
}
|
||||||
kprintf("to_string(Process::State): Invalid state: %u\n", state);
|
kprintf("to_string(Process::State): Invalid state: %u\n", state);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <AK/Weakable.h>
|
#include <AK/Weakable.h>
|
||||||
#include <Kernel/Lock.h>
|
#include <Kernel/Lock.h>
|
||||||
|
|
||||||
|
class Alarm;
|
||||||
class FileDescriptor;
|
class FileDescriptor;
|
||||||
class PageDirectory;
|
class PageDirectory;
|
||||||
class Region;
|
class Region;
|
||||||
|
@ -78,6 +79,7 @@ public:
|
||||||
BlockedSelect,
|
BlockedSelect,
|
||||||
BlockedConnect,
|
BlockedConnect,
|
||||||
BlockedReceive,
|
BlockedReceive,
|
||||||
|
BlockedSnoozing,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Priority {
|
enum Priority {
|
||||||
|
@ -139,6 +141,8 @@ public:
|
||||||
void set_wakeup_time(dword t) { m_wakeup_time = t; }
|
void set_wakeup_time(dword t) { m_wakeup_time = t; }
|
||||||
dword wakeup_time() const { return m_wakeup_time; }
|
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(Callback);
|
||||||
template<typename Callback> static void for_each_in_pgrp(pid_t, Callback);
|
template<typename Callback> static void for_each_in_pgrp(pid_t, Callback);
|
||||||
template<typename Callback> static void for_each_in_state(State, Callback);
|
template<typename Callback> static void for_each_in_state(State, Callback);
|
||||||
|
@ -382,6 +386,7 @@ private:
|
||||||
dword m_pending_signals { 0 };
|
dword m_pending_signals { 0 };
|
||||||
dword m_signal_mask { 0 };
|
dword m_signal_mask { 0 };
|
||||||
RetainPtr<Socket> m_blocked_socket;
|
RetainPtr<Socket> m_blocked_socket;
|
||||||
|
Alarm* m_snoozing_alarm { nullptr };
|
||||||
|
|
||||||
byte m_termination_status { 0 };
|
byte m_termination_status { 0 };
|
||||||
byte m_termination_signal { 0 };
|
byte m_termination_signal { 0 };
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "i8253.h"
|
#include "i8253.h"
|
||||||
#include <AK/TemporaryChange.h>
|
#include <AK/TemporaryChange.h>
|
||||||
|
#include <Kernel/Alarm.h>
|
||||||
|
|
||||||
//#define LOG_EVERY_CONTEXT_SWITCH
|
//#define LOG_EVERY_CONTEXT_SWITCH
|
||||||
//#define SCHEDULER_DEBUG
|
//#define SCHEDULER_DEBUG
|
||||||
|
@ -136,6 +137,14 @@ bool Scheduler::pick_next()
|
||||||
return true;
|
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) {
|
if (process.state() == Process::Skip1SchedulerPass) {
|
||||||
process.set_state(Process::Skip0SchedulerPasses);
|
process.set_state(Process::Skip0SchedulerPasses);
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue