Processes.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/JsonObjectSerializer.h>
  7. #include <AK/Try.h>
  8. #include <Kernel/FileSystem/SysFS/Subsystems/Kernel/Processes.h>
  9. #include <Kernel/Process.h>
  10. #include <Kernel/Scheduler.h>
  11. #include <Kernel/Sections.h>
  12. #include <Kernel/TTY/TTY.h>
  13. namespace Kernel {
  14. UNMAP_AFTER_INIT SysFSOverallProcesses::SysFSOverallProcesses(SysFSDirectory const& parent_directory)
  15. : SysFSGlobalInformation(parent_directory)
  16. {
  17. }
  18. UNMAP_AFTER_INIT NonnullRefPtr<SysFSOverallProcesses> SysFSOverallProcesses::must_create(SysFSDirectory const& parent_directory)
  19. {
  20. return adopt_ref_if_nonnull(new (nothrow) SysFSOverallProcesses(parent_directory)).release_nonnull();
  21. }
  22. ErrorOr<void> SysFSOverallProcesses::try_generate(KBufferBuilder& builder)
  23. {
  24. auto json = TRY(JsonObjectSerializer<>::try_create(builder));
  25. // Keep this in sync with CProcessStatistics.
  26. auto build_process = [&](JsonArraySerializer<KBufferBuilder>& array, Process const& process) -> ErrorOr<void> {
  27. auto process_object = TRY(array.add_object());
  28. if (process.is_user_process()) {
  29. StringBuilder pledge_builder;
  30. #define __ENUMERATE_PLEDGE_PROMISE(promise) \
  31. if (process.has_promised(Pledge::promise)) \
  32. TRY(pledge_builder.try_append(#promise " "sv));
  33. ENUMERATE_PLEDGE_PROMISES
  34. #undef __ENUMERATE_PLEDGE_PROMISE
  35. TRY(process_object.add("pledge"sv, pledge_builder.string_view()));
  36. switch (process.veil_state()) {
  37. case VeilState::None:
  38. TRY(process_object.add("veil"sv, "None"));
  39. break;
  40. case VeilState::Dropped:
  41. TRY(process_object.add("veil"sv, "Dropped"));
  42. break;
  43. case VeilState::Locked:
  44. TRY(process_object.add("veil"sv, "Locked"));
  45. break;
  46. case VeilState::LockedInherited:
  47. // Note: We don't reveal if the locked state is either by our choice
  48. // or someone else applied it.
  49. TRY(process_object.add("veil"sv, "Locked"));
  50. break;
  51. }
  52. } else {
  53. TRY(process_object.add("pledge"sv, ""sv));
  54. TRY(process_object.add("veil"sv, ""sv));
  55. }
  56. TRY(process_object.add("pid"sv, process.pid().value()));
  57. ProcessGroupID tty_pgid = 0;
  58. if (auto tty = process.tty())
  59. tty_pgid = tty->pgid();
  60. TRY(process_object.add("pgid"sv, tty_pgid.value()));
  61. TRY(process_object.add("pgp"sv, process.pgid().value()));
  62. TRY(process_object.add("sid"sv, process.sid().value()));
  63. auto credentials = process.credentials();
  64. TRY(process_object.add("uid"sv, credentials->uid().value()));
  65. TRY(process_object.add("gid"sv, credentials->gid().value()));
  66. TRY(process_object.add("ppid"sv, process.ppid().value()));
  67. if (process.tty()) {
  68. auto tty_pseudo_name = TRY(process.tty()->pseudo_name());
  69. TRY(process_object.add("tty"sv, tty_pseudo_name->view()));
  70. } else {
  71. TRY(process_object.add("tty"sv, ""));
  72. }
  73. TRY(process_object.add("nfds"sv, process.fds().with_shared([](auto& fds) { return fds.open_count(); })));
  74. TRY(process.name().with([&](auto& process_name) { return process_object.add("name"sv, process_name->view()); }));
  75. TRY(process_object.add("executable"sv, process.executable() ? TRY(process.executable()->try_serialize_absolute_path())->view() : ""sv));
  76. size_t amount_virtual = 0;
  77. size_t amount_resident = 0;
  78. size_t amount_dirty_private = 0;
  79. size_t amount_clean_inode = 0;
  80. size_t amount_shared = 0;
  81. size_t amount_purgeable_volatile = 0;
  82. size_t amount_purgeable_nonvolatile = 0;
  83. TRY(process.address_space().with([&](auto& space) -> ErrorOr<void> {
  84. amount_virtual = space->amount_virtual();
  85. amount_resident = space->amount_resident();
  86. amount_dirty_private = space->amount_dirty_private();
  87. amount_clean_inode = TRY(space->amount_clean_inode());
  88. amount_shared = space->amount_shared();
  89. amount_purgeable_volatile = space->amount_purgeable_volatile();
  90. amount_purgeable_nonvolatile = space->amount_purgeable_nonvolatile();
  91. return {};
  92. }));
  93. TRY(process_object.add("amount_virtual"sv, amount_virtual));
  94. TRY(process_object.add("amount_resident"sv, amount_resident));
  95. TRY(process_object.add("amount_dirty_private"sv, amount_dirty_private));
  96. TRY(process_object.add("amount_clean_inode"sv, amount_clean_inode));
  97. TRY(process_object.add("amount_shared"sv, amount_shared));
  98. TRY(process_object.add("amount_purgeable_volatile"sv, amount_purgeable_volatile));
  99. TRY(process_object.add("amount_purgeable_nonvolatile"sv, amount_purgeable_nonvolatile));
  100. TRY(process_object.add("dumpable"sv, process.is_dumpable()));
  101. TRY(process_object.add("kernel"sv, process.is_kernel_process()));
  102. auto thread_array = TRY(process_object.add_array("threads"sv));
  103. TRY(process.try_for_each_thread([&](const Thread& thread) -> ErrorOr<void> {
  104. SpinlockLocker locker(thread.get_lock());
  105. auto thread_object = TRY(thread_array.add_object());
  106. #if LOCK_DEBUG
  107. TRY(thread_object.add("lock_count"sv, thread.lock_count()));
  108. #endif
  109. TRY(thread_object.add("tid"sv, thread.tid().value()));
  110. TRY(thread.name().with([&](auto& thread_name) { return thread_object.add("name"sv, thread_name->view()); }));
  111. TRY(thread_object.add("times_scheduled"sv, thread.times_scheduled()));
  112. TRY(thread_object.add("time_user"sv, thread.time_in_user()));
  113. TRY(thread_object.add("time_kernel"sv, thread.time_in_kernel()));
  114. TRY(thread_object.add("state"sv, thread.state_string()));
  115. TRY(thread_object.add("cpu"sv, thread.cpu()));
  116. TRY(thread_object.add("priority"sv, thread.priority()));
  117. TRY(thread_object.add("syscall_count"sv, thread.syscall_count()));
  118. TRY(thread_object.add("inode_faults"sv, thread.inode_faults()));
  119. TRY(thread_object.add("zero_faults"sv, thread.zero_faults()));
  120. TRY(thread_object.add("cow_faults"sv, thread.cow_faults()));
  121. TRY(thread_object.add("file_read_bytes"sv, thread.file_read_bytes()));
  122. TRY(thread_object.add("file_write_bytes"sv, thread.file_write_bytes()));
  123. TRY(thread_object.add("unix_socket_read_bytes"sv, thread.unix_socket_read_bytes()));
  124. TRY(thread_object.add("unix_socket_write_bytes"sv, thread.unix_socket_write_bytes()));
  125. TRY(thread_object.add("ipv4_socket_read_bytes"sv, thread.ipv4_socket_read_bytes()));
  126. TRY(thread_object.add("ipv4_socket_write_bytes"sv, thread.ipv4_socket_write_bytes()));
  127. TRY(thread_object.finish());
  128. return {};
  129. }));
  130. TRY(thread_array.finish());
  131. TRY(process_object.finish());
  132. return {};
  133. };
  134. {
  135. auto array = TRY(json.add_array("processes"sv));
  136. // FIXME: Do we actually want to expose the colonel process in a Jail environment?
  137. TRY(build_process(array, *Scheduler::colonel()));
  138. TRY(Process::for_each_in_same_jail([&](Process& process) -> ErrorOr<void> {
  139. TRY(build_process(array, process));
  140. return {};
  141. }));
  142. TRY(array.finish());
  143. }
  144. auto total_time_scheduled = Scheduler::get_total_time_scheduled();
  145. TRY(json.add("total_time"sv, total_time_scheduled.total));
  146. TRY(json.add("total_time_kernel"sv, total_time_scheduled.total_kernel));
  147. TRY(json.finish());
  148. return {};
  149. }
  150. }