master ohmu/fastfetch-openbsd / src / detection / top / top_bsd.c
ohmu  ·  2026-10-15
 1#include "top.h"
 2#include "common/debug.h"
 3#include "common/mallocHelper.h"
 4
 5#include <errno.h>
 6#include <string.h>
 7
 8#include <sys/types.h>
 9#include <sys/resource.h>
10#include <sys/sysctl.h>
11#include <sys/user.h>
12
13const char* ffTopGetProcessSnapshot(FFlist* snapshots, [[maybe_unused]] FFTopTypes showTypes) {
14    int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC };
15    size_t length;
16
17    if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) {
18        FF_DEBUG("sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}, nullptr) failed: %s", strerror(errno));
19        return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed";
20    }
21
22    // The process table may change between the two sysctl calls; retry with a larger buffer.
23    length += length / 8 + sizeof(struct kinfo_proc);
24    FF_AUTO_FREE struct kinfo_proc* processes = malloc(length);
25    if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) {
26        FF_DEBUG("sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}, processes) failed: %s", strerror(errno));
27        return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed";
28    }
29    uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc));
30
31    const uint32_t pageSizeShift = instance.state.platform.sysinfo.pageSizeShift;
32
33    for (uint32_t i = 0; i < count; ++i) {
34        const struct kinfo_proc* proc = &processes[i];
35
36        if (proc->ki_flag & P_KPROC) {
37            continue;
38        }
39
40        uint32_t pid = (uint32_t) proc->ki_pid;
41
42        FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
43
44        ffStrbufInitS(&item->name, proc->ki_comm);
45        item->pid = pid;
46
47        uint64_t userMs = (uint64_t) proc->ki_rusage.ru_utime.tv_sec * 1000 +
48            (uint64_t) proc->ki_rusage.ru_utime.tv_usec / 1000;
49        uint64_t sysMs = (uint64_t) proc->ki_rusage.ru_stime.tv_sec * 1000 +
50            (uint64_t) proc->ki_rusage.ru_stime.tv_usec / 1000;
51        item->cpuTime = userMs + sysMs;
52
53        item->memBytes = (uint64_t) proc->ki_rssize << pageSizeShift;
54
55        item->startTime = (uint64_t) proc->ki_start.tv_sec * 1000 +
56            (uint64_t) proc->ki_start.tv_usec / 1000;
57
58        item->bytesRead = (uint64_t) proc->ki_rusage.ru_inblock * DEV_BSIZE;
59        item->bytesWritten = (uint64_t) proc->ki_rusage.ru_oublock * DEV_BSIZE;
60        item->threads = (uint32_t) proc->ki_numthreads;
61    }
62
63    return NULL;
64}