master ohmu/fastfetch-openbsd / src / detection / top / top_dbsd.c
ohmu  ·  2026-10-15
 1#include "top.h"
 2#include "common/mallocHelper.h"
 3
 4#include <sys/types.h>
 5#include <sys/resource.h>
 6#include <sys/sysctl.h>
 7#include <sys/user.h>
 8
 9const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) {
10    int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
11    size_t length;
12
13    if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) {
14        return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, nullptr}) failed";
15    }
16
17    // The process table may change between the two sysctl calls; retry with a larger buffer.
18    length += length / 8 + sizeof(struct kinfo_proc);
19
20    FF_AUTO_FREE struct kinfo_proc* processes = malloc(length);
21    if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) {
22        return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL, processes}) failed";
23    }
24    uint32_t count = (uint32_t) (length / sizeof(struct kinfo_proc));
25
26    const uint32_t pageSizeShift = instance.state.platform.sysinfo.pageSizeShift;
27
28    for (uint32_t i = 0; i < count; ++i) {
29        const struct kinfo_proc* proc = &processes[i];
30
31        // KERN_PROC_ALL won't return kernel threads
32        if (proc->kp_stat == SZOMB) { // Ignore zombie processes
33            continue;
34        }
35
36        FFTopProcessSnapshot* item = FF_LIST_ADD(FFTopProcessSnapshot, *snapshots);
37
38        ffStrbufInitS(&item->name, proc->kp_comm);
39        item->pid = (uint32_t) proc->kp_pid;
40
41        // kp_ru only accounts for exited lwps; the cpu times of live lwps are
42        // kept in microseconds in kp_lwp.kl_uticks/kl_sticks (see calcru(9)).
43        uint64_t exitedMs = (uint64_t) (proc->kp_ru.ru_utime.tv_sec + proc->kp_ru.ru_stime.tv_sec) * 1000 +
44            (uint64_t) (proc->kp_ru.ru_utime.tv_usec + proc->kp_ru.ru_stime.tv_usec) / 1000;
45        uint64_t liveMs = (proc->kp_lwp.kl_uticks + proc->kp_lwp.kl_sticks) / 1000;
46        item->cpuTime = exitedMs + liveMs;
47
48        item->memBytes = (uint64_t) proc->kp_vm_rssize << pageSizeShift;
49
50        item->startTime = (uint64_t) proc->kp_start.tv_sec * 1000 +
51            (uint64_t) proc->kp_start.tv_usec / 1000;
52
53        item->bytesRead = (uint64_t) (proc->kp_ru.ru_inblock + proc->kp_lwp.kl_ru.ru_inblock) * DEV_BSIZE;
54        item->bytesWritten = (uint64_t) (proc->kp_ru.ru_oublock + proc->kp_lwp.kl_ru.ru_oublock) * DEV_BSIZE;
55        item->threads = (uint32_t) proc->kp_nthreads;
56    }
57
58    return nullptr;
59}