ohmu
·
2026-10-15
1#include "top.h"
2
3#include <hurd.h>
4#include <string.h>
5#include <ps.h>
6
7const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
8 struct ps_context* context = nullptr;
9 if (ps_context_create(getproc(), &context) != 0) {
10 return "ps_context_create(getproc()) failed";
11 }
12
13 const char* error = nullptr;
14 struct proc_stat_list* list = nullptr;
15 if (proc_stat_list_create(context, &list) != 0) {
16 error = "proc_stat_list_create() failed";
17 goto done;
18 }
19
20 if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) {
21 error = "proc_stat_list_add_all() failed";
22 goto done;
23 }
24
25 // Flags that cannot be fetched for some process are simply left unset;
26 // each field must be checked before use.
27 if (proc_stat_list_set_flags(list, PSTAT_ARGS | PSTAT_STATE | PSTAT_TASK_BASIC | ((showTypes & FF_TOP_TYPE_THREADS) ? PSTAT_NUM_THREADS : 0)) != 0) {
28 error = "proc_stat_list_set_flags() failed";
29 goto done;
30 }
31
32 for (unsigned i = 0; i < list->num_procs; ++i) {
33 struct proc_stat* stat = list->proc_stats[i];
34
35 if (!proc_stat_has(stat, PSTAT_PID | PSTAT_STATE)) {
36 continue;
37 }
38 if (proc_stat_state(stat) & PSTAT_STATE_P_ZOMBIE) {
39 continue;
40 }
41
42 uint32_t pid = (uint32_t) proc_stat_pid(stat);
43 if (pid == 2) { // Kernel Task
44 continue;
45 }
46
47 FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
48
49 // There is no kernel-side comm on the Hurd; use the first argument.
50 ffStrbufInit(&item->name);
51 if (proc_stat_has(stat, PSTAT_ARGS) && proc_stat_args(stat)) {
52 size_t len = strnlen(proc_stat_args(stat), proc_stat_args_len(stat));
53 ffStrbufAppendNS(&item->name, (uint32_t) len, proc_stat_args(stat));
54 }
55 if (item->name.length == 0) {
56 ffStrbufAppendS(&item->name, "(unknown)");
57 }
58
59 item->pid = pid;
60 item->cpuTime = 0;
61 item->memBytes = 0;
62 item->startTime = 0;
63 item->threads = 0;
64
65 if (showTypes & FF_TOP_TYPE_THREADS) {
66 if (proc_stat_has(stat, PSTAT_NUM_THREADS)) {
67 item->threads = (uint32_t) proc_stat_num_threads(stat);
68 }
69 }
70
71 if (proc_stat_has(stat, PSTAT_TASK_BASIC)) {
72 const task_basic_info_t info = proc_stat_task_basic_info(stat);
73 item->cpuTime = (uint64_t) info->user_time64.seconds * 1000 +
74 (uint64_t) info->user_time64.nanoseconds / 1000000 +
75 (uint64_t) info->system_time64.seconds * 1000 +
76 (uint64_t) info->system_time64.nanoseconds / 1000000;
77 item->memBytes = (uint64_t) info->resident_size;
78 item->startTime = (uint64_t) info->creation_time64.seconds * 1000 +
79 (uint64_t) info->creation_time64.nanoseconds / 1000000;
80 }
81
82 // Storage io counters aren't exposed by kernel; leave them zeroed.
83 item->bytesRead = 0;
84 item->bytesWritten = 0;
85 }
86
87done:
88 if (list) {
89 proc_stat_list_free(list);
90 }
91 ps_context_free(context);
92 return error;
93}