| 121 | } |
| 122 | |
| 123 | ByteBuf format_global_threads(const Engine& eng) { |
| 124 | std::string out; |
| 125 | out.reserve(64 * 1024); |
| 126 | std::size_t total = 0; |
| 127 | for (const auto& p : eng.processes()) total += 1; // upper bound only |
| 128 | |
| 129 | out += "# /sys/processes/threads.txt — every thread of every visible process\n" |
| 130 | "# Walks each leader's signal->thread_head. \"TID\" is the kernel's\n" |
| 131 | "# per-thread pid; TGID is the leader's pid.\n" |
| 132 | "#\n" |
| 133 | "# TID TGID state comm\n" |
| 134 | "# ------- ------- --------------------- ----------------\n"; |
| 135 | std::size_t real_threads = 0; |
| 136 | for (const auto& leader : eng.processes()) { |
| 137 | std::vector<ThreadInfo> ts; |
| 138 | try { ts = enumerate_threads(eng, leader); } |
| 139 | catch (...) { continue; } |
| 140 | real_threads += ts.size(); |
| 141 | for (const auto& t : ts) { |
| 142 | out += fmt::format(" {:>6} {:>6} {:<22} {}\n", |
| 143 | t.pid, t.tgid, state_name(t.state), t.comm); |
| 144 | } |
| 145 | } |
| 146 | // Prepend the real total now that we know it. |
| 147 | std::string hdr = fmt::format( |
| 148 | "# Total: {} threads across {} thread-group leaders\n#\n", |
| 149 | real_threads, eng.processes().size()); |
| 150 | std::string combined = hdr + out; |
| 151 | return ByteBuf(combined.begin(), combined.end()); |
| 152 | } |
| 153 | |
| 154 | } // namespace lmpfs::linux |
no test coverage detected