cpulimit

Platforms

A process iterator exists for Linux, macOS, FreeBSD, OpenBSD, NetBSD and Solaris/illumos. How much each has been run differs a lot, and this page says so instead of rounding up.

Status

PlatformStatusEvidence
Linux, glibctestedCI on x86_64 and arm64; gcc and clang; -O0, -O2, -O3; -std=gnu99 to gnu2x; sanitizers, valgrind, fuzzing, stress
Linux, muslCIx86_64, i386, arm64, armv7, ppc64le, s390x, riscv64 (qemu-user except x86_64, which fakes parts of /proc)
macOS 14, 15unit testsCI builds and runs the unit tests, not the integration tests. The job does not gate a release.
OpenBSD 7.9, 8.0unit testsCI builds with -Werror and runs the unit tests and the command-mode tests in a VM. 7.9 passes; on 8.0 one timing bound failed once and was relaxed, so 8.0 is not yet confirmed with the final code. Does not gate a release.
FreeBSD 14, 15buildsCI builds on 14.1; the vm workflow (manual and weekly) builds and tests 14.5 and 15.1. The iterator was reworked in 1.0.3 and has not been run on FreeBSD since.
NetBSD 10, 11not yet runWritten from the NetBSD sources, sharing code with OpenBSD. Some facts (zombie status value, the clock rate source) are assumptions until the first run.
HardenedBSD, GhostBSDreport onlyBuilt by the vm workflow; they should select the FreeBSD code.
Solaris, OmniOS, OpenIndiananever runAn iterator was contributed by Jim Mason; it has never been compiled in CI. The vm workflow is the first attempt, and its compiler package names are guesses.
DragonFly BSDunsupportedNo iterator. Its kinfo_proc and clock units are not confirmed.
GNU/Hurd, HaikuunsupportedProbed only. Haiku's team info has no parent pid, so -i cannot work there as designed.

"Does not gate a release" means a failure of that job is reported but does not stop a tag from producing release assets. The current results of every job are on the Actions page; this page does not copy them.

The vm workflow

Hosted CI has no BSD or illumos runners, so the repository runs those systems in QEMU virtual machines (the vmactions actions). The workflow vm.yml is experimental and report only: it runs by hand (Actions → vm → Run workflow) and weekly. Each job builds, runs the unit tests and copies its transcript back, which is shown as an annotation on the run, so a failure can be read without opening raw logs. It also runs the full suite, integration tests included, on Debian for riscv64, ppc64le and aarch64 under system emulation, where /proc is real, and probes GNU/Hurd and Haiku.

Platform notes

OpenBSD and NetBSD

  • No libkvm and no special group: the iterator reads sysctl kern.proc (NetBSD: kern.proc2).
  • CPU time comes from the statistics tick counters, divided by the statistics clock rate. They are sampled at randomised instants, so one 50 ms sample can show five to seven ticks; the unit test allows for that on OpenBSD (usage bound 1.7 instead of 1.2).
  • Zombies are listed by the kernel and are skipped (p_stat dead/zombie). Without that, command mode waited on children that had already ended.

macOS

  • CPU time is reported in mach absolute time units, which are nanoseconds on Intel but not on Apple silicon; the iterator converts with the timebase.
  • Inspecting another user's process needs privilege; a process that cannot be inspected is skipped.

Linux containers

  • The target must be visible in your PID namespace and signalable. Inside a container, -e matches processes of that container only.
  • If the container's cgroup has a CPU quota, that quota applies as well; cpulimit adds to it, it does not replace it.

Adding a platform

A port is one file, src/platform/<os>/iterator.c, plus a branch in src/platform/iterator.c. It must provide init_process_iterator, get_next_process and close_process_iterator and fill struct process (pid, parent pid, a start time that is only ever compared for equality, CPU time in milliseconds). Take a snapshot if the system allows it and call snapshot_select() for the filter; skip zombies and kernel threads. The checklist is in Contributing.