Skip to content

FreeBSD Port: FFM concretes for Memory/Sensors/Network/CPU - #3322

Merged
dbwiddis merged 5 commits into
oshi:masterfrom
dbwiddis:freebsd-ffm
Jun 3, 2026
Merged

FreeBSD Port: FFM concretes for Memory/Sensors/Network/CPU#3322
dbwiddis merged 5 commits into
oshi:masterfrom
dbwiddis:freebsd-ffm

Conversation

@dbwiddis

@dbwiddis dbwiddis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

Phase 4 of the FreeBSD FFM port (tracking #3315). Ports the
sysctl-friendly FreeBSD HAL/OS concretes onto the Phase 3 bindings:
six new FreeBsd*FFM siblings (ComputerSystem, GlobalMemory,
VirtualMemory, Sensors, NetworkParams, CentralProcessor) plus the
libc surface NetworkParams needs (gethostname, getaddrinfo family).
FFM SystemInfo still reports FreeBSD as unsupported — wiring stays
for Phase 6 so we never expose half-built state.

Per-commit walk

  1. Phase 4 commit 1FreeBsdComputerSystemFFM,
    FreeBsdGlobalMemoryFFM, FreeBsdVirtualMemoryFFM. Each is a
    mechanical mirror of its *JNA sibling: same abstract parent in
    oshi-common, same overrides, BsdSysctlUtil swapped for
    BsdSysctlUtilFFM. ~100 lines total.
  2. Phase 4 commit 2FreeBsdSensorsFFM. Per-CPU
    dev.cpu.%d.temperature loop via raw
    FreeBsdLibcFunctions.sysctlbyname (the MIB is formatted at each
    iteration so going through the util would just add indirection).
    Uses callInArenaDoubleOrDefault to scope the arena.
  3. Phase 4 commit 3FreeBsdNetworkParamsFFM plus the libc
    surface it needs. Extends FreeBsdLibcFunctions with
    gethostname, getaddrinfo, freeaddrinfo, gai_strerror
    mirroring LinuxLibcFunctions but with FreeBSD's actual
    struct addrinfo layout (ai_canonname comes BEFORE ai_addr on
    FreeBSD, the opposite of glibc).
  4. Phase 4 commit 4FreeBsdCentralProcessorFFM. Largest of
    the batch. Native reads all go through BsdSysctlUtilFFM (sysctl,
    sysctlbyname struct/raw variants) or FreeBsdLibcFunctions.getloadavg:
    kern.cp_time → 40-byte segment; kern.cp_times → variable-sized
    buffer indexed by CP_USER/CP_NICE/CP_SYS/CP_INTR/CP_IDLE;
    hw.model, hw.clockrate, dev.cpu.0.freq*, machdep.tsc_freq,
    kern.sched.topology_spec via the util; vm.stats.sys.v_swtch /
    v_intr via int sysctl + ParseUtil.unsignedIntToLong. Private
    parsing helpers (parseTopology, matchBitmasks,
    getCacheInfoFromLscpu, getProcessorIDfromDmiDecode) are
    duplicated from the JNA sibling — Phase 2 explicitly deferred this
    class's abstract API design, and the duplication keeps Phase 4
    scope tight.

Intentionally deferred

  • FFM SystemInfo factory wiring — Phase 6, so isAvailable()
    doesn't return true while the rest of the HAL/OS is still being
    built. NativeComparisonTest stays gated to
    {LINUX, MAC, WINDOWS}.
  • Remaining FreeBsd*FFM concretesPowerSource,
    InternetProtocolStats, HWDiskStore, OSProcess,
    OperatingSystem. These are the Phase 2 deferrals (too JNA-heavy /
    struct-tangled to pre-design the abstract API at hoist time). They
    land in Phase 5 alongside the libc bindings they need
    (sysctl(int*…) for kproc info, getpid, thr_self, getrlimit).
  • Hoisting CentralProcessor's pure-Java parsing helpers to
    oshi-common
    parseTopology/matchBitmasks/getProcessorIDfromDmiDecode
    could move to the abstract super and be shared by both JNA and FFM
    siblings. Doing it now would require redesigning the abstract API
    Phase 2 deferred; leaving the duplication keeps this PR small and
    reviewable.
  • Tests — none committed for the new concretes. Per the testing
    pattern established in FreeBSD Port: FFM libc bindings + sysctl util + WhoFFM driver #3319 commit 3, Phase 6's
    NativeComparisonTest HAL/OS traversal will cover them
    transitively. The existing GlobalMemoryFFMTest /
    VirtualMemoryFFMTest etc. in oshi-core-ffm are likewise gated
    to {LINUX, MAC, WINDOWS} until then.

Test plan

  • ./mvnw -pl oshi-core-ffm compile clean on each commit
  • ./mvnw -pl oshi-core-ffm test — 68 successful on Mac (the
    FreeBSD-only Phase 3 smoke tests skip as expected)
  • ./mvnw spotless:check checkstyle:check -pl oshi-core-ffm clean
  • Temporary FreeBSD CI green on all 4 commits in succession
  • PR CI: existing testfreebsd job in pr.yaml will exercise
    the codebase under flags: freebsd

Tracks #3315.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Enhanced FreeBSD CPU monitoring (topology, frequencies, per‑CPU ticks, load averages)
    • Improved physical and virtual memory reporting and swap metrics
    • CPU temperature sensing via coretemp
    • Hostname and domain name resolution improvements
    • System UUID discovery for FreeBSD
  • Bug Fixes

    • More robust kernel counter handling to avoid integer truncation
    • More accurate processor info extraction from system DMI data

dbwiddis and others added 4 commits June 2, 2026 18:41
First batch of sysctl-only FreeBSD HAL concretes. Each is a mechanical
mirror of its FreeBsd*JNA sibling: same abstract parent in oshi-common,
same overrides, with BsdSysctlUtil swapped for BsdSysctlUtilFFM.

* FreeBsdComputerSystemFFM — kern.hostuuid fallback.
* FreeBsdGlobalMemoryFFM — vm.stats.vm.v_inactive_count, v_free_count,
  hw.physmem. createVirtualMemory() returns the FFM sibling.
* FreeBsdVirtualMemoryFFM — vm.swap_total, v_swappgsin, v_swappgsout.
  Package-private; constructor takes FreeBsdGlobalMemory like the JNA
  sibling.

No tests committed: per the established testing principle, Phase 6's
NativeComparisonTest globalMemory()/virtualMemory()/computerSystem()
cases will cover these transitively through HAL traversal once
SystemInfo wires FreeBSD in. The corresponding GlobalMemoryFFMTest /
VirtualMemoryFFMTest in oshi-core-ffm are also gated to
{LINUX, MAC, WINDOWS} for the same reason — they'll add FREEBSD in
Phase 6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror of FreeBsdSensorsJNA using callInArenaDoubleOrDefault + raw
FreeBsdLibcFunctions.sysctlbyname (the per-CPU MIB is formatted at
each iteration, so going through BsdSysctlUtilFFM would just be
extra indirection). Loops dev.cpu.0.temperature, dev.cpu.1.temperature,
… until sysctlbyname fails, then returns the average in Celsius —
or NaN if the coretemp kld module isn't loaded.

Fan speeds and CPU voltage have no FreeBSD-supported source and stay
on the inherited FreeBsdSensors defaults, matching JNA behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends FreeBsdLibcFunctions with the libc surface FreeBsdNetworkParams
needs: gethostname, getaddrinfo, freeaddrinfo, gai_strerror, plus an
ADDRINFO_LAYOUT and addrinfoCanonname / gaiStrerror accessors. Mirrors
LinuxLibcFunctions but with FreeBSD's actual struct addrinfo layout
(ai_canonname comes BEFORE ai_addr on FreeBSD, the opposite of glibc).

FreeBsdNetworkParamsFFM is the mirror of FreeBsdNetworkParamsJNA: same
abstract parent in oshi-common, same two overrides (queryDomainName,
queryHostName), going through the new FFM bindings instead of JNA.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors FreeBsdCentralProcessorJNA. Overrides queryProcessorId,
initProcessorCounts, querySystemCpuLoadTicks, queryCurrentFreq,
queryMaxFreq, getSystemLoadAverage, queryProcessorCpuLoadTicks,
queryContextSwitches, queryInterrupts.

Native reads all go through BsdSysctlUtilFFM (sysctl/sysctlbyname) or
FreeBsdLibcFunctions.getloadavg — both already bound:
* kern.cp_time → 40-byte MemorySegment via BsdSysctlUtilFFM.sysctl(name, segment)
* kern.cp_times → variable-sized buffer via BsdSysctlUtilFFM.sysctl(name)
  reads N×40 bytes for N logical CPUs, indexed by CP_USER/CP_NICE/
  CP_SYS/CP_INTR/CP_IDLE.
* hw.model, hw.clockrate, dev.cpu.0.freq, dev.cpu.0.freq_levels,
  machdep.tsc_freq, kern.sched.topology_spec → BsdSysctlUtilFFM variants
* vm.stats.sys.v_swtch, vm.stats.sys.v_intr → sysctl int +
  ParseUtil.unsignedIntToLong
* getloadavg → arena-allocated double[] segment, FreeBsdLibcFunctions

Private parsing helpers (parseTopology, matchBitmasks, getMatchingBitmask,
getCacheInfoFromLscpu, getProcessorIDfromDmiDecode) are duplicated from
the JNA sibling. They could be hoisted to oshi-common FreeBsdCentralProcessor
in a follow-up but Phase 2 explicitly deferred this class's abstract API
design, and the duplication keeps Phase 4 scope tight.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3440a900-48ed-4757-983d-c1eb7b19749b

📥 Commits

Reviewing files that changed from the base of the PR and between c5afd0a and 19669ee.

📒 Files selected for processing (4)
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java
  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorJNA.java
  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
  • GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
  • GitHub Check: JMH Benchmarks, macos-latest
  • GitHub Check: Test JDK 26, macos-latest
  • GitHub Check: Test JDK 26, windows-latest
  • GitHub Check: Test JDK 21, macos-latest
  • GitHub Check: JMH Benchmarks, windows-latest
  • GitHub Check: Test JDK 25, FreeBSD (+ JNA==FFM)
  • GitHub Check: JMH Benchmarks, ubuntu-latest
  • GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
  • GitHub Check: Analyze (java)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2026-05-31T04:49:16.646Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3310
File: oshi-core/src/main/java/oshi/software/os/unix/netbsd/NetBsdOperatingSystem.java:164-166
Timestamp: 2026-05-31T04:49:16.646Z
Learning: In the oshi/oshi project, the NetBSD platform intentionally removes all JNA/native library dependencies (PR `#3310`). `NetBsdOperatingSystem.getThreadId()` uses `(int) Thread.currentThread().getId()` rather than `NetBsdLibc._lwp_self()` because the JNA native library is not bundled with the Maven dependency for the NetBSD platform. The mismatch between Java thread ids and kernel LWP ids is an accepted trade-off. Do not suggest reintroducing JNA-based calls (such as `NetBsdLibc._lwp_self()`) in NetBSD platform code.

Applied to files:

  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorJNA.java
📚 Learning: 2026-04-17T23:43:35.860Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3168
File: oshi-core-java25/src/main/java/oshi/ffm/windows/PdhFFM.java:0-0
Timestamp: 2026-04-17T23:43:35.860Z
Learning: In `oshi-core-java25/src/main/java/oshi/ffm/windows/PdhFFM.java`, the `PDH_RAW_COUNTER_LAYOUT` Java FFM struct layout must place `FirstValue` at byte offset 16 (not 12). The native MSVC compiler inserts 4 bytes of implicit alignment padding before the `LONGLONG FirstValue` field (after CStatus=4 bytes + FILETIME TimeStamp=8 bytes = 12 bytes), because LONGLONG requires 8-byte alignment. The total struct size is 40 bytes (with trailing padding). Do not use JAVA_LONG_UNALIGNED without explicit padding here, as that incorrectly places FirstValue at offset 12 and causes reads of garbage counter values.

Applied to files:

  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
📚 Learning: 2026-04-20T03:07:05.660Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3176
File: oshi-core-java25/src/main/java/oshi/hardware/platform/windows/WindowsVirtualMemoryFFM.java:53-60
Timestamp: 2026-04-20T03:07:05.660Z
Learning: In OSHI's Windows FFM paging file implementation (`oshi-core-java25/src/main/java/oshi/hardware/platform/windows/WindowsVirtualMemoryFFM.java`), the `querySwapUsed()` method uses the Windows PDH raw counter for "% Usage" on the paging file. Despite its name, this raw counter returns page counts: `FirstValue` is the number of pages currently used and `SecondValue` is the total number of pages in the swap file. The formatted counter performs the division and multiplies by 100% to yield a true percentage. Therefore, computing swap used bytes as `pageSize * used.get()` (pages × page size) is correct — do not treat the return value as a percentage.

Applied to files:

  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
📚 Learning: 2026-03-29T20:01:06.452Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3014
File: oshi-core-java11/src/main/java/module-info.java:10-17
Timestamp: 2026-03-29T20:01:06.452Z
Learning: In the oshi project, `oshi-core-java25/src/main/java/module-info.java` intentionally does NOT export `oshi.util.platform.unix.freebsd`, `oshi.util.platform.unix.openbsd`, or `oshi.util.platform.unix.solaris`, because the FFM (Foreign Function & Memory) implementation only supports Windows, macOS, and Linux. This differs from `oshi-core-java11/src/main/java/module-info.java` which exports all Unix platform packages. The asymmetry is by design.

Applied to files:

  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
📚 Learning: 2026-04-06T04:45:47.644Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3121
File: oshi-core/src/main/java/oshi/software/os/linux/LinuxOperatingSystem.java:53-53
Timestamp: 2026-04-06T04:45:47.644Z
Learning: In the oshi/oshi project, only interfaces and classes in the root packages `oshi`, `oshi.hardware`, and `oshi.software.os` are considered the public API. Code in subpackages that represent specific implementations/platforms (e.g., `oshi.software.os.linux`, `oshi.hardware.platform.linux`, and similar subpackages) is implementation detail. When reviewing, do not treat changes to classes in these platform-specific subpackages as public API breaks (for example: making `LinuxOperatingSystem` abstract, narrowing constructor visibility, or adding/removing abstract methods should not be flagged as breaking public API).

Applied to files:

  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
  • oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorJNA.java
🔇 Additional comments (2)
oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorJNA.java (1)

367-380: LGTM!

oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java (1)

20-27: LGTM!


📝 Walkthrough

Walkthrough

Adds FreeBSD FFM libc bindings for hostname/address resolution and implements FFM-backed FreeBSD classes for CPU, memory, virtual memory, sensors, network parameters, and computer-system host UUID lookups.

Changes

FreeBSD FFM Hardware and System APIs

Layer / File(s) Summary
FFM Libc Address Resolution Bindings
oshi-core-ffm/src/main/java/oshi/ffm/unix/freebsd/FreeBsdLibcFunctions.java
Class-level javadoc clarified. Added AI_CANONNAME, HOST_NAME_MAX, ADDRINFO_LAYOUT, and FFM wrappers gethostname(), getaddrinfo(), freeaddrinfo(), gaiStrerror(), and addrinfoCanonname() for canonical-name/error extraction.
CPU Processor Information and Topology
oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
FFM-backed CPU implementation: processor ID from sysctls/dmesg boot, topology parsing from kern.sched.topology_spec, cache discovery via lscpu/dmesg, per-CPU and system tick reads (kern.cp_time, kern.cp_times), current/max frequency reads, getloadavg integration, and sysctl-based context/interrupt counters.
Global and Virtual Memory Queries
oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java, oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdVirtualMemoryFFM.java
FreeBsdGlobalMemoryFFM reads hw.physmem and computes available VM pages as unsigned (inactive+free) * pageSize. FreeBsdVirtualMemoryFFM wires swap totals and swap page counters (vm.swap_total, vm.stats.vm.v_swappgsin, vm.stats.vm.v_swappgsout) to FFM sysctl calls.
Computer System Host UUID
oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdComputerSystemFFM.java
Overrides host UUID lookup via kern.hostuuid sysctl using FFM, falling back to Constants.UNKNOWN.
CPU Temperature Sensor Reading
oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdSensorsFFM.java
Implements queryCpuTemperature() using sysctlbyname("dev.cpu.%d.temperature") via FFM, converts deci-Kelvin to Celsius, averages successful per-CPU reads, returns Double.NaN on failure.
Network Hostname and Domain Name Resolution
oshi-core-ffm/src/main/java/oshi/software/os/unix/freebsd/FreeBsdNetworkParamsFFM.java
queryHostName() uses FFM gethostname() into a buffer. queryDomainName() calls FFM getaddrinfo() on the hostname, extracts canonical name via addrinfoCanonname(), frees results with freeaddrinfo(), logs warnings on errors, and returns trimmed domain or empty string.
JNA compatibility fixes
oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorJNA.java, oshi-core/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryJNA.java
dmidecode target for processor ID parsing changed to -t processor. FreeBsdGlobalMemoryJNA.queryVmStats() now widens kernel uint32 counters to unsigned long via Integer.toUnsignedLong(...) before arithmetic.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes


Possibly related issues

  • FFM port for FreeBSD #3315: Phase-related FFM porting objectives overlap — this PR implements getaddrinfo/gethostname/getloadavg and several FreeBsd*FFM classes described by that issue.

Possibly related PRs

  • oshi/oshi#3319: Related FreeBsdLibcFunctions FFM bindings work in the same Phase 3–4 area.
  • oshi/oshi#3316: Introduces the abstract FreeBsdNetworkParams hooks that FreeBsdNetworkParamsFFM implements.
  • oshi/oshi#3104: Similar FFM-backed getaddrinfo/gethostname bindings for another platform; shared wrapper patterns (gaiStrerror/freeaddrinfo/AI_CANONNAME).

Poem

🐰 I nibble at syscalls in moonlit code,

FFM bridges built on FreeBSD road,
CPUs counted, caches softly named,
Hostnames chased and canonically framed,
A rabbit's hop makes native calls less owed.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the primary change: adding FFM concrete implementations for FreeBSD memory, sensors, network, and CPU components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0.83333% with 238 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.89%. Comparing base (fe50ae9) to head (19669ee).

Files with missing lines Patch % Lines
...tform/unix/freebsd/FreeBsdCentralProcessorFFM.java 0.00% 184 Missing ⚠️
...tware/os/unix/freebsd/FreeBsdNetworkParamsFFM.java 0.00% 24 Missing ⚠️
...dware/platform/unix/freebsd/FreeBsdSensorsFFM.java 0.00% 16 Missing ⚠️
.../platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java 0.00% 6 Missing ⚠️
...platform/unix/freebsd/FreeBsdVirtualMemoryFFM.java 0.00% 5 Missing ⚠️
...latform/unix/freebsd/FreeBsdComputerSystemFFM.java 0.00% 2 Missing ⚠️
...tform/unix/freebsd/FreeBsdCentralProcessorJNA.java 0.00% 0 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (0.83%) is below the target coverage (70.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3322      +/-   ##
============================================
- Coverage     75.96%   74.89%   -1.07%     
  Complexity       76       76              
============================================
  Files           449      455       +6     
  Lines         17255    17492     +237     
  Branches       2824     2872      +48     
============================================
- Hits          13107    13101       -6     
- Misses         2550     2790     +240     
- Partials       1598     1601       +3     
Flag Coverage Δ
freebsd 30.73% <0.83%> (-0.42%) ⬇️
linux 37.69% <0.00%> (-0.55%) ⬇️
macos 38.00% <0.00%> (-0.52%) ⬇️
windows 45.20% <0.00%> (-0.67%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java`:
- Around line 337-346: The dmidecode probe in
FreeBsdCentralProcessorFFM.getProcessorIDfromDmiDecode is querying the wrong
table ("dmidecode -t system") so the loop using marker/procInfo never sees the
"Processor Information" / "ID:" lines; change the ExecutingCommand.runNative
call to use "dmidecode -t processor" (Type 4) or alternatively keep the command
but update the marker strings to match the selected table, ensuring the loop can
set procInfo when it sees "Processor Information" and then return the "ID:"
value.

In
`@oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java`:
- Around line 22-24: The sum of the page counters is done in 32-bit int and can
overflow before multiplying by getPageSize(); change the calculation in the
FreeBsdGlobalMemoryFFM method that currently uses int inactive and int free
(fetched via BsdSysctlUtilFFM.sysctl) so you cast at least one operand to long
before adding (or cast the result) and perform the multiplication in long,
returning a long total bytes value; update any local variable types involved
(e.g., inactive, free or the interim sum) so the addition and multiplication use
64-bit arithmetic and avoid integer overflow while still calling getPageSize().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d0749a5e-4b36-4777-8bed-80a078362b55

📥 Commits

Reviewing files that changed from the base of the PR and between fe50ae9 and c5afd0a.

📒 Files selected for processing (7)
  • oshi-core-ffm/src/main/java/oshi/ffm/unix/freebsd/FreeBsdLibcFunctions.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdComputerSystemFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdSensorsFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdVirtualMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/software/os/unix/freebsd/FreeBsdNetworkParamsFFM.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
  • GitHub Check: Test JDK 26, windows-latest
  • GitHub Check: Test JDK 26, macos-latest
  • GitHub Check: Test JDK 21, macos-latest
  • GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
  • GitHub Check: Test JDK 21, windows-latest
  • GitHub Check: Analyze (java)
  • GitHub Check: JMH Benchmarks, ubuntu-latest
  • GitHub Check: JMH Benchmarks, windows-latest
  • GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
  • GitHub Check: JMH Benchmarks, macos-latest
  • GitHub Check: Test JDK 25, FreeBSD (+ JNA==FFM)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2026-03-29T20:01:06.452Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3014
File: oshi-core-java11/src/main/java/module-info.java:10-17
Timestamp: 2026-03-29T20:01:06.452Z
Learning: In the oshi project, `oshi-core-java25/src/main/java/module-info.java` intentionally does NOT export `oshi.util.platform.unix.freebsd`, `oshi.util.platform.unix.openbsd`, or `oshi.util.platform.unix.solaris`, because the FFM (Foreign Function & Memory) implementation only supports Windows, macOS, and Linux. This differs from `oshi-core-java11/src/main/java/module-info.java` which exports all Unix platform packages. The asymmetry is by design.

Applied to files:

  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdComputerSystemFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdVirtualMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdSensorsFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
📚 Learning: 2026-04-03T18:44:48.200Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3112
File: oshi-core/src/main/java/oshi/PlatformEnum.java:63-66
Timestamp: 2026-04-03T18:44:48.200Z
Learning: In oshi/oshi PlatformEnum.java, the DRAGONFLYBSD enum constant is intentionally added for platform detection only (no implementation classes exist yet). It allows UnsupportedOperationException messages to say "DragonFly BSD" rather than "Unknown". Full DragonFly BSD support is tracked in issue `#2583`. Do not flag the missing switch-case implementations as a bug.

Applied to files:

  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdComputerSystemFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
📚 Learning: 2026-05-31T04:49:16.646Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3310
File: oshi-core/src/main/java/oshi/software/os/unix/netbsd/NetBsdOperatingSystem.java:164-166
Timestamp: 2026-05-31T04:49:16.646Z
Learning: In the oshi/oshi project, the NetBSD platform intentionally removes all JNA/native library dependencies (PR `#3310`). `NetBsdOperatingSystem.getThreadId()` uses `(int) Thread.currentThread().getId()` rather than `NetBsdLibc._lwp_self()` because the JNA native library is not bundled with the Maven dependency for the NetBSD platform. The mismatch between Java thread ids and kernel LWP ids is an accepted trade-off. Do not suggest reintroducing JNA-based calls (such as `NetBsdLibc._lwp_self()`) in NetBSD platform code.

Applied to files:

  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
📚 Learning: 2026-04-20T03:07:05.660Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3176
File: oshi-core-java25/src/main/java/oshi/hardware/platform/windows/WindowsVirtualMemoryFFM.java:53-60
Timestamp: 2026-04-20T03:07:05.660Z
Learning: In OSHI's Windows FFM paging file implementation (`oshi-core-java25/src/main/java/oshi/hardware/platform/windows/WindowsVirtualMemoryFFM.java`), the `querySwapUsed()` method uses the Windows PDH raw counter for "% Usage" on the paging file. Despite its name, this raw counter returns page counts: `FirstValue` is the number of pages currently used and `SecondValue` is the total number of pages in the swap file. The formatted counter performs the division and multiplies by 100% to yield a true percentage. Therefore, computing swap used bytes as `pageSize * used.get()` (pages × page size) is correct — do not treat the return value as a percentage.

Applied to files:

  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdGlobalMemoryFFM.java
  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdVirtualMemoryFFM.java
📚 Learning: 2026-04-10T22:44:36.786Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3136
File: oshi-core-java25/src/main/java/oshi/software/os/linux/LinuxOperatingSystemFFM.java:46-53
Timestamp: 2026-04-10T22:44:36.786Z
Learning: In OSHI's `AuxvFFM.queryAuxv()` (oshi-core-java25/src/main/java/oshi/driver/linux/proc/AuxvFFM.java), the do-while loop is safe even when `/proc/self/auxv` cannot be read: `FileUtil.readAllBytesAsBuffer` returns an empty ByteBuffer on failure, and `FileUtil.readLongFromBuffer`/`readIntFromBuffer` return 0L when reading past the buffer limit. This 0L equals AT_NULL, causing the loop to exit immediately with an empty map, which triggers the `getconf`/hardcoded-default fallback in callers like `LinuxOperatingSystemFFM`. Do not flag this do-while loop or the static initializer that calls `AuxvFFM.queryAuxv()` as unsafe.

Applied to files:

  • oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdCentralProcessorFFM.java
🔇 Additional comments (8)
oshi-core-ffm/src/main/java/oshi/ffm/unix/freebsd/FreeBsdLibcFunctions.java (3)

316-324: LGTM!


243-307: LGTM!


41-66: FreeBSD addrinfo/layout bindings need header-backed constants and sizing

  • ADDRINFO_LAYOUT encodes ai_canonname before ai_addr, but the gathered evidence doesn’t include FreeBSD header definitions to support the specific socklen_t sizing, padding/byte offsets, or the asserted total = 48 bytes.
  • AI_CANONNAME = 2 and HOST_NAME_MAX = 255 aren’t backed by any FreeBSD header content in the gathered results (repo search found no local netdb.h/FreeBSD headers to cite).
oshi-core-ffm/src/main/java/oshi/software/os/unix/freebsd/FreeBsdNetworkParamsFFM.java (2)

34-59: LGTM!


62-70: LGTM!

oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdVirtualMemoryFFM.java (1)

19-35: LGTM!

oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdSensorsFFM.java (1)

33-59: LGTM!

oshi-core-ffm/src/main/java/oshi/hardware/platform/unix/freebsd/FreeBsdComputerSystemFFM.java (1)

19-22: LGTM!

Comment on lines +187 to +207
String csvMatch = m.group(1);
String[] csvTokens = csvMatch.split(",");
String firstVal = csvTokens[0];
long parsedVal = ParseUtil.hexStringToLong(firstVal, 0);
switch (groupLevel) {
case 1:
group1 = parsedVal;
break;
case 2:
group2.add(parsedVal);
break;
case 3:
group3.add(parsedVal);
break;
default:
break;
}
}
}
}
return matchBitmasks(group1, group2, group3);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Parse the full CPU mask instead of only the first 64 bits.

