diff options
-rw-r--r-- | AK/JsonParser.cpp | 4 | ||||
-rw-r--r-- | AK/JsonValue.cpp | 21 | ||||
-rw-r--r-- | AK/JsonValue.h | 29 | ||||
-rw-r--r-- | AK/Types.h | 2 | ||||
-rw-r--r-- | Applications/ProcessManager/ProcessModel.cpp | 42 | ||||
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 50 | ||||
-rw-r--r-- | Kernel/Makefile | 4 | ||||
-rw-r--r-- | Servers/WindowServer/WSCPUMonitor.cpp | 25 | ||||
-rw-r--r-- | Userland/top.cpp | 53 |
9 files changed, 127 insertions, 103 deletions
diff --git a/AK/JsonParser.cpp b/AK/JsonParser.cpp index e6cc4b7e6f..0dde664b5b 100644 --- a/AK/JsonParser.cpp +++ b/AK/JsonParser.cpp @@ -146,7 +146,9 @@ JsonValue JsonParser::parse_number() { auto number_string = extract_while([](char ch) { return ch == '-' || (ch >= '0' && ch <= '9'); }); bool ok; - auto value = JsonValue(number_string.to_int(ok)); + auto value = JsonValue(number_string.to_uint(ok)); + if (!ok) + value = JsonValue(number_string.to_int(ok)); ASSERT(ok); return value; } diff --git a/AK/JsonValue.cpp b/AK/JsonValue.cpp index 48ca1effd5..adb796c716 100644 --- a/AK/JsonValue.cpp +++ b/AK/JsonValue.cpp @@ -68,15 +68,15 @@ JsonValue::JsonValue(int value) m_value.as_int = value; } +JsonValue::JsonValue(long unsigned value) + : JsonValue((unsigned)value) +{ +} + JsonValue::JsonValue(unsigned value) + : m_type(Type::UnsignedInt) { - if (value > INT32_MAX) { - m_type = Type::Double; - m_value.as_double = value; - } else { - m_type = Type::Int; - m_value.as_int = (int)value; - } + m_value.as_uint = value; } JsonValue::JsonValue(const char* cstring) @@ -84,11 +84,13 @@ JsonValue::JsonValue(const char* cstring) { } +#ifndef KERNEL JsonValue::JsonValue(double value) : m_type(Type::Double) { m_value.as_double = value; } +#endif JsonValue::JsonValue(bool value) : m_type(Type::Bool) @@ -153,12 +155,17 @@ void JsonValue::serialize(StringBuilder& builder) const case Type::Bool: builder.append(m_value.as_bool ? "true" : "false"); break; +#ifndef KERNEL case Type::Double: builder.appendf("%g", m_value.as_double); break; +#endif case Type::Int: builder.appendf("%d", m_value.as_int); break; + case Type::UnsignedInt: + builder.appendf("%u", m_value.as_uint); + break; case Type::Undefined: builder.append("undefined"); break; diff --git a/AK/JsonValue.h b/AK/JsonValue.h index 324201d3e5..201a69c7c6 100644 --- a/AK/JsonValue.h +++ b/AK/JsonValue.h @@ -14,7 +14,10 @@ public: Undefined, Null, Int, + UnsignedInt, +#ifndef KERNEL Double, +#endif Bool, String, Array, @@ -34,7 +37,10 @@ public: JsonValue(int); JsonValue(unsigned); + JsonValue(long unsigned); +#ifndef KERNEL JsonValue(double); +#endif JsonValue(bool); JsonValue(const char*); JsonValue(const String&); @@ -75,18 +81,36 @@ public: bool is_undefined() const { return m_type == Type::Undefined; } bool is_string() const { return m_type == Type::String; } bool is_int() const { return m_type == Type::Int; } + bool is_uint() const { return m_type == Type::UnsignedInt; } +#ifndef KERNEL bool is_double() const { return m_type == Type::Double; } +#endif bool is_array() const { return m_type == Type::Array; } bool is_object() const { return m_type == Type::Object; } - bool is_number() const { return m_type == Type::Int || m_type == Type::Double; } + bool is_number() const + { + if (m_type == Type::Int || m_type == Type::UnsignedInt) + return true; +#ifdef KERNEL + return false; +#else + return m_type == Type::Double; +#endif + } dword to_dword(dword default_value = 0) const { if (!is_number()) return default_value; +#ifdef KERNEL + return (dword)m_value.as_int; +#else if (type() == Type::Int) return (dword)m_value.as_int; + if (type() == Type::UnsignedInt) + return m_value.as_uint; return (dword)m_value.as_double; +#endif } private: @@ -99,8 +123,11 @@ private: StringImpl* as_string { nullptr }; JsonArray* as_array; JsonObject* as_object; +#ifndef KERNEL double as_double; +#endif int as_int; + unsigned int as_uint; bool as_bool; } m_value; }; diff --git a/AK/Types.h b/AK/Types.h index 89a459a063..f0c5cd76e7 100644 --- a/AK/Types.h +++ b/AK/Types.h @@ -13,7 +13,7 @@ typedef signed short signed_word; typedef signed int signed_dword; typedef signed long long int signed_qword; -typedef decltype(sizeof(void*)) size_t; +typedef __SIZE_TYPE__ size_t; typedef signed_dword ssize_t; static_assert(sizeof(size_t) == sizeof(dword)); diff --git a/Applications/ProcessManager/ProcessModel.cpp b/Applications/ProcessManager/ProcessModel.cpp index f7f7c86fed..7a75bbf8fb 100644 --- a/Applications/ProcessManager/ProcessModel.cpp +++ b/Applications/ProcessManager/ProcessModel.cpp @@ -1,5 +1,8 @@ #include "ProcessModel.h" #include "GraphWidget.h" +#include <AK/JsonArray.h> +#include <AK/JsonObject.h> +#include <AK/JsonValue.h> #include <LibCore/CFile.h> #include <fcntl.h> #include <pwd.h> @@ -191,24 +194,16 @@ void ProcessModel::update() HashTable<pid_t> live_pids; unsigned sum_nsched = 0; - for (;;) { - auto line = m_proc_all.read_line(1024); - if (line.is_empty()) - break; - auto chomped = String((const char*)line.pointer(), line.size() - 1, Chomp); - auto parts = chomped.split_view(','); - if (parts.size() < 18) - break; - bool ok; - pid_t pid = parts[0].to_uint(ok); - ASSERT(ok); - unsigned nsched = parts[1].to_uint(ok); - ASSERT(ok); + auto file_contents = m_proc_all.read_all(); + auto json = JsonValue::from_string({ file_contents.data(), file_contents.size() }); + json.as_array().for_each([&](auto& value) { + const JsonObject& process_object = value.as_object(); + pid_t pid = process_object.get("pid").to_dword(); + unsigned nsched = process_object.get("times_scheduled").to_dword(); ProcessState state; state.pid = pid; state.nsched = nsched; - unsigned uid = parts[5].to_uint(ok); - ASSERT(ok); + unsigned uid = process_object.get("uid").to_dword(); { auto it = m_usernames.find((uid_t)uid); if (it != m_usernames.end()) @@ -216,15 +211,12 @@ void ProcessModel::update() else state.user = String::format("%u", uid); } - state.priority = parts[16]; - state.syscalls = parts[17].to_uint(ok); - ASSERT(ok); - state.state = parts[7]; - state.name = parts[11]; - state.virtual_size = parts[12].to_uint(ok); - ASSERT(ok); - state.physical_size = parts[13].to_uint(ok); - ASSERT(ok); + state.priority = process_object.get("priority").to_string(); + state.syscalls = process_object.get("syscall_count").to_dword(); + state.state = process_object.get("state").to_string(); + state.name = process_object.get("name").to_string(); + state.virtual_size = process_object.get("amount_virtual").to_dword(); + state.physical_size = process_object.get("amount_resident").to_dword(); sum_nsched += nsched; { auto it = m_processes.find(pid); @@ -237,7 +229,7 @@ void ProcessModel::update() (*it).value->current_state = state; live_pids.set(pid); - } + }); m_pids.clear(); float total_cpu_percent = 0; diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index d34f065ab2..5ffcb265cf 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -4,6 +4,9 @@ #include "Process.h" #include "Scheduler.h" #include "StdLib.h" +#include <AK/JsonArray.h> +#include <AK/JsonObject.h> +#include <AK/JsonValue.h> #include <AK/StringBuilder.h> #include <Kernel/Arch/i386/CPU.h> #include <Kernel/FileSystem/Custody.h> @@ -581,32 +584,33 @@ ByteBuffer procfs$all(InodeIdentifier) { InterruptDisabler disabler; auto processes = Process::all_processes(); + JsonArray array; StringBuilder builder(processes.size() * 80); - auto build_process_line = [&builder](Process* process) { - builder.appendf("%u,%u,%u,%u,%u,%u,%u,%s,%u,%u,%s,%s,%u,%u,%u,%u,%s,%u\n", - process->pid(), - process->main_thread().times_scheduled(), // FIXME(Thread): Bill all scheds to the process - process->tty() ? process->tty()->pgid() : 0, - process->pgid(), - process->sid(), - process->uid(), - process->gid(), - to_string(process->state()), - process->ppid(), - process->number_of_open_file_descriptors(), - process->tty() ? process->tty()->tty_name().characters() : "notty", - process->name().characters(), - process->amount_virtual(), - process->amount_resident(), - process->amount_shared(), - process->main_thread().ticks(), // FIXME(Thread): Bill all ticks to the process - to_string(process->priority()), - process->syscall_count()); + auto build_process = [&](const Process& process) { + JsonObject process_object; + process_object.set("pid", process.pid()); + process_object.set("times_scheduled", process.main_thread().times_scheduled()); + process_object.set("pgid", process.tty() ? process.tty()->pgid() : 0); + process_object.set("sid", process.sid()); + process_object.set("uid", process.uid()); + process_object.set("gid", process.gid()); + process_object.set("state", to_string(process.state())); + process_object.set("ppid", process.ppid()); + process_object.set("nfds", process.number_of_open_file_descriptors()); + process_object.set("name", process.name()); + process_object.set("tty", process.tty() ? process.tty()->tty_name() : "notty"); + process_object.set("amount_virtual", process.amount_virtual()); + process_object.set("amount_resident", process.amount_resident()); + process_object.set("amount_shared", process.amount_shared()); + process_object.set("ticks", process.main_thread().ticks()); + process_object.set("priority", to_string(process.priority())); + process_object.set("syscall_count", process.syscall_count()); + array.append(process_object); }; - build_process_line(Scheduler::colonel()); + build_process(*Scheduler::colonel()); for (auto* process : processes) - build_process_line(process); - return builder.to_byte_buffer(); + build_process(*process); + return array.serialized().to_byte_buffer(); } ByteBuffer procfs$inodes(InodeIdentifier) diff --git a/Kernel/Makefile b/Kernel/Makefile index cd90d8c48a..74d5dbc623 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -84,6 +84,10 @@ AK_OBJS = \ ../AK/StringView.o \ ../AK/FileSystemPath.o \ ../AK/StdLibExtras.o \ + ../AK/JsonObject.o \ + ../AK/JsonValue.o \ + ../AK/JsonArray.o \ + ../AK/JsonParser.o \ ../AK/ELF/ELFImage.o \ ../AK/ELF/ELFLoader.o diff --git a/Servers/WindowServer/WSCPUMonitor.cpp b/Servers/WindowServer/WSCPUMonitor.cpp index 71a3e6a234..3dccde4f2e 100644 --- a/Servers/WindowServer/WSCPUMonitor.cpp +++ b/Servers/WindowServer/WSCPUMonitor.cpp @@ -1,3 +1,6 @@ +#include <AK/JsonArray.h> +#include <AK/JsonObject.h> +#include <AK/JsonValue.h> #include <WindowServer/WSCPUMonitor.h> #include <WindowServer/WSEventLoop.h> #include <WindowServer/WSWindowManager.h> @@ -37,25 +40,17 @@ void WSCPUMonitor::get_cpu_usage(unsigned& busy, unsigned& idle) idle = 0; m_proc_all.seek(0); - for (;;) { - auto line = m_proc_all.read_line(BUFSIZ); - if (line.is_null()) - break; - auto chomped = String((const char*)line.pointer(), line.size() - 1, Chomp); - auto parts = chomped.split_view(','); - if (parts.size() < 18) - break; - bool ok; - pid_t pid = parts[0].to_uint(ok); - ASSERT(ok); - unsigned nsched = parts[1].to_uint(ok); - ASSERT(ok); - + auto file_contents = m_proc_all.read_all(); + auto json = JsonValue::from_string({ file_contents.data(), file_contents.size() }); + json.as_array().for_each([&](auto& value) { + const JsonObject& process_object = value.as_object(); + pid_t pid = process_object.get("pid").to_dword(); + unsigned nsched = process_object.get("times_scheduled").to_dword(); if (pid == 0) idle += nsched; else busy += nsched; - } + }); } void WSCPUMonitor::paint(Painter& painter, const Rect& rect) diff --git a/Userland/top.cpp b/Userland/top.cpp index aeebd98622..defa0efa8e 100644 --- a/Userland/top.cpp +++ b/Userland/top.cpp @@ -1,7 +1,11 @@ #include <AK/AKString.h> #include <AK/HashMap.h> +#include <AK/JsonArray.h> +#include <AK/JsonObject.h> +#include <AK/JsonValue.h> #include <AK/QuickSort.h> #include <AK/Vector.h> +#include <LibCore/CFile.h> #include <fcntl.h> #include <pwd.h> #include <stdio.h> @@ -31,44 +35,33 @@ struct Snapshot { static Snapshot get_snapshot() { - Snapshot snapshot; - - FILE* fp = fopen("/proc/all", "r"); - if (!fp) { - perror("failed to open /proc/all"); + CFile file("/proc/all"); + if (!file.open(CIODevice::ReadOnly)) { + fprintf(stderr, "Failed to open /proc/all: %s\n", file.error_string()); exit(1); } - for (;;) { - char buf[4096]; - char* ptr = fgets(buf, sizeof(buf), fp); - if (!ptr) - break; - auto parts = String(buf, Chomp).split(','); - if (parts.size() < 17) - break; - bool ok; - pid_t pid = parts[0].to_uint(ok); - ASSERT(ok); - unsigned nsched = parts[1].to_uint(ok); - ASSERT(ok); + + Snapshot snapshot; + + auto file_contents = file.read_all(); + auto json = JsonValue::from_string({ file_contents.data(), file_contents.size() }); + json.as_array().for_each([&](auto& value) { + const JsonObject& process_object = value.as_object(); + pid_t pid = process_object.get("pid").to_dword(); + unsigned nsched = process_object.get("times_scheduled").to_dword(); snapshot.sum_nsched += nsched; Process process; process.pid = pid; process.nsched = nsched; - unsigned uid = parts[5].to_uint(ok); - ASSERT(ok); + unsigned uid = process_object.get("uid").to_dword(); process.user = s_usernames->get(uid); - process.priority = parts[16]; - process.state = parts[7]; - process.name = parts[11]; - process.virtual_size = parts[12].to_uint(ok); - ASSERT(ok); - process.physical_size = parts[13].to_uint(ok); - ASSERT(ok); + process.priority = process_object.get("priority").to_string(); + process.state = process_object.get("state").to_string(); + process.name = process_object.get("name").to_string(); + process.virtual_size = process_object.get("amount_virtual").to_dword(); + process.physical_size = process_object.get("amount_resident").to_dword(); snapshot.map.set(pid, move(process)); - } - int rc = fclose(fp); - ASSERT(rc == 0); + }); return snapshot; } |