Repository navigation
[AI generated] illumos/Solaris platform support - #1845
agorouvein-rgb wants to merge 11 commits into
Conversation
Adds a new src/openindiana/ backend implementing Shared, Cpu, Mem,
Net, and Proc data collection against illumos-native APIs, replacing
FreeBSD's kvm(3)/sysctl(3)/devstat(3) mechanisms this backend was
originally copied from:
- CPU stats: kstat(3KSTAT) cpu_stat per-core counters
- Memory: kstat unix:system_pages + ZFS ARC size (kstat zfs:arcstats)
- Swap: native swapctl(2), no kvm handle required
- Filesystem enumeration: getmntent(3C) reading /etc/mnttab
- Disk I/O: kstat_io_t enumeration by ks_class=="disk"
- Network: kstat per-link rbytes64/obytes64, looked up by interface
name (module "link", class "net")
- Process enumeration: /proc/<pid>/psinfo (psinfo_t), replacing the
kvm_getprocs()/kvm_getargv() process-table walk
Also includes two small portability fixes to shared, non-platform
files:
- src/btop.cpp: extend the existing pthread_join() fallback (already
used for __APPLE__/__OpenBSD__/__NetBSD__) to __sun, since
pthread_timedjoin_np() is a GNU/glibc extension unavailable on
illumos
- Makefile: add a sunos/openindiana PLATFORM_DIR block matching the
existing per-platform pattern, linking -lkstat -lproc -lsocket -lnsl
Known limitations:
- ZFS per-dataset disk I/O is not separated; all physical disk I/O
is attributed to the root ("/") mountpoint, since illumos ZFS
mounts report the dataset name rather than a physical device path
in /etc/mnttab. True per-dataset attribution likely requires
illumos's per-dataset zfs kstats, not yet investigated.
- pr_psargs truncates long command lines to PRARGSZ (~80 chars);
full argv reconstruction via libproc's proc_arg_grab() is a
possible follow-up.
- CPU temperature, frequency, and battery reporting are stubbed
(return empty/false/no-op), not yet implemented.
- get_cpuName() currently returns an empty string.
Built and tested in a VirtualBox VM running OpenIndiana Hipster
2026.04, GCC 14.3.0. Not yet tested on bare metal.
…e network collection without getifaddrs(), add optional Solaris 10 compat shim (S10=true)
…as to avoid sys/buf.h collision on native Solaris, portable thread count and source discovery, make -static-libstdc++ opt-in (S10=true)
|
Hey, really nice'; cheers. Compiled directly using gmake. I've got OI running on Linux using VirtualBox . I've also tried running it though valgrind; but had to stop as it took for ever. But, in general, btop is very responsive which is good. Would be nice to test it on bare-metal, i.e, ssh on to a sparc machine. I'll do further testing tomorrow evening and check memory and have a look at the code. |
…upstream's short display form) and per-process I/O (pr_ioch; Solaris's pr_inblk/pr_oublk are documented as unreliable and unused, so IO/R shows the combined total and IO/W is left blank rather than a false zero)
|
Hey @mebenn Thanks for the detailed testing, especially catching the IO/R and IO/W issue — that one wasn't actually documented anywhere, so genuinely good find. Both are fixed and pushed: CPU hardware name: now pulled from the IO/R and IO/W: these were dead code left over from a macOS-derived stub, now implemented via Both tested and confirmed working on OpenIndiana. More broadly (not specific to this latest commit, but worth mentioning for context): the port has also been confirmed on bare metal — an old Acer laptop running current OI — and independently by a mailing-list contributor who compiled and ran it on a T8-1 with 64 SPARC cores. |
|
Oh, thanks for the fix; fetched merged, compiled and ran and IO/R and W and CPU details correctly displayed
I've randomly checked the numers on some of the processes against the ptools commands and they would appear to be correct. So things are looking good. Hopefully at the weekend I'll do some deep diving. If there's anything specific you'd like me to check (I'm using OpenIndiana in a VirtualBox on Debian with Ryzen), just let me know. |
|
Is CMakeLists.txt ok in this PR? This afternoon I pulled the PR into the openindiana branch but it did not compile: 'SunOS is not supported'. So cmake worked, gmake compillled and is now working and showing infos about my AMD CPUs. Am I doing something wrong here? |
…'SunOS is not supported'); link kstat/socket/nsl, consistent with the Makefile
|
Good catch — you're right, and I see exactly why: this PR only ever updated the Makefile, Fixed and pushed now — added a
Built and tested cleanly on OI via |
|
Good, I'll update to your version: we don't want different versions flying about. I linked in libkstat.so as there is only one implementation for the kstat.h interface. In the makefile this is easy to do as we could to a uname -a and parse out the version of Solaris; this is probably possible for CMakeLists.txt; or, if that doesn't work, require a cmake -DS10. |
|
Appreciate you aligning on the libs — agreed, one tested combination is better than two. And no concern at all on the valgrind side; that sounds like the right call (file the upstream bug, let it run properly over time rather than force-killing it). Let us know what the long-run memory check turns up whenever you get to it. On S10: I don't think it's a waste of time to ask, but I think the Solaris 10 has no C++23-capable compiler at all, so there's no such thing as running Separately — worth untangling since your SPARC question conflates two unrelated things: S10 here means Solaris 10 x86, and the shim is x86-specific (a handful of missing libc functions, nothing architecture-level). Peter Tribble's SPARC testing was Solaris 11.4, which has its own modern toolchain and needs no shim at all — so SPARC users are already covered, separately, and get no benefit from S10 support either way. A hypothetical Solaris 10 on SPARC would be a third, completely untested situation — different ABI, and I have no idea whether the current shim's approach would even apply there. Worth being upfront too: the S10 x86 path itself has only been tested in a VMware VM, not on real hardware — I don't have access to actual Solaris 10 hardware, and as far as I know neither does anyone else who's tested this PR. Given all that, I don't think it's worth chasing a CMake equivalent right now — not something either of us has the appetite or the hardware to properly verify at the moment. The Makefile path covers it for anyone who needs it. |
|
I've noticed another flaw: CPU frequency, which should appear on the right of the CPU type. I added this feature and added the code to your branch of openindiana-support. You can get it here: I'm not sure whether I've implemented everything correctly and I'm unsure whether this will work on all different type of hardware: Sparc??? If you've got other VMs with different systems (Solaris 10/11, SPARC, Intel, ...) it would be very helpful if you were able to run it on each system and activate logging. Then send me the logging. Here's how to activate logging: It looks stable oon my machine and I still have to run the long term memory test (thought this missing feature was more important.) |
|
Thanks for this, good catch on the missing frequency. Pulling from Codeberg worked fine, no need to move it to GitHub. I merged your commit as-is so it keeps your authorship, then added a follow-up commit on top that changes a few things in
Tested on:
So the A reminder on SPARC, since it keeps coming up: the SPARC support here means Solaris 11 on SPARC, built natively there with its own modern GCC (Peter's T8-1). Solaris 8 and 9 on SPARC won't work at all. They have no C++23-capable compiler, there's no practical way to cross-build for SPARC from an x86 illumos host, and the S10 compat shim is x86-only anyway. Solaris 10 on SPARC is untested and would be a separate project. On the logging instructions: the setting in Thanks again, and good luck with the memory test. |
…close kstat handle, prefer current_clock_Hz over clock_MHz, format like Linux (e.g. 2.5 GHz)
|
I've noticed another flaw: CPU frequency, which should appear on the right of the CPU type. I added this feature and added the code to your branch of openindiana-support. You can get it here: I'm not sure whether I've implemented everything correctly and I'm unsure whether this will work on all different type of hardware: Sparc??? If you've got other VMs with different systems (Solaris 10/11, SPARC, Intel, ...) it would be very helpful if you were able to run it on each system and activate logging. Then send me the logging. Here's how to activate logging: It looks stable oon my machine and I still have to run the long term memory test (thought this missing feature was more important.) |
|
Ah, thanks. The code, debugging info, etc. were all only temporary, I had expected this commit to be squashed later on. I only know enough about kstat as from the 3KSTAT man page and kstat.h; and I didn't know how to 'aggregate' all CPUs together and take an average? (There is only one display field for it in btop, I think). The only other place to look would be in the Illumos src code. Have you had access to other sources of kstat.h info? That is interesting (and weird) with the SPARC CPU numeration, or is that a SUN SPARC scheme as opposed to an Illumos SPARC CPU numbering scheme. Wouldn't help if these differed, but if you loop through all cpu_infos, you should be ok. I had intended to throw nearly all of the get_cpuHz() logging away (as I hadn't a clue about whether i32 was correct over the data field). The logging should maybe be better geared towards new, unknown systems maybe. |
|
Thanks for your contribution. I decided to abandon this project, since I am not a developer and all the code for this pull was written by Claude. According to the updated rules from btop author, this pull will never be merged. You are welcome to continue on your own. |


[AI generated] — drafted with Claude, reviewed, tested, and debugged by me on real hardware/VMs at every step. See the "How this was built" note at the bottom for full transparency.
Summary
Adds a new
src/sunos/backend (originallysrc/openindiana/, renamed since the backend is generic across illumos distributions and Solaris, not OpenIndiana-specific) implementingShared,Cpu,Mem,Net, andProcdata collection against illumos-native APIs, with optional support for Solaris 10 x86. This backend started as a copy ofsrc/freebsd/, with every FreeBSD-specific mechanism (kvm(3),sysctl(3),devstat(3)) replaced by illumos equivalents:kstat(3KSTAT)cpu_statper-core counters, discovered by walking the live kstat chain rather than probing instance numbers 0..N-1 (CPU ids are not guaranteed contiguous or zero-based — confirmed on SPARC, where a 64-CPU system reported ids 64-127)cpu_infokstat (brandon x86, falling back toimplementationelsewhere), then cleaned up the same way upstream's Linux backend does — strips boilerplate (Intel(R),Core(TM), aCPU @ x.xxGHzsuffix, etc.) down to just the model namekstat unix:system_pages+ ZFS ARC size (kstat zfs:arcstats), used to derive used/available/cached the way Linux/FreeBSD treat page cacheswapctl(2)— nokvmhandle requiredgetmntent(3C)reading/etc/mnttab, filtering out pseudo-mounts (vmblock,vmhgfs, etc.)kstat_io_tenumeration byks_class=="disk"kstatper-linkrbytes64/obytes64, looked up directly by interface name (module"link", class"net"). Interface enumeration usesSIOCGLIFCONFrather thangetifaddrs(), which doesn't exist on Solaris 10./proc/<pid>/psinfo(psinfo_t), replacingkvm_getprocs()/kvm_getargv()/proc/<pid>/usage(prusage_t). Solaris/illumos's per-direction counters (pr_inblk/pr_oublk) are a long-documented dead end — they don't reliably track actual I/O volume regardless of platform or workload — sopr_ioch(a combined read+write character count) is used instead; see Known limitations below.Also includes portability fixes to shared, non-platform files:
src/btop.cpp: extends the existingpthread_join()fallback (already used for__APPLE__/__OpenBSD__/__NetBSD__) to__sun, sincepthread_timedjoin_np()is a GNU/glibc extension unavailable on illumos.src/btop.cpp: fixes a crash on terminal resize.signal()has one-shot (System V) semantics on illumos/Solaris — handlers reset to default after their first delivery. btop usesSIGWINCH/SIGUSR1to interrupt its input loop, so a second resize (or a second Ctrl-C/Ctrl-Z) during a session could kill the process outright, with no core dump or log entry. Signal handlers on this platform are now installed viasigaction()for persistent, BSD-style semantics. This affected every illumos/Solaris build, not just Solaris 10.src/sunos/btop_collect.cpp: the file-localnamespace fs = std::filesystem;alias is renamed tobtop_fs, since native Solaris's<sys/buf.h>(pulled in transitively by some of the headers this backend uses) declares its ownfsat file scope and collides with it. illumos doesn't hit this, which is why it wasn't caught earlier.Makefile: adds asunosPLATFORM_DIRblock matching the existing per-platform pattern, linking-lkstat -lsocket -lnsl. Source-file discovery now uses GNU Make's built-in$(wildcard ...)instead of shelling out tofind -maxdepth, which native Solaris'sfinddoesn't support. Thread count detection now triespsrinfofirst, falling back togetconf NPROCESSORS_ONLNonly if that's empty, since the latter alone has been reported as unrecognized on at least one native Solaris configuration (silently serializing the build).-static-libstdc++is no longer forced by default — Oracle Solaris ships no static libstdc++ at all — and is now opt-in viaS10=true(see below), which is the only case that actually needs it.Solaris 10 x86 support (optional,
S10=true)Solaris 10 has no C++23-capable compiler, so binaries are cross-built on an illumos system with a modern GCC and run on Solaris 10 itself. That requires a small number of libc functions Solaris 10 lacks (mostly POSIX 2008 locale functions, plus a few small helpers like
clock_gettime/nanosleep, which live inlibrtrather than libc there). These are provided by an optional compatibility shim,src/sunos/s10compat.c, compiled and linked in only withS10=true; the defaultsunosbuild doesn't touch it. It's inert unless explicitly requested.Known limitations
/) mountpoint, since illumos ZFS mounts report the dataset name rather than a physical device path in/etc/mnttab. True per-dataset attribution likely requires illumos's per-dataset ZFS kstats, not yet investigated.pr_psargstruncates long command lines toPRARGSZ(~80 chars); full argv reconstruction vialibproc'sproc_arg_grab()is a possible follow-up.0 Byte, since Solaris/illumos has no reliable way to report the two directions separately (see above).implementationstrings, so minor cosmetic artifacts (e.g. a stray trailing character) are possible there.Testing
Built and tested in a VirtualBox VM running OpenIndiana Hipster 2026.04, GCC 14.3.0, and on bare metal (Acer Aspire V5-571, same OI release, using the built-in Realtek RTL8111 Ethernet as
rge0). Bare-metal testing included running btop continuously in a MATE Terminal session while connecting in over SSH from a separate OI VM and running a package install (pkg install fastfetch), exercising real CPU, disk, and network activity end-to-end rather than synthetic load. (Aside, for anyone else with this model: the built-in Atheros AR9462 wifi is not supported by illumos'sarndriver, which only covers AR9280/9281/9285 — Ethernet works fine.)Solaris 10 (1/13, x86, 64-bit kernel) tested separately, cross-built from the OpenIndiana host per the
S10=trueprocess above.All of Peter Tribble's review feedback (thank you again) has been addressed and tested, including a retest on his own hardware:
fs/sys/buf.hcollision on native Solaris — fixed, renamed tobtop_fs; confirmed by the same native Solaris 11.4 build.find/getconf NPROCESSORS_ONLNbuild portability — fixed; confirmed by the same native Solaris 11.4 build.-static-libstdc++forced unconditionally — now opt-in, off by default, only added for the Solaris 10 cross-build (S10=true); dropping it by default is what let the native Solaris 11.4 build succeed.A second reviewer additionally caught that the per-process IO/R and IO/W fields were always blank (dead code left over from the FreeBSD-derived backend's macOS-originated stub) and that the CPU box showed no hardware name. Both are now implemented per the Summary above and confirmed working on OpenIndiana (VM and bare metal, including sustained raw-device I/O to verify
pr_iochactually tracks real activity).Also tested on OmniOS (a QEMU VM,
vioif0/virtio networking) by a tester from a retro-computing community, confirming the backend works on a second illumos distribution beyond OpenIndiana — different hypervisor, different NIC driver, different userland (SMB/NFS services running). Screenshot below. This was also an unplanned but useful test of the CPU-name cleanup logic against a completely different brand-string shape (QEMU Virtual CPU version 2.5), which it handled correctly.Still not tested: SmartOS, and native (non-cross-built) compilation on Solaris 10, which has no C++23-capable compiler and so isn't expected to support a native build at all.
How this was built
I don't have a C++ background, but I am a software tester with 30+ years of experience in the software industry. I worked through this interactively with Claude (Anthropic's AI) over several sessions: I ran every command and test on my actual VMs and hardware, verified every kstat/swapctl/psinfo field against real system output before any of it went into the actual source file, and traced/fixed real bugs along the way (e.g. the ZFS-dataset I/O attribution limitation above was a design decision I made once we hit it, not something guessed at; the resize crash was found and root-caused by reproducing it with
truss, tracing it tosignal()'s platform-specific semantics, and confirming the fix against the actual signal delivery behavior; the per-process I/O fix went through two iterations after the first attempt tested as silently non-functional against real sustained disk I/O). Happy to answer questions about any part of the implementation, and glad to keep iterating based on review feedback.Screenshots:
OpenIndiana (VirtualBox VM):

OpenIndiana fastfetch system info (VirtualBox VM):

Solaris 10 x86 (VMWare VM):

T8-1, Solaris 11.4 SPARC, 64 cores (ids 64-127), courtesy of Peter Tribble:

OmniOS (QEMU VM):
