nproc: A new program to count the available processors
authorGiuseppe Scrivano <gscrivano@gnu.org>
Sat, 31 Oct 2009 17:59:50 +0000 (18:59 +0100)
committerPádraig Brady <P@draigBrady.com>
Fri, 6 Nov 2009 16:54:12 +0000 (16:54 +0000)
* AUTHORS: Add my name.
* NEWS: Mention it.
* README: Likewise.
* bootstrap.conf (gnulib_modules): Add nproc.
* doc/coreutils.texi (nproc invocation): Add nproc info.
* man/Makefile.am (nproc.1): Add dependency.
* man/nproc.x: New template.
* man/.gitignore: Ignore generated man page.
* po/POTFILES.in: Add src/nproc.c.
* src/.gitignore: Exclude nproc.
* src/Makefile.am (EXTRA_PROGRAMS): Add nproc.
* src/nproc.c: New file.
* tests/Makefile.am (TESTS): Add misc/nproc-{avail,positive}.
* tests/misc/nproc-avail: New file.
* tests/misc/nproc-positive: New file.

15 files changed:
AUTHORS
NEWS
README
bootstrap.conf
doc/coreutils.texi
man/.gitignore
man/Makefile.am
man/nproc.x [new file with mode: 0644]
po/POTFILES.in
src/.gitignore
src/Makefile.am
src/nproc.c [new file with mode: 0644]
tests/Makefile.am
tests/misc/nproc-avail [new file with mode: 0755]
tests/misc/nproc-positive [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
index 59a0dfa..0c15472 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -51,6 +51,7 @@ mv: Mike Parker, David MacKenzie, Jim Meyering
 nice: David MacKenzie
 nl: Scott Bartram, David MacKenzie
 nohup: Jim Meyering
+nproc: Giuseppe Scrivano
 od: Jim Meyering
 paste: David M. Ihnat, David MacKenzie
 pathchk: Paul Eggert, David MacKenzie, Jim Meyering
diff --git a/NEWS b/NEWS
index 5b75dbb..24b2afa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -62,6 +62,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   Also, "rm /read-only-fs/nonexistent" now reports "file not found" rather
   than the less precise "Read-only file system" error.
 
+** New programs
+
+  nproc: Print the number of processing units available to a process.
+
 ** New features
 
   env and printenv now accept the option --null (-0), as a means to
diff --git a/README b/README
index 7545eab..0951b62 100644 (file)
--- a/README
+++ b/README
@@ -11,7 +11,7 @@ The programs that can be built with this package are:
   csplit cut date dd df dir dircolors dirname du echo env expand expr
   factor false fmt fold groups head hostid hostname id install join kill
   link ln logname ls md5sum mkdir mkfifo mknod mktemp mv nice nl nohup
-  od paste pathchk pinky pr printenv printf ptx pwd readlink rm rmdir
+  nproc od paste pathchk pinky pr printenv printf ptx pwd readlink rm rmdir
   runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf
   sleep sort split stat stdbuf stty su sum sync tac tail tee test timeout
   touch tr true truncate tsort tty uname unexpand uniq unlink uptime users
index be8d961..3a26394 100644 (file)
@@ -159,6 +159,7 @@ gnulib_modules="
   modechange
   mountlist
   mpsort
+  nproc
   obstack
   pathmax
   perl
index 227014c..3fc3a52 100644 (file)
@@ -84,6 +84,7 @@
 * nice: (coreutils)nice invocation.             Modify niceness.
 * nl: (coreutils)nl invocation.                 Number lines and write files.
 * nohup: (coreutils)nohup invocation.           Immunize to hangups.
+* nproc: (coreutils)nproc invocation.           Print the number of processors.
 * od: (coreutils)od invocation.                 Dump files in octal, etc.
 * paste: (coreutils)paste invocation.           Merge lines of files.
 * pathchk: (coreutils)pathchk invocation.       Check file name portability.
@@ -410,6 +411,7 @@ System context
 
 * arch invocation::              Print machine hardware name
 * date invocation::              Print or set system date and time
+* nproc invocation::             Print the number of processors
 * uname invocation::             Print system information
 * hostname invocation::          Print or set system name
 * hostid invocation::            Print numeric host identifier
@@ -13407,6 +13409,7 @@ information.
 @menu
 * date invocation::             Print or set system date and time.
 * arch invocation::             Print machine hardware name.
+* nproc invocation::            Print the number of processors.
 * uname invocation::            Print system information.
 * hostname invocation::         Print or set system name.
 * hostid invocation::           Print numeric host identifier.
@@ -14066,6 +14069,43 @@ The program accepts the @ref{Common options} only.
 @exitstatus
 
 
+@node nproc invocation
+@section @command{nproc}: Print the number of available processors
+
+@pindex nproc
+@cindex Print the number of processors
+@cindex system information, printing
+
+Print the number of processing units available to the current process,
+which may be less than the number of online processors.
+If this information is not accessible, then print the number of
+processors installed.  If the @env{OMP_NUM_THREADS} environment variable is
+set, then it will determine the returned value.  The result is guaranteed to be
+greater than zero.  Synopsis:
+
+@example
+nproc [@var{option}]
+@end example
+
+The program accepts the following options.  Also see @ref{Common options}.
+
+@table @samp
+
+@item --all
+@opindex --all
+Print the number of installed processors on the system, which may
+be greater than the number online or available to the current process.
+The @env{OMP_NUM_THREADS} environment variable is not honored in this case.
+
+@item --ignore=@var{number}
+@opindex --ignore
+If possible, exclude this @var{number} of processing units.
+
+@end table
+
+@exitstatus
+
+
 @node uname invocation
 @section @command{uname}: Print system information
 
index 1085ff0..2c2ffcd 100644 (file)
@@ -48,6 +48,7 @@ mv.1
 nice.1
 nl.1
 nohup.1
+nproc.1
 od.1
 paste.1
 pathchk.1
index b56db94..f1fca5c 100644 (file)
@@ -80,6 +80,7 @@ mv.1:         $(common_dep)   $(srcdir)/mv.x          ../src/mv.c
 nice.1:                $(common_dep)   $(srcdir)/nice.x        ../src/nice.c
 nl.1:          $(common_dep)   $(srcdir)/nl.x          ../src/nl.c
 nohup.1:       $(common_dep)   $(srcdir)/nohup.x       ../src/nohup.c
+nproc.1:       $(common_dep)   $(srcdir)/nproc.x       ../src/nproc.c
 od.1:          $(common_dep)   $(srcdir)/od.x          ../src/od.c
 paste.1:       $(common_dep)   $(srcdir)/paste.x       ../src/paste.c
 pathchk.1:     $(common_dep)   $(srcdir)/pathchk.x     ../src/pathchk.c
diff --git a/man/nproc.x b/man/nproc.x
new file mode 100644 (file)
index 0000000..870d6bd
--- /dev/null
@@ -0,0 +1,4 @@
+[NAME]
+nproc \- print the number of processing units available
+[DESCRIPTION]
+.\" Add any additional description here
index e84e2ea..9a46a9a 100644 (file)
@@ -89,6 +89,7 @@ src/mv.c
 src/nice.c
 src/nl.c
 src/nohup.c
+src/nproc.c
 src/od.c
 src/operand2sig.c
 src/paste.c
index f2886de..d397370 100644 (file)
@@ -56,6 +56,7 @@ mv
 nice
 nl
 nohup
+nproc
 od
 paste
 pathchk
index 67c29cc..be1df2b 100644 (file)
@@ -86,6 +86,7 @@ EXTRA_PROGRAMS = \
   mktemp       \
   mv           \
   nl           \
+  nproc                \
   nohup                \
   od           \
   paste                \
@@ -189,6 +190,7 @@ chown_LDADD = $(LDADD)
 chroot_LDADD = $(LDADD)
 cksum_LDADD = $(LDADD)
 comm_LDADD = $(LDADD)
+nproc_LDADD = $(LDADD)
 cp_LDADD = $(LDADD)
 csplit_LDADD = $(LDADD)
 cut_LDADD = $(LDADD)
@@ -480,6 +482,7 @@ rmdir_SOURCES = rmdir.c prog-fprintf.c
 
 uname_SOURCES = uname.c uname-uname.c
 arch_SOURCES = uname.c uname-arch.c
+nproc_SOURCES = nproc.c
 
 md5sum_SOURCES = md5sum.c
 md5sum_CPPFLAGS = -DHASH_ALGO_MD5=1 $(AM_CPPFLAGS)
diff --git a/src/nproc.c b/src/nproc.c
new file mode 100644 (file)
index 0000000..5c7aed1
--- /dev/null
@@ -0,0 +1,127 @@
+/* nproc - print the number of processors.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Giuseppe Scrivano.  */
+
+#include <config.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "system.h"
+#include "error.h"
+#include "nproc.h"
+#include "xstrtol.h"
+
+/* The official name of this program (e.g., no `g' prefix).  */
+#define PROGRAM_NAME "nproc"
+
+#define AUTHORS proper_name ("Giuseppe Scrivano")
+
+enum
+{
+  ALL_OPTION = CHAR_MAX + 1,
+  IGNORE_OPTION
+};
+
+static struct option const longopts[] =
+{
+  {"all", no_argument, NULL, ALL_OPTION},
+  {"ignore", required_argument, NULL, IGNORE_OPTION},
+  {GETOPT_HELP_OPTION_DECL},
+  {GETOPT_VERSION_OPTION_DECL},
+  {NULL, 0, NULL, 0}
+};
+
+void
+usage (int status)
+{
+  if (status != EXIT_SUCCESS)
+    fprintf (stderr, _("Try `%s --help' for more information.\n"),
+             program_name);
+  else
+    {
+      printf (_("Usage: %s [OPTION]...\n"), program_name);
+      fputs (_("\
+Print the number of processing units available to the current process,\n\
+which may be less than the number of online processors\n\
+\n\
+"), stdout);
+      fputs (_("\
+     --all       print the number of installed processors\n\
+     --ignore=N  if possible, exclude N processing units\n\
+"), stdout);
+
+      fputs (HELP_OPTION_DESCRIPTION, stdout);
+      fputs (VERSION_OPTION_DESCRIPTION, stdout);
+      emit_ancillary_info ();
+    }
+  exit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+  unsigned long nproc, ignore = 0;
+  initialize_main (&argc, &argv);
+  set_program_name (argv[0]);
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+
+  atexit (close_stdout);
+
+  enum nproc_query mode = NPROC_CURRENT_OVERRIDABLE;
+
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "", longopts, NULL);
+      if (c == -1)
+        break;
+      switch (c)
+        {
+        case_GETOPT_HELP_CHAR;
+
+        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
+
+        case ALL_OPTION:
+          mode = NPROC_ALL;
+          break;
+
+        case IGNORE_OPTION:
+          if (xstrtoul (optarg, NULL, 10, &ignore, "") != LONGINT_OK)
+            {
+              error (0, 0, _("%s: invalid number to ignore"), optarg);
+              usage (EXIT_FAILURE);
+            }
+          break;
+
+        default:
+          usage (EXIT_FAILURE);
+        }
+    }
+
+  nproc = num_processors (mode);
+
+  if (ignore < nproc)
+    nproc -= ignore;
+  else
+    nproc = 1;
+
+  printf ("%lu\n", nproc);
+
+  exit (EXIT_SUCCESS);
+}
index f67b796..f74d0a1 100644 (file)
@@ -189,6 +189,8 @@ TESTS =                                             \
   misc/nice-fail                               \
   misc/nl                                      \
   misc/nohup                                   \
+  misc/nproc-avail                             \
+  misc/nproc-positive                          \
   misc/od-N                                    \
   misc/od-multiple-t                           \
   misc/od-x8                                   \
diff --git a/tests/misc/nproc-avail b/tests/misc/nproc-avail
new file mode 100755 (executable)
index 0000000..dcbad25
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Ensure that "nproc" is less than or equal to "nproc --all".
+
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  nproc --version
+fi
+
+. $srcdir/test-lib.sh
+
+all=$(nproc --all)
+available=$(OMP_NUM_THREADS= nproc)
+
+test $available -le $all || fail=1
+
+Exit $fail
diff --git a/tests/misc/nproc-positive b/tests/misc/nproc-positive
new file mode 100755 (executable)
index 0000000..991647e
--- /dev/null
@@ -0,0 +1,48 @@
+#!/bin/sh
+# Ensure that nproc prints a number > 0
+
+# Copyright (C) 2009 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test "$VERBOSE" = yes; then
+  set -x
+  nproc --version
+fi
+
+. $srcdir/test-lib.sh
+
+for mode in --all ''; do
+    procs=$(nproc $mode)
+    test "$procs" -gt 0 || fail=1
+done
+
+for i in -1000 0 1 1000; do
+    procs=$(OMP_NUM_THREADS=$i nproc)
+    test "$procs" -gt 0 || fail=1
+done
+
+for i in 0 ' 1' 1000; do
+    procs=$(nproc --ignore="$i")
+    test "$procs" -gt 0 || fail=1
+done
+
+for i in -1 N; do
+    nproc --ignore=$i && fail=1
+done
+
+procs=$(OMP_NUM_THREADS=42 nproc --ignore=40)
+test "$procs" -eq 2 || fail=1
+
+Exit $fail