Decoded: nproc (coreutils)

[Back to Project Main Page]

Note: This page explores the design of command-line utilities. It is not a user guide.
[GNU Manual] [No POSIX requirement] [Linux man] [No FreeBSD entry]

Logical flow of nproc command (coreutils)

Summary

nproc - print the number of processing units available

[Source] [Code Walkthrough]

Lines of code: 130
Principal syscall: Arch-dependent. One of getenv(), sysctl(), sysmp(), and others
Support syscalls: None
Options: 4 (0 short, 4 long)

Added to Coreutils in November 2009 [First version]
Number of revisions: 20 [Code Evolution]

Helpers:
  • None
External non-standard helpers:
  • error() - Outputs error message to standard error with possible process termination
  • num_processors() - Gets the processor count. Part of gnulib (here)

Setup

Little setup is needed for the nproc utility since the real muscle is done within gnulib. main() does two things to note:

  • Initialize the nprocresult variable and the ignore count to 0.
  • Initialize the mode variable (nproc_query_mode) to NPROC_CURRENT_OVERRIDABLE in preparation for default behavior to only return the number of processing units available to the current process. The _OVERRIDABLE suffix is used within the gnulib to integrate with OpenMP.

Parsing

Parsing for nproc considers two things:

  • Does the user want available processors or total count?
  • How many processors should we ignore?

Parsing failures

These failure case is explicitly checked:

  • Ignoring an unreasonably large number of processors
  • Using too many operands
  • Using unknown operands

This failure result in a short error message followed by the usage instructions.


Execution

Call num_processors() with the current mode. Subtract the number of ignored processors or report 1 if ignore is too large.

That's all there is. This utility does not fail within the coreutils implementation.

num_processors()

I wouldn't be doing my job if we stopped here so let's take a peek behind the curtain at num_processors() within gnulib.

nproc isn't required to be portable (not POSIX), and thus the approach may be different for all architectures. This work is best pushed out of coreutils and in to gnulib. Here, we find a mashup for various routines rolled together to test the system to find the appropriate syscall.

There's ~eight strategies to use depending on the system and the request mode:

For available processors:

  • pthread_getaffinity_np() for most systems using glibc
  • sched_getaffinity() for NetBSD
  • GetProcessAffinityMask for Windows

For total processors:

  • sysconf() in most OSs supporting glibc
  • pstat_getdynamic() in HP-UX (System V)
  • sysmp() for IRIX (System V)
  • sysctl() MacOS and many BSD variants
  • GetSystemInfo() in Windows


[Back to Project Main Page]