summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-12-01 17:36:06 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-12-01 17:40:27 +0100
commit5a45376180fe589622a169828bb030eb929a509d (patch)
treea47ff74abdda552b28e7cb661c7c839fac9061a5
parenta18aa8fd5f65708d840c5ff8c13f673ae4c8b079 (diff)
downloadserenity-5a45376180fe589622a169828bb030eb929a509d.zip
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.
-rw-r--r--Applications/SystemMonitor/ProcessModel.cpp54
-rw-r--r--Applications/SystemMonitor/ProcessModel.h12
-rw-r--r--Kernel/FileSystem/InodeFile.cpp13
-rw-r--r--Kernel/FileSystem/ProcFS.cpp6
-rw-r--r--Kernel/Net/IPv4Socket.cpp10
-rw-r--r--Kernel/Net/LocalSocket.cpp25
-rw-r--r--Kernel/Net/LocalSocket.h3
-rw-r--r--Kernel/Thread.h48
-rw-r--r--Libraries/LibCore/CProcessStatisticsReader.cpp7
-rw-r--r--Libraries/LibCore/CProcessStatisticsReader.h6
10 files changed, 169 insertions, 15 deletions
diff --git a/Applications/SystemMonitor/ProcessModel.cpp b/Applications/SystemMonitor/ProcessModel.cpp
index 9dbaf99807..d6a6b782de 100644
--- a/Applications/SystemMonitor/ProcessModel.cpp
+++ b/Applications/SystemMonitor/ProcessModel.cpp
@@ -71,6 +71,18 @@ String ProcessModel::column_name(int column) const
return "F:Zero";
case Column::CowFaults:
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:
ASSERT_NOT_REACHED();
}
@@ -107,6 +119,18 @@ GModel::ColumnMetadata ProcessModel::column_metadata(int column) const
return { 60, TextAlignment::CenterRight };
case Column::CowFaults:
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:
ASSERT_NOT_REACHED();
}
@@ -164,6 +188,18 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const
return (int)thread.current_state.zero_faults;
case Column::CowFaults:
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();
return {};
@@ -216,6 +252,18 @@ GVariant ProcessModel::data(const GModelIndex& index, Role role) const
return (int)thread.current_state.zero_faults;
case Column::CowFaults:
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.zero_faults = thread.zero_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.amount_virtual = it.value.amount_virtual;
state.amount_resident = it.value.amount_resident;
diff --git a/Applications/SystemMonitor/ProcessModel.h b/Applications/SystemMonitor/ProcessModel.h
index c6365d109f..bb22d459cb 100644
--- a/Applications/SystemMonitor/ProcessModel.h
+++ b/Applications/SystemMonitor/ProcessModel.h
@@ -34,6 +34,12 @@ public:
InodeFaults,
ZeroFaults,
CowFaults,
+ FileReadBytes,
+ FileWriteBytes,
+ UnixSocketReadBytes,
+ UnixSocketWriteBytes,
+ IPv4SocketReadBytes,
+ IPv4SocketWriteBytes,
__Count
};
@@ -68,6 +74,12 @@ private:
unsigned inode_faults;
unsigned zero_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;
int icon_id;
};
diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp
index 7ba9814019..d47f42ba2a 100644
--- a/Kernel/FileSystem/InodeFile.cpp
+++ b/Kernel/FileSystem/InodeFile.cpp
@@ -15,15 +15,20 @@ InodeFile::~InodeFile()
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 ret = m_inode->write_bytes(description.offset(), count, data, &description);
- if (ret > 0)
+ ssize_t nwritten = m_inode->write_bytes(description.offset(), count, data, &description);
+ if (nwritten > 0) {
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)
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp
index 2f98ae442b..749a169538 100644
--- a/Kernel/FileSystem/ProcFS.cpp
+++ b/Kernel/FileSystem/ProcFS.cpp
@@ -725,6 +725,12 @@ Optional<KBuffer> procfs$all(InodeIdentifier)
thread_object.add("inode_faults", thread.inode_faults());
thread_object.add("zero_faults", thread.zero_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;
});
};
diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp
index 3949fb5692..06d3e21249 100644
--- a/Kernel/Net/IPv4Socket.cpp
+++ b/Kernel/Net/IPv4Socket.cpp
@@ -206,7 +206,10 @@ ssize_t IPv4Socket::sendto(FileDescription&, const void* data, size_t data_lengt
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)
@@ -285,7 +288,10 @@ ssize_t IPv4Socket::recvfrom(FileDescription& description, void* buffer, size_t
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)
diff --git a/Kernel/Net/LocalSocket.cpp b/Kernel/Net/LocalSocket.cpp
index babe57a023..d41d445620 100644
--- a/Kernel/Net/LocalSocket.cpp
+++ b/Kernel/Net/LocalSocket.cpp
@@ -222,27 +222,35 @@ ssize_t LocalSocket::sendto(FileDescription& description, const void* data, size
{
if (!has_attached_peer(description))
return -EPIPE;
+ ssize_t nwritten = send_buffer_for(description).write((const u8*)data, data_size);
+ if (nwritten > 0)
+ current->did_unix_socket_write(nwritten);
+ return nwritten;
+}
+
+DoubleBuffer& LocalSocket::receive_buffer_for(FileDescription& description)
+{
auto role = this->role(description);
if (role == Role::Accepted)
- return m_for_client.write((const u8*)data, data_size);
+ return m_for_server;
if (role == Role::Connected)
- return m_for_server.write((const u8*)data, data_size);
+ return m_for_client;
ASSERT_NOT_REACHED();
}
-DoubleBuffer& LocalSocket::buffer_for(FileDescription& description)
+DoubleBuffer& LocalSocket::send_buffer_for(FileDescription& description)
{
auto role = this->role(description);
- if (role == Role::Accepted)
- return m_for_server;
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*)
{
- auto& buffer_for_me = buffer_for(description);
+ auto& buffer_for_me = receive_buffer_for(description);
if (!description.is_blocking()) {
if (buffer_for_me.is_empty()) {
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())
return 0;
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
diff --git a/Kernel/Net/LocalSocket.h b/Kernel/Net/LocalSocket.h
index bd529933f1..7677a25e8d 100644
--- a/Kernel/Net/LocalSocket.h
+++ b/Kernel/Net/LocalSocket.h
@@ -36,7 +36,8 @@ private:
virtual bool is_local() const override { return true; }
bool has_attached_peer(const FileDescription&) const;
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.
RefPtr<FileDescription> m_file;
diff --git a/Kernel/Thread.h b/Kernel/Thread.h
index 54a46e4e2d..8f3c044438 100644
--- a/Kernel/Thread.h
+++ b/Kernel/Thread.h
@@ -363,6 +363,45 @@ public:
unsigned cow_faults() const { return 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&);
template<typename Callback>
@@ -416,6 +455,15 @@ private:
unsigned m_zero_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 };
State m_state { Invalid };
ThreadPriority m_priority { ThreadPriority::Normal };
diff --git a/Libraries/LibCore/CProcessStatisticsReader.cpp b/Libraries/LibCore/CProcessStatisticsReader.cpp
index 39f8db097e..39db980ee8 100644
--- a/Libraries/LibCore/CProcessStatisticsReader.cpp
+++ b/Libraries/LibCore/CProcessStatisticsReader.cpp
@@ -53,6 +53,12 @@ HashMap<pid_t, CProcessStatistics> CProcessStatisticsReader::get_all()
thread.inode_faults = thread_object.get("inode_faults").to_u32();
thread.zero_faults = thread_object.get("zero_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));
});
@@ -78,4 +84,3 @@ String CProcessStatisticsReader::username_from_uid(uid_t uid)
return (*it).value;
return String::number(uid);
}
-
diff --git a/Libraries/LibCore/CProcessStatisticsReader.h b/Libraries/LibCore/CProcessStatisticsReader.h
index bb6da21d31..05e9e9659e 100644
--- a/Libraries/LibCore/CProcessStatisticsReader.h
+++ b/Libraries/LibCore/CProcessStatisticsReader.h
@@ -12,6 +12,12 @@ struct CThreadStatistics {
unsigned inode_faults;
unsigned zero_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 priority;
};