Using csvTokens[0] throws away every mask word after the first one, so kern.sched.topology_spec gets truncated on FreeBSD hosts with more than 64 logical CPUs. That undercounts processors and cascades into incorrect core/package grouping and per-CPU telemetry sizing.

Also applies to: 210-223

CodeRabbit flagged two bugs in the new FFM concretes. Both are
identical to the long-standing JNA siblings — fixing only the FFM
copies would introduce a behavioral divergence that breaks Phase 6
NativeComparisonTest parity, so both pairs are updated in lockstep
(per the project convention of fixing pre-existing JNA bugs flagged
during the FFM port).

1. getProcessorIDfromDmiDecode used "dmidecode -t system", which
   filters to DMI type 1 (System Information) only. The "Processor
   Information" marker the loop scans for is DMI type 4. Result: the
   loop never matched, the fallback ("%016X" formatting of the
   dmesg.boot-derived bits) always ran. Switched both copies to
   "dmidecode -t processor".

2. queryVmStats summed two uint32 page counters as Java ints
   (BsdSysctlUtil.sysctl returns signed int). For counters > 2^31 the
   addition would sign-extend incorrectly and the subsequent multiply
   by getPageSize() could truncate. Switched both copies to
   Integer.toUnsignedLong on each counter and perform the add and
   multiply in long.

Each fix is one line per file. No other behavior changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dbwiddis
dbwiddis merged commit 1af6e21 into oshi:master Jun 3, 2026
19 of 20 checks passed
@dbwiddis
dbwiddis deleted the freebsd-ffm branch June 3, 2026 06:18
dbwiddis added a commit to dbwiddis/oshi that referenced this pull request Jun 4, 2026
FreeBsdFileSystemFFM mirrors FreeBsdFileSystemJNA — two trivial
overrides for kern.openfiles / kern.maxfiles via BsdSysctlUtilFFM.

Folds in three Sonar findings from PR oshi#3322:
* FreeBsdNetworkParamsFFM (S2184): widen HOST_NAME_MAX + 1 to long for
  the arena allocate call to match the gethostname argument on the
  next line, keeping both arithmetic paths in 64-bit math.
* DisklabelTest x2 (S2153): drop the unnecessary .longValue() unboxing
  from assertThat(diskdata.getC()…) in the OpenBSD and NetBSD live
  smoke tests — Hamcrest's greaterThanOrEqualTo(0L) works on the Long
  directly, the unbox-then-rebox roundtrip is wasted work.

The CPUMASK regex S5998 finding in FreeBsdCentralProcessorFFM (and its
JNA sibling) was reviewed and marked false positive: the comma anchor
between alternatives prevents catastrophic backtracking, and input is
bounded kernel-controlled sysctl output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dbwiddis added a commit that referenced this pull request Jun 4, 2026
* Phase 5 commit 1: FreeBsdFileSystemFFM + Sonar fixes

FreeBsdFileSystemFFM mirrors FreeBsdFileSystemJNA — two trivial
overrides for kern.openfiles / kern.maxfiles via BsdSysctlUtilFFM.

Folds in three Sonar findings from PR #3322:
* FreeBsdNetworkParamsFFM (S2184): widen HOST_NAME_MAX + 1 to long for
  the arena allocate call to match the gethostname argument on the
  next line, keeping both arithmetic paths in 64-bit math.
* DisklabelTest x2 (S2153): drop the unnecessary .longValue() unboxing
  from assertThat(diskdata.getC()…) in the OpenBSD and NetBSD live
  smoke tests — Hamcrest's greaterThanOrEqualTo(0L) works on the Long
  directly, the unbox-then-rebox roundtrip is wasted work.

The CPUMASK regex S5998 finding in FreeBsdCentralProcessorFFM (and its
JNA sibling) was reviewed and marked false positive: the comma anchor
between alternatives prevents catastrophic backtracking, and input is
bounded kernel-controlled sysctl output.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 2: FreeBsdInternetProtocolStatsFFM

Mirror of FreeBsdInternetProtocolStatsJNA. Reads net.inet.tcp.stats
and net.inet.udp.stats via BsdSysctlUtilFFM.sysctl(name), returning
the auto-arena MemorySegment, then memoizes the segment itself
(instead of an intermediate BsdTcpstat / BsdUdpstat struct as the JNA
sibling does — FFM lets us pull fields out at offset on demand, so
the extra holder type isn't needed).

Established-connection counts continue to come from the shared
NetStat command-line driver. Field offsets and the
ParseUtil.unsignedIntToLong widening match the JNA layout exactly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 3: FreeBsdPowerSourceFFM

Mirror of FreeBsdPowerSourceJNA — three hw.acpi.battery.* sysctl reads
(state/time/life) via BsdSysctlUtilFFM, then acpiconf -i 0 parsing for
the richer device fields. Constructor signature and the heavy-but-
straightforward command-output parsing are byte-identical to the JNA
sibling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 4: FreeBsdHWDiskStoreFFM

Mirror of FreeBsdHWDiskStoreJNA. One native read (kern.disks via
BsdSysctlUtilFFM); everything else is pure-Java parsing of iostat -Ix
plus the GeomDiskList / GeomPartList drivers in oshi-common (hoisted
in Phase 2).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 5: FreeBsdOperatingSystemFFM + FreeBsdOSProcessFFM

The two classes are circularly dependent (OS constructs OSProcess,
OSProcess holds the OS reference for the rlimit-of-self path), so they
land together with all the libc bindings they share.

* FreeBsdLibcFunctions gains: getpid, thr_self, sysctl (int-MIB form
  with errno capture), getrlimit + RLIMIT_LAYOUT (two longs, matching
  FreeBSD's struct rlimit) + RLIMIT_NOFILE = 8 (FreeBSD's value,
  not Linux's 7). rlimitCur/rlimitMax accessor helpers.

* FreeBsdOSProcessFFM mirrors FreeBsdOSProcessJNA. Static ARGMAX read
  via BsdSysctlUtilFFM at class init; queryArguments / queryEnvironmentVariables
  / queryBitness via sysctl int-MIB (CTL_KERN=1, KERN_PROC=14, with
  KERN_PROC_ARGS=7 / KERN_PROC_ENV=35 / KERN_PROC_SV_NAME=9 leaves);
  getSoftOpenFileLimit / getHardOpenFileLimit via getrlimit(RLIMIT_NOFILE)
  for the calling process, falling back to /proc/<pid>/limits parsing
  for others (same as JNA).

* FreeBsdOperatingSystemFFM mirrors FreeBsdOperatingSystemJNA. Wires
  the FFM siblings (FreeBsdFileSystemFFM, FreeBsdInternetProtocolStatsFFM,
  FreeBsdNetworkParamsFFM, FreeBsdOSProcessFFM); sessions go through
  WhoFFM.queryUtxent() (Phase 3); getProcessId / getThreadId use the
  new getpid / thr_self bindings; querySystemBootTime reads kern.boottime
  as a 16-byte struct via BsdSysctlUtilFFM.sysctl(name, segment),
  parsing the tv_sec long out of the result.

* Hoists ProcstatUtil (oshi-core/oshi.util.platform.unix.freebsd) to
  oshi-common (oshi.util.common.platform.unix.freebsd) per the Phase 2
  pattern, since both JNA OSProcess and the new FFM OSProcess need it
  and the original package is split (it also contains BsdSysctlUtil
  which is JNA-tied). FreeBsdOSProcessJNA import updated; the pure-
  parsing tests come along, and the live test now derives the current
  PID from ManagementFactory rather than oshi.SystemInfo (which lives
  in the JNA module and isn't visible from oshi-common). Module-info
  exports + add-opens updated to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 6: FreeBsdHardwareAbstractionLayerFFM (bookend)

Aggregate FFM HAL. Wires the FreeBsd*FFM concretes from Phases 4–5
(ComputerSystem, GlobalMemory, CentralProcessor, Sensors, PowerSource,
HWDiskStore, Cups printer) and reuses the pure-Java BSD-shared classes
(UnixDisplay, BsdNetworkIF, FreeBsdGraphicsCard / SoundCard / UsbDevice)
that already live in oshi-common.

Hoists BsdNetworkIF (oshi-core/oshi.hardware.platform.unix) to
oshi-common (oshi.hardware.common.platform.unix), mirroring the Phase 2
treatment of FreeBsdGraphicsCard / SoundCard / UsbDevice etc. The class
is pure-Java already (just ExecutingCommand + netstat parsing); it was
just stranded in the JNA module because Phase 2 didn't touch the BSD
network path. Both DragonFlyBsdHardwareAbstractionLayer and
FreeBsdHardwareAbstractionLayerJNA pick up the new import path; no
behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 7: fix two CodeRabbit findings on PR #3328

Both findings verified against current code; both still valid.

1. ProcstatUtilTest live-test PID parse defaulted to 0 on failure,
   which would silently pass 0 to ProcstatUtil.getOpenFiles and let
   the rest of the live assertions run against a meaningless PID.
   Switched the default to -1 and added an upfront
   assertThat(pid, is(greaterThan(0))) so a platform that doesn't
   follow RuntimeMXBean#getName()'s "pid@host" convention fails fast
   with a clear message instead of producing confusing downstream
   failures.

2. FreeBsdPowerSourceFFM/JNA: hw.acpi.battery.life uses -1 as the
   sysctl-failure sentinel and the kernel returns 0–100 for a real
   reading. The "life > 0" check left psRemainingCapacityPercent at
   its default 1.0 when life was a legitimate 0 (battery flat),
   reporting a discharged battery as fully charged. Both FFM and JNA
   copies switch to ">= 0" so genuine 0 readings drive the percent to
   0.0; -1 still falls through and keeps the 1.0 default. Lockstep
   fix on the JNA sibling because Phase 6's NativeComparisonTest will
   compare the two implementations and any divergence would fail
   parity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 5 commit 8: strip trailing newlines in unix.yaml (post-merge)

Upstream 8f3f018 removed the NetBSD GCC farm CI job but left two
trailing blank lines at the end of unix.yaml that Spotless flags. The
new upstream master is otherwise unchanged for the FreeBSD port, so
this is just a one-line cleanup after the merge into freebsd-ffm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dbwiddis added a commit to dbwiddis/oshi that referenced this pull request Jun 4, 2026
Adds PlatformEnum.FREEBSD to SUPPORTED_PLATFORMS, dispatches to
FreeBsdOperatingSystemFFM / FreeBsdHardwareAbstractionLayerFFM (shipped
in PRs oshi#3322 and oshi#3328), and updates the class-level Javadoc that
previously listed only Windows/macOS/Linux. FreeBSD is dropped from
the "use oshi.SystemInfo (JNA) instead" call-out since the FFM path
now covers it; OpenBSD, Solaris, AIX still need the JNA entry point.

This is the last load-bearing change of the FreeBSD FFM port — after
this, oshi.ffm.SystemInfo.isAvailable() returns true on FreeBSD and
the public API works end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dbwiddis added a commit that referenced this pull request Jun 4, 2026
* Phase 6 commit 1: wire FreeBSD into oshi.ffm.SystemInfo

Adds PlatformEnum.FREEBSD to SUPPORTED_PLATFORMS, dispatches to
FreeBsdOperatingSystemFFM / FreeBsdHardwareAbstractionLayerFFM (shipped
in PRs #3322 and #3328), and updates the class-level Javadoc that
previously listed only Windows/macOS/Linux. FreeBSD is dropped from
the "use oshi.SystemInfo (JNA) instead" call-out since the FFM path
now covers it; OpenBSD, Solaris, AIX still need the JNA entry point.

This is the last load-bearing change of the FreeBSD FFM port — after
this, oshi.ffm.SystemInfo.isAvailable() returns true on FreeBSD and
the public API works end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 6 commit 2: enable FreeBSD across FFM tests

Now that oshi.ffm.SystemInfo dispatches to FreeBSD (Phase 6 commit 1),
all six FFM tests previously gated to {LINUX, MAC, WINDOWS} need
FreeBSD added so they exercise the new wiring on the FreeBSD CI:

* oshi-core-ffm: SystemInfoTest, GlobalMemoryFFMTest, VirtualMemoryFFMTest,
  OperatingSystemFFMTest, ForeignFunctionsTest
* oshi-benchmark: NativeComparisonTest (the big JNA-vs-FFM HAL/OS
  parity test that retires the per-piece comparison tests we explicitly
  skipped during Phases 3–5)

No assertion changes — the test bodies already cover the FreeBSD-relevant
surface generically through the public OSHI API. Mac CI continues to
see the same 39 successful / 53 skipped split.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 6 commit 3: handle FreeBSD-specific NativeComparisonTest parity gaps

Three failures surfaced when Phase 6 commit 2 enabled NativeComparisonTest
on FreeBSD. None are real parity bugs; all are structural differences
between FreeBSD's process/sensor model and the other platforms.

* ComparisonAssertions.assertWithinRatio now treats both-NaN as equal.
  CPU temperature comes back NaN on the FreeBSD CI VM (no coretemp kld
  module loaded) from both JNA and FFM, which is correct parity, but
  NaN/NaN arithmetic made the ratio check fail.

* assertStartTimeMatches helper added to NativeComparisonTest. On
  Linux/Mac/Windows OSProcess#getStartTime() exposes the kernel's
  exact start time and strict equality holds. On FreeBSD startTime is
  derived as (now - elapsedTime) where elapsedTime is the
  seconds-resolution `ps -o etimes` value; JNA and FFM each capture
  `now` at slightly different timestamps so the derived values drift
  by tens of milliseconds. Switched the two startTime assertions
  (currentProcess() and processListStructure()) to a 2000ms tolerance
  on FreeBSD; other platforms keep strict equality.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 6 commit 4: more FreeBSD parity gaps surfaced by NativeComparisonTest

Two more failures appeared once Phase 6 commit 3's startTime and NaN
fixes cleared the way; both are real and fixed in this commit.

1. process.softOpenFileLimit — JNA returned 10328, FFM returned 175554
   (real open-files limit). Pre-existing JNA-on-FreeBSD bug:
   Resource.RLIMIT_NOFILE in the JNA platform module is the Linux
   value 7, but on FreeBSD RLIMIT_NOFILE = 8 (7 is RLIMIT_NPROC). So
   FreeBsdOSProcessJNA was calling getrlimit on the wrong resource —
   returning the max-processes limit instead of open-files. Added an
   explicit `int RLIMIT_NOFILE = 8;` to FreeBsdLibc that shadows the
   inherited Linux constant so the existing call site picks up the
   correct value with no code change at the caller. FFM was already
   using 8 (added in Phase 5 commit 5).

2. fileStoreUpdateAttributes totalSpace — JNA and FFM call
   updateAttributes() back-to-back, but on a live filesystem total
   space can drift by a few blocks while the test is itself writing
   (the observed delta was exactly 3×4KB = 12 KB out of 208 GB).
   Relaxed the strict equality to assertWithinRatio with a 0.1%
   tolerance, the same pattern this file already uses for other
   drift-prone counters.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Phase 6 commit 5: remove temporary FreeBSD FFM CI workflow

freebsd-ffm.yaml was the push-triggered FreeBSD VM job introduced in
Phase 1 (PR #3316) so in-progress FFM work got FreeBSD coverage
between PR submissions. With the port complete and the permanent
testfreebsd job in pr.yaml + unix.yaml exercising every change, the
temp workflow is no longer needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dbwiddis added a commit that referenced this pull request Jun 4, 2026
Follow-up to the five FreeBSD FFM port PRs (#3316, #3319, #3322,
#3328, #3330) covering loose ends that don't fit any individual port
commit.

JaCoCo agent excludes:
* Remove `**/unix/BsdNetworkIF*` and `**/unix/UnixBaseboard*`. Both
  classes were hoisted to oshi-common during the port (#3316 and
  #3328 respectively) and are now exercised on the permanent
  FreeBSD CI job through `NativeComparisonTest.networkInterfaces()`
  and `ComputerSystem.getBaseboard()`; the excludes were silently
  dropping that coverage from the `freebsd` codecov flag.
* Add `**/FreeBsdPowerSource*` alongside the existing
  `**/{Mac,Windows,Linux}PowerSource*` entries. No battery on the
  FreeBSD CI VM, same hardware-conditional pattern.

Documentation:
* Update the supported-platforms statement in README.md, FAQ.md,
  PERFORMANCE.md, src/site/markdown/index.md, oshi-core-ffm
  module-info Javadoc, oshi-core SystemInfo Javadoc, and oshi-core
  package-info Javadoc from "Windows, macOS, and Linux" to
  "Windows, macOS, Linux, and FreeBSD".

CHANGELOG.md gains a New Features bullet linking all five FreeBSD
FFM port PRs.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant