mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:07:35 +00:00
Kernel+SystemMonitor: Log amounts of I/O per thread
This patch adds these I/O counters to each thread: - (Inode) file read bytes - (Inode) file write bytes - Unix socket read bytes - Unix socket write bytes - IPv4 socket read bytes - IPv4 socket write bytes These are then exposed in /proc/all and seen in SystemMonitor.
This commit is contained in:
parent
a18aa8fd5f
commit
5a45376180
10 changed files with 171 additions and 17 deletions
|
@ -71,6 +71,18 @@ String ProcessModel::column_name(int column) const
|
||||||
return "F:Zero";
|
return "F:Zero";
|
||||||
case Column::CowFaults:
|
case Column::CowFaults:
|
||||||
return "F:CoW";
|
return "F:CoW";
|
||||||
|
case Column::IPv4SocketReadBytes:
|
||||||
|
return "IPv4 In";
|
||||||
|
case Column::IPv4SocketWriteBytes:
|
||||||
|
return "IPv4 Out";
|
||||||
|
case Column::UnixSocketReadBytes:
|
||||||
|
return "Unix In";
|
||||||
|
case Column::UnixSocketWriteBytes:
|
||||||
|
return "Unix Out";
|
||||||
|
case Column::FileReadBytes:
|
||||||
|
return "File In";
|
||||||
|
case Column::FileWriteBytes:
|
||||||
|
return "File Out";
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -107,6 +119,18 @@ GModel::ColumnMetadata ProcessModel::column_metadata(int column) const
|
||||||
return { 60, TextAlignment::CenterRight };
|
return { 60, TextAlignment::CenterRight };
|
||||||
case Column::CowFaults:
|
case Column::CowFaults:
|
||||||
return { 60, TextAlignment::CenterRight };
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::FileReadBytes:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::FileWriteBytes:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::UnixSocketReadBytes:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::UnixSocketWriteBytes:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::IPv4SocketReadBytes:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
|
case Column::IPv4SocketWriteBytes:
|
||||||
|
return { 60, TextAlignment::CenterRight };
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -164,6 +188,18 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const
|
||||||
return (int)thread.current_state.zero_faults;
|
return (int)thread.current_state.zero_faults;
|
||||||
case Column::CowFaults:
|
case Column::CowFaults:
|
||||||
return (int)thread.current_state.cow_faults;
|
return (int)thread.current_state.cow_faults;
|
||||||
|
case Column::IPv4SocketReadBytes:
|
||||||
|
return (int)thread.current_state.ipv4_socket_read_bytes;
|
||||||
|
case Column::IPv4SocketWriteBytes:
|
||||||
|
return (int)thread.current_state.ipv4_socket_write_bytes;
|
||||||
|
case Column::UnixSocketReadBytes:
|
||||||
|
return (int)thread.current_state.unix_socket_read_bytes;
|
||||||
|
case Column::UnixSocketWriteBytes:
|
||||||
|
return (int)thread.current_state.unix_socket_write_bytes;
|
||||||
|
case Column::FileReadBytes:
|
||||||
|
return (int)thread.current_state.file_read_bytes;
|
||||||
|
case Column::FileWriteBytes:
|
||||||
|
return (int)thread.current_state.file_write_bytes;
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
return {};
|
return {};
|
||||||
|
@ -216,6 +252,18 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const
|
||||||
return (int)thread.current_state.zero_faults;
|
return (int)thread.current_state.zero_faults;
|
||||||
case Column::CowFaults:
|
case Column::CowFaults:
|
||||||
return (int)thread.current_state.cow_faults;
|
return (int)thread.current_state.cow_faults;
|
||||||
|
case Column::IPv4SocketReadBytes:
|
||||||
|
return (int)thread.current_state.ipv4_socket_read_bytes;
|
||||||
|
case Column::IPv4SocketWriteBytes:
|
||||||
|
return (int)thread.current_state.ipv4_socket_write_bytes;
|
||||||
|
case Column::UnixSocketReadBytes:
|
||||||
|
return (int)thread.current_state.unix_socket_read_bytes;
|
||||||
|
case Column::UnixSocketWriteBytes:
|
||||||
|
return (int)thread.current_state.unix_socket_write_bytes;
|
||||||
|
case Column::FileReadBytes:
|
||||||
|
return (int)thread.current_state.file_read_bytes;
|
||||||
|
case Column::FileWriteBytes:
|
||||||
|
return (int)thread.current_state.file_write_bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +289,12 @@ void ProcessModel::update()
|
||||||
state.inode_faults = thread.inode_faults;
|
state.inode_faults = thread.inode_faults;
|
||||||
state.zero_faults = thread.zero_faults;
|
state.zero_faults = thread.zero_faults;
|
||||||
state.cow_faults = thread.cow_faults;
|
state.cow_faults = thread.cow_faults;
|
||||||
|
state.unix_socket_read_bytes = thread.unix_socket_read_bytes;
|
||||||
|
state.unix_socket_write_bytes = thread.unix_socket_write_bytes;
|
||||||
|
state.ipv4_socket_read_bytes = thread.ipv4_socket_read_bytes;
|
||||||
|
state.ipv4_socket_write_bytes = thread.ipv4_socket_write_bytes;
|
||||||
|
state.file_read_bytes = thread.file_read_bytes;
|
||||||
|
state.file_write_bytes = thread.file_write_bytes;
|
||||||
state.name = it.value.name;
|
state.name = it.value.name;
|
||||||
state.amount_virtual = it.value.amount_virtual;
|
state.amount_virtual = it.value.amount_virtual;
|
||||||
state.amount_resident = it.value.amount_resident;
|
state.amount_resident = it.value.amount_resident;
|
||||||
|
|
|
@ -34,6 +34,12 @@ public:
|
||||||
InodeFaults,
|
InodeFaults,
|
||||||
ZeroFaults,
|
ZeroFaults,
|
||||||
CowFaults,
|
CowFaults,
|
||||||
|
FileReadBytes,
|
||||||
|
FileWriteBytes,
|
||||||
|
UnixSocketReadBytes,
|
||||||
|
UnixSocketWriteBytes,
|
||||||
|
IPv4SocketReadBytes,
|
||||||
|
IPv4SocketWriteBytes,
|
||||||
__Count
|
__Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,6 +74,12 @@ private:
|
||||||
unsigned inode_faults;
|
unsigned inode_faults;
|
||||||
unsigned zero_faults;
|
unsigned zero_faults;
|
||||||
unsigned cow_faults;
|
unsigned cow_faults;
|
||||||
|
unsigned unix_socket_read_bytes;
|
||||||
|
unsigned unix_socket_write_bytes;
|
||||||
|
unsigned ipv4_socket_read_bytes;
|
||||||
|
unsigned ipv4_socket_write_bytes;
|
||||||
|
unsigned file_read_bytes;
|
||||||
|
unsigned file_write_bytes;
|
||||||
float cpu_percent;
|
float cpu_percent;
|
||||||
int icon_id;
|
int icon_id;
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,15 +15,20 @@ InodeFile::~InodeFile()
|
||||||
|
|
||||||
ssize_t InodeFile::read(FileDescription& description, u8* buffer, ssize_t count)
|
ssize_t InodeFile::read(FileDescription& description, u8* buffer, ssize_t count)
|
||||||
{
|
{
|
||||||
return m_inode->read_bytes(description.offset(), count, buffer, &description);
|
ssize_t nread = m_inode->read_bytes(description.offset(), count, buffer, &description);
|
||||||
|
if (nread > 0)
|
||||||
|
current->did_file_read(nread);
|
||||||
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t InodeFile::write(FileDescription& description, const u8* data, ssize_t count)
|
ssize_t InodeFile::write(FileDescription& description, const u8* data, ssize_t count)
|
||||||
{
|
{
|
||||||
ssize_t ret = m_inode->write_bytes(description.offset(), count, data, &description);
|
ssize_t nwritten = m_inode->write_bytes(description.offset(), count, data, &description);
|
||||||
if (ret > 0)
|
if (nwritten > 0) {
|
||||||
m_inode->set_mtime(kgettimeofday().tv_sec);
|
m_inode->set_mtime(kgettimeofday().tv_sec);
|
||||||
return ret;
|
current->did_file_write(nwritten);
|
||||||
|
}
|
||||||
|
return nwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& description, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot)
|
KResultOr<Region*> InodeFile::mmap(Process& process, FileDescription& description, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot)
|
||||||
|
|
|
@ -725,6 +725,12 @@ Optional<KBuffer> procfs$all(InodeIdentifier)
|
||||||
thread_object.add("inode_faults", thread.inode_faults());
|
thread_object.add("inode_faults", thread.inode_faults());
|
||||||
thread_object.add("zero_faults", thread.zero_faults());
|
thread_object.add("zero_faults", thread.zero_faults());
|
||||||
thread_object.add("cow_faults", thread.cow_faults());
|
thread_object.add("cow_faults", thread.cow_faults());
|
||||||
|
thread_object.add("file_read_bytes", thread.file_read_bytes());
|
||||||
|
thread_object.add("file_write_bytes", thread.file_write_bytes());
|
||||||
|
thread_object.add("unix_socket_read_bytes", thread.unix_socket_read_bytes());
|
||||||
|
thread_object.add("unix_socket_write_bytes", thread.unix_socket_write_bytes());
|
||||||
|
thread_object.add("ipv4_socket_read_bytes", thread.ipv4_socket_read_bytes());
|
||||||
|
thread_object.add("ipv4_socket_write_bytes", thread.ipv4_socket_write_bytes());
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -206,7 +206,10 @@ ssize_t IPv4Socket::sendto(FileDescription&, const void* data, size_t data_lengt
|
||||||
return data_length;
|
return data_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return protocol_send(data, data_length);
|
int nsent = protocol_send(data, data_length);
|
||||||
|
if (nsent > 0)
|
||||||
|
current->did_ipv4_socket_write(nsent);
|
||||||
|
return nsent;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length)
|
ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t buffer_length, int flags, sockaddr* addr, socklen_t* addr_length)
|
||||||
|
@ -285,7 +288,10 @@ ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t
|
||||||
return ipv4_packet.payload_size();
|
return ipv4_packet.payload_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return protocol_receive(packet.data.value(), buffer, buffer_length, flags);
|
int nreceived = protocol_receive(packet.data.value(), buffer, buffer_length, flags);
|
||||||
|
if (nreceived > 0)
|
||||||
|
current->did_ipv4_socket_read(nreceived);
|
||||||
|
return nreceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port, KBuffer&& packet)
|
bool IPv4Socket::did_receive(const IPv4Address& source_address, u16 source_port, KBuffer&& packet)
|
||||||
|
|
|
@ -222,15 +222,13 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size
|
||||||
{
|
{
|
||||||
if (!has_attached_peer(description))
|
if (!has_attached_peer(description))
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
auto role = this->role(description);
|
ssize_t nwritten = send_buffer_for(description).write((const u8*)data, data_size);
|
||||||
if (role == Role::Accepted)
|
if (nwritten > 0)
|
||||||
return m_for_client.write((const u8*)data, data_size);
|
current->did_unix_socket_write(nwritten);
|
||||||
if (role == Role::Connected)
|
return nwritten;
|
||||||
return m_for_server.write((const u8*)data, data_size);
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DoubleBuffer& LocalSocket::buffer_for(FileDescription& description)
|
DoubleBuffer& LocalSocket::receive_buffer_for(FileDescription& description)
|
||||||
{
|
{
|
||||||
auto role = this->role(description);
|
auto role = this->role(description);
|
||||||
if (role == Role::Accepted)
|
if (role == Role::Accepted)
|
||||||
|
@ -240,9 +238,19 @@ DoubleBuffer& LocalSocket::buffer_for(FileDescription& description)
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DoubleBuffer& LocalSocket::send_buffer_for(FileDescription& description)
|
||||||
|
{
|
||||||
|
auto role = this->role(description);
|
||||||
|
if (role == Role::Connected)
|
||||||
|
return m_for_server;
|
||||||
|
if (role == Role::Accepted)
|
||||||
|
return m_for_client;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*)
|
ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t buffer_size, int, sockaddr*, socklen_t*)
|
||||||
{
|
{
|
||||||
auto& buffer_for_me = buffer_for(description);
|
auto& buffer_for_me = receive_buffer_for(description);
|
||||||
if (!description.is_blocking()) {
|
if (!description.is_blocking()) {
|
||||||
if (buffer_for_me.is_empty()) {
|
if (buffer_for_me.is_empty()) {
|
||||||
if (!has_attached_peer(description))
|
if (!has_attached_peer(description))
|
||||||
|
@ -257,7 +265,10 @@ ssize_t LocalSocket::recvfrom(FileDescription& description, void* buffer, size_t
|
||||||
if (!has_attached_peer(description) && buffer_for_me.is_empty())
|
if (!has_attached_peer(description) && buffer_for_me.is_empty())
|
||||||
return 0;
|
return 0;
|
||||||
ASSERT(!buffer_for_me.is_empty());
|
ASSERT(!buffer_for_me.is_empty());
|
||||||
return buffer_for_me.read((u8*)buffer, buffer_size);
|
int nread = buffer_for_me.read((u8*)buffer, buffer_size);
|
||||||
|
if (nread > 0)
|
||||||
|
current->did_unix_socket_read(nread);
|
||||||
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView LocalSocket::socket_path() const
|
StringView LocalSocket::socket_path() const
|
||||||
|
|
|
@ -36,7 +36,8 @@ private:
|
||||||
virtual bool is_local() const override { return true; }
|
virtual bool is_local() const override { return true; }
|
||||||
bool has_attached_peer(const FileDescription&) const;
|
bool has_attached_peer(const FileDescription&) const;
|
||||||
static Lockable<InlineLinkedList<LocalSocket>>& all_sockets();
|
static Lockable<InlineLinkedList<LocalSocket>>& all_sockets();
|
||||||
DoubleBuffer& buffer_for(FileDescription&);
|
DoubleBuffer& receive_buffer_for(FileDescription&);
|
||||||
|
DoubleBuffer& send_buffer_for(FileDescription&);
|
||||||
|
|
||||||
// An open socket file on the filesystem.
|
// An open socket file on the filesystem.
|
||||||
RefPtr<FileDescription> m_file;
|
RefPtr<FileDescription> m_file;
|
||||||
|
|
|
@ -363,6 +363,45 @@ public:
|
||||||
unsigned cow_faults() const { return m_cow_faults; }
|
unsigned cow_faults() const { return m_cow_faults; }
|
||||||
void did_cow_fault() { ++m_cow_faults; }
|
void did_cow_fault() { ++m_cow_faults; }
|
||||||
|
|
||||||
|
unsigned file_read_bytes() const { return m_file_read_bytes; }
|
||||||
|
unsigned file_write_bytes() const { return m_file_write_bytes; }
|
||||||
|
|
||||||
|
void did_file_read(unsigned bytes)
|
||||||
|
{
|
||||||
|
m_file_read_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_file_write(unsigned bytes)
|
||||||
|
{
|
||||||
|
m_file_write_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned unix_socket_read_bytes() const { return m_unix_socket_read_bytes; }
|
||||||
|
unsigned unix_socket_write_bytes() const { return m_unix_socket_write_bytes; }
|
||||||
|
|
||||||
|
void did_unix_socket_read(unsigned bytes)
|
||||||
|
{
|
||||||
|
m_unix_socket_read_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_unix_socket_write(unsigned bytes)
|
||||||
|
{
|
||||||
|
m_unix_socket_write_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ipv4_socket_read_bytes() const { return m_ipv4_socket_read_bytes; }
|
||||||
|
unsigned ipv4_socket_write_bytes() const { return m_ipv4_socket_write_bytes; }
|
||||||
|
|
||||||
|
void did_ipv4_socket_read(unsigned bytes)
|
||||||
|
{
|
||||||
|
m_ipv4_socket_read_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void did_ipv4_socket_write(unsigned bytes)
|
||||||
|
{
|
||||||
|
m_ipv4_socket_write_bytes += bytes;
|
||||||
|
}
|
||||||
|
|
||||||
Thread* clone(Process&);
|
Thread* clone(Process&);
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
|
@ -416,6 +455,15 @@ private:
|
||||||
unsigned m_zero_faults { 0 };
|
unsigned m_zero_faults { 0 };
|
||||||
unsigned m_cow_faults { 0 };
|
unsigned m_cow_faults { 0 };
|
||||||
|
|
||||||
|
unsigned m_file_read_bytes { 0 };
|
||||||
|
unsigned m_file_write_bytes { 0 };
|
||||||
|
|
||||||
|
unsigned m_unix_socket_read_bytes { 0 };
|
||||||
|
unsigned m_unix_socket_write_bytes { 0 };
|
||||||
|
|
||||||
|
unsigned m_ipv4_socket_read_bytes { 0 };
|
||||||
|
unsigned m_ipv4_socket_write_bytes { 0 };
|
||||||
|
|
||||||
FPUState* m_fpu_state { nullptr };
|
FPUState* m_fpu_state { nullptr };
|
||||||
State m_state { Invalid };
|
State m_state { Invalid };
|
||||||
ThreadPriority m_priority { ThreadPriority::Normal };
|
ThreadPriority m_priority { ThreadPriority::Normal };
|
||||||
|
|
|
@ -53,6 +53,12 @@ HashMap<pid_t, CProcessStatistics> CProcessStatisticsReader::get_all()
|
||||||
thread.inode_faults = thread_object.get("inode_faults").to_u32();
|
thread.inode_faults = thread_object.get("inode_faults").to_u32();
|
||||||
thread.zero_faults = thread_object.get("zero_faults").to_u32();
|
thread.zero_faults = thread_object.get("zero_faults").to_u32();
|
||||||
thread.cow_faults = thread_object.get("cow_faults").to_u32();
|
thread.cow_faults = thread_object.get("cow_faults").to_u32();
|
||||||
|
thread.unix_socket_read_bytes = thread_object.get("unix_socket_read_bytes").to_u32();
|
||||||
|
thread.unix_socket_write_bytes = thread_object.get("unix_socket_write_bytes").to_u32();
|
||||||
|
thread.ipv4_socket_read_bytes = thread_object.get("ipv4_socket_read_bytes").to_u32();
|
||||||
|
thread.ipv4_socket_write_bytes = thread_object.get("ipv4_socket_write_bytes").to_u32();
|
||||||
|
thread.file_read_bytes = thread_object.get("file_read_bytes").to_u32();
|
||||||
|
thread.file_write_bytes = thread_object.get("file_write_bytes").to_u32();
|
||||||
process.threads.append(move(thread));
|
process.threads.append(move(thread));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -78,4 +84,3 @@ String CProcessStatisticsReader::username_from_uid(uid_t uid)
|
||||||
return (*it).value;
|
return (*it).value;
|
||||||
return String::number(uid);
|
return String::number(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,12 @@ struct CThreadStatistics {
|
||||||
unsigned inode_faults;
|
unsigned inode_faults;
|
||||||
unsigned zero_faults;
|
unsigned zero_faults;
|
||||||
unsigned cow_faults;
|
unsigned cow_faults;
|
||||||
|
unsigned unix_socket_read_bytes;
|
||||||
|
unsigned unix_socket_write_bytes;
|
||||||
|
unsigned ipv4_socket_read_bytes;
|
||||||
|
unsigned ipv4_socket_write_bytes;
|
||||||
|
unsigned file_read_bytes;
|
||||||
|
unsigned file_write_bytes;
|
||||||
String state;
|
String state;
|
||||||
String priority;
|
String priority;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue