Add mixed-vendor GPU summary and fix startup heap corruption

Collect AMD amdgpu sysfs and optional NVIDIA nvidia-smi stats in the
background, auto-detecting supported adapters in PCI order and rotating
additional pairs alongside CPU/RAM. Explicit PCI selection and off mode
remain supported; missing metrics render as N/A.

Initialize the bitmap-only canvas locally instead of the ABI-dependent
libg15render initializer: the installed TTF-enabled renderer wrote an
8-byte FreeType pointer past the smaller bitmap-only allocation, corrupting
the heap before GPU threads started. Add collector, rendering and full-main
regression tests.
This commit is contained in:
Mikhail Yevchenko committed 2026-09-07 17:06:32 +00:00
1 parent 076641c867
commit 7c06a8089d
12 files changed
+1417 -4

No files matched your search

+107
View File
@@ -2,6 +2,113 @@ G15Stats - a CPU/Memory/Swap/Network/Battery/Temperature/Fan Speed/CPU Frequenci
The G15Stats requires libgtop development packages to be installed before compilation.
GPU summary columns:
The default --gpu auto collects ALL PCI devices (sorted PCI address) bound
to amdgpu or nvidia at startup, including mixed vendors. Use --gpu dddd:bb:ss.f (also -gpu), for example
--gpu 0000:01:00.0, to select a particular card. --gpu off restores the original
layout and disables collection. An explicit missing/unsupported card shows N/A;
auto with no supported card leaves the original layout unchanged. Restart to
rediscover cards after hotplug. Intel and the nouveau/radeon drivers are not
supported. Missing tools, permissions or individual metrics produce N/A, not 0.
With one GPU the 160x43 summary retains its existing 4/5 indicator rows and
labels. Graphs end at x=96 instead of 153; TOTAL moves to x=98. A divider
at x=105 separates the column at x=108..159. With two or more GPUs the left
x=0..50 shows compact CPU percent, R used system RAM, T total system RAM,
SWP percent, and (in five-row mode) GPU count. Four-row mode uses y=1,10,19,28;
five-row mode uses y=1,8,15,22,29. System RAM uses the same explicit units as VRAM.
Two GPU columns at x=54..104 and x=108..159 are visible together, with dividers
at x=51 and x=105 (the first column's glyphs end before its right divider).
Each GPU has five lines at y=1,8,15,22,29: vendor/index plus PCI bus:slot.function,
UTL percent, U used VRAM, T total VRAM, TEM temperature in Celsius (C).
For example NV1 01:00.0 and AMD2 11:00.0 identify different cards. Indices are
one-based positions in the selected PCI-sorted inventory, not NVIDIA ordinals;
startup diagnostics map each index to its full domain:bus:slot.function address.
More than two GPUs cycle through consecutive pairs every five seconds from
startup (1/2, 3/4, ..., then 1/2); the last odd card occupies the first column.
All cards are collected continuously, not just the visible pair. The display
refresh interval can delay a page change: each draw advances at most one pair,
so slow refresh never skips pairs. Inventory is bounded at 64 cards;
overflow/enumeration failure is an explicit startup error, never silent omission.
Use explicit PCI selection or off to recover. Hotplug requires restart.
The bottom info bar at y=37..42 and all non-summary screens retain their geometry.
Used and total are on separate lines so each retains an explicit MiB/GiB unit
(TiB/PiB for very large values), rounded to one decimal. Other screens do not
change. U/T refer to VRAM, not memory-controller utilization or system RAM;
on AMD APUs the driver may report only the reserved VRAM carveout.
AMD reads gpu_busy_percent, mem_info_vram_used/total (bytes), and the selected
PCI device's hwmon/temp1_input (millidegrees C). NVIDIA optionally executes
/usr/bin/nvidia-smi with pci.bus_id,utilization.gpu,memory.used,memory.total,temperature.gpu
and --format=csv,noheader,nounits: one query for all NVIDIA cards, matched by PCI
identity (including NVIDIA's eight-digit domain form), not response order. No CUDA/NVML SDK
or additional build dependency is needed. Run as an ordinary user.
Independent AMD workers and one batched NVIDIA worker wait two seconds between
queries; drawing uses only a mutex-protected snapshot array. A stalled AMD read
does not block another card or NVIDIA. NVIDIA queries share one 750ms monotonic deadline, fixed
arguments/environment, no shell, bounded output, and SIGKILL on timeout or
parent death. An unreaped child prevents further launches. Samples older than
five seconds display N/A per card, including when a sysfs read stalls. Worker
shutdown has one shared one-second join/reap budget; a stuck kernel read can
outlive that budget in static storage until process exit (no restart after a
failed stop). Normal application termination exits the process; no driver waits
are added to signal handling. The -r display
refresh interval still applies independently. No GPU settings are written.
Official interface references:
https://docs.kernel.org/gpu/amdgpu/thermal.html
https://docs.kernel.org/gpu/amdgpu/driver-misc.html
https://docs.nvidia.com/deploy/nvidia-smi/index.html
GPU validation:
After configuring/building, make check runs compiled parsing, units, missing-data,
expiry, selection, subprocess deadline/reaping/parent-death and descriptor checks,
plus real libg15render buffer checks. No daemon, input devices or synthetic GPU
sysfs fixtures are used. ./gpu-test auto additionally checks every real GPU,
its sysfs vendor identity and background cache (requires all four metrics).
Explicit PCI arguments still test one card. ./render-test auto output writes
real live 160x43 buffers to output-0.pgm and output-1.pgm (five/four rows), plus
output (four rows). ./render-test off output renders the original GPU-off layout.
For in-memory cases, ./render-test off output COUNT PAGE [large|unknown] selects
1..64 cards and a zero-based pair page. Omit PAGE to export the last pair.
The default values exercise LLONG_MAX VRAM and -273C/1000C; large uses
100.0/192.0GiB and 1000C, while unknown uses N/A for all GPU metrics.
For example ./render-test off output 2 tests worst-width dual-card values;
./render-test off output 3 1 tests the odd last page. With no arguments,
make check retains the worst-width two-card case. These are rendering inputs,
not simulated hardware or claims about the installed GPUs.
These do not connect to g15daemon and are not physical LCD tests.
make check also runs tests/render-layouts.sh for off, single, dual, large,
unknown, odd-last and 64-card layouts, each in both summary modes. In addition
to isolated-column comparisons, the test compares final GPU text, vertical
TOTAL and time-footer cells directly with the installed font's bitmap bits.
This independent oracle includes blank cells and checks full glyph bounds;
repeating renderString on another canvas alone cannot detect shared clipping.
Canvas initialization is tested starting from poisoned storage.
Startup regression: make check also runs runtime-test through the full main
loop for three frames with real libgtop and bitmap rendering. Only daemon
transport is replaced by a private socketpair; no keyboard events are sent.
./runtime-test auto 21 additionally requires valid live GPU samples after
twenty seconds. This is not a physical LCD or real daemon integration test.
The bitmap-only client initializes its own canvas, avoiding g15r_initCanvas:
a TTF-enabled renderer can otherwise write beyond a non-TTF caller's canvas
and corrupt malloc metadata at startup, even with --gpu off.
Each visual export also writes output-0.bin and output-1.bin: the actual 860
packed framebuffer bytes (one means black). With ImageMagick installed, run
sh tests/render-images.sh /absolute/output/directory after generating frames
there. It compares packed PBM, PGM and native PNG pixels, generates exact
nearest-neighbor 8x images, and checks the 8x-to-native round trip. Per-scenario
contact sheets use 4x tiles with labels outside the LCD and one column, avoiding
very wide sheets that viewers may downscale. No trim or crop is applied.
Inspect the individual native and 8x files as well as the contact sheets.
The supplied default small font has only three ink columns plus a blank column
per character; its N, M and other shapes can look incomplete when enlarged.
Use the bitmap checks to distinguish those font shapes from missing pixels.
Features:
Summary Screen displays 4 or 5 indicators from CPU/Frequency/Memory/NET/Temperature/Fan Speed/Swap,
along with current time.