aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2023-02-04 23:33:48 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2023-02-23 17:51:07 +0000
commiteb9e9f1c2533a8b01446e14a46f45eb7b0cd71e2 (patch)
tree36a32238b84eddcaf9c05d80b9359d4001f7cd2e
parent5e8827063b9f565697135b33399a64ca9f000a02 (diff)
downloadsrc-eb9e9f1c2533a8b01446e14a46f45eb7b0cd71e2.tar.gz
src-eb9e9f1c2533a8b01446e14a46f45eb7b0cd71e2.zip
Add nproc(1)
This program prints the number of CPU threads it can run on, while respecting cpusets (or not, depending on switches). It aims to be compatible with nproc as found in GNU coreutils. Approved by: re (cperciva) Reviewed by: des Reviewed by: pstef Differential Revision: https://reviews.freebsd.org/D38386 (cherry picked from commit 48bfd3597654490cdc43bf0f591a539d3a28b590) (cherry picked from commit 31f9db72a35bb20ad01d792eaaa1d6048252ab38)
-rw-r--r--bin/Makefile1
-rw-r--r--bin/nproc/Makefile4
-rw-r--r--bin/nproc/nproc.154
-rw-r--r--bin/nproc/nproc.c132
-rw-r--r--usr.bin/cpuset/cpuset.11
5 files changed, 192 insertions, 0 deletions
diff --git a/bin/Makefile b/bin/Makefile
index cdd96d0b84e8..83bf79dcb9f9 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -24,6 +24,7 @@ SUBDIR= cat \
ls \
mkdir \
mv \
+ nproc \
pax \
pkill \
ps \
diff --git a/bin/nproc/Makefile b/bin/nproc/Makefile
new file mode 100644
index 000000000000..2a57083b9d40
--- /dev/null
+++ b/bin/nproc/Makefile
@@ -0,0 +1,4 @@
+PACKAGE=runtime
+PROG= nproc
+
+.include <bsd.prog.mk>
diff --git a/bin/nproc/nproc.1 b/bin/nproc/nproc.1
new file mode 100644
index 000000000000..ae252fe0f50c
--- /dev/null
+++ b/bin/nproc/nproc.1
@@ -0,0 +1,54 @@
+.\"-
+.\" * Copyright (c) 2023 Piotr Paweł Stefaniak
+.\"
+.\" * SPDX-License-Identifier: BSD-2-Clause
+.\"
+.Dd February 5, 2023
+.Dt NPROC 1
+.Os
+.Sh NAME
+.Nm nproc
+.Nd print the number of processors
+.Sh SYNOPSIS
+.Nm
+.Op Fl -all
+.Op Fl -ignore Ns = Ns Ar count
+.Nm Fl -help
+.Nm Fl -version
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to print the number of processors limited to the
+.Xr cpuset 2
+of the current process, unless the
+.Fl -all
+flag is specified.
+.Pp
+The available flags are:
+.Bl -tag -width Ds
+.It Fl -all
+Count all processors currently online.
+.It Fl -ignore Ns = Ns Ar count
+The result is decreased by
+.Ar count ,
+but never below 1.
+.It Fl -version
+Print the current program version and exit. Don't use this option.
+.It Fl -help
+Print usage information and exit.
+.El
+.Sh COMPATIBILITY
+This program is intended to be compatible with nproc as found in GNU coreutils.
+.Sh SEE ALSO
+.Xr cpuset 1
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 14.0 .
+.Sh AUTHORS
+.An -nosplit
+.An Mateusz Guzik Aq Mt mjg@FreeBSD.org
+wrote the program and
+.An Piotr Paweł Stefaniak Aq Mt pstef@FreeBSD.org
+wrote this page.
diff --git a/bin/nproc/nproc.c b/bin/nproc/nproc.c
new file mode 100644
index 000000000000..9037c74dbfff
--- /dev/null
+++ b/bin/nproc/nproc.c
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 2023 Mateusz Guzik
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * This program is intended to be compatible with nproc as found in GNU
+ * coreutils.
+ *
+ * In order to maintain that, do not add any features here if they are not
+ * present in said program. If you are looking for anything more advanced you
+ * probably should patch cpuset(1) instead.
+ */
+
+#include <sys/param.h>
+#include <sys/cpuset.h>
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#define OPT_ALL (CHAR_MAX + 1)
+#define OPT_IGNORE (CHAR_MAX + 2)
+#define OPT_VERSION (CHAR_MAX + 3)
+#define OPT_HELP (CHAR_MAX + 4)
+
+static struct option long_opts[] = {
+ { "all", no_argument, NULL, OPT_ALL },
+ { "ignore", required_argument, NULL, OPT_IGNORE },
+ { "version", no_argument, NULL, OPT_VERSION },
+ { "help", no_argument, NULL, OPT_HELP },
+ { NULL, 0, NULL, 0 }
+};
+
+static void
+help(void)
+{
+ fprintf(stderr,
+ "usage: nproc [--all] [--ignore=count]\n");
+ fprintf(stderr,
+ " nproc --help\n");
+ fprintf(stderr,
+ " nproc --version\n");
+}
+
+static void
+usage(void)
+{
+ help();
+ exit(EX_USAGE);
+}
+
+/*
+ * GNU variant ships with the --version switch.
+ *
+ * While we don't have anything to put there, print something which is
+ * whitespace-compatible with the original. Version number was taken
+ * from coreutils this code is in sync with.
+ */
+static void
+version(void)
+{
+ printf("nproc (neither_GNU nor_coreutils) 8.32\n");
+ exit(EXIT_SUCCESS);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *errstr;
+ cpuset_t mask;
+ int ch, cpus, ignore;
+ bool all_flag;
+
+ ignore = 0;
+ all_flag = false;
+
+ while ((ch = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+ switch (ch) {
+ case OPT_ALL:
+ all_flag = true;
+ break;
+ case OPT_IGNORE:
+ ignore = strtonum(optarg, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "bad ignore count: %s", errstr);
+ break;
+ case OPT_VERSION:
+ version();
+ __builtin_unreachable();
+ case OPT_HELP:
+ help();
+ exit(EXIT_SUCCESS);
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0)
+ usage();
+
+ if (all_flag) {
+ cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ if (cpus == -1)
+ err(1, "sysconf");
+ } else {
+ CPU_ZERO(&mask);
+ if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1,
+ sizeof(mask), &mask) != 0)
+ err(1, "cpuset_getaffinity");
+ cpus = CPU_COUNT(&mask);
+ }
+
+ if (ignore >= cpus)
+ cpus = 1;
+ else
+ cpus -= ignore;
+
+ printf("%u\n", cpus);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/usr.bin/cpuset/cpuset.1 b/usr.bin/cpuset/cpuset.1
index 935164394b31..1d0180c98991 100644
--- a/usr.bin/cpuset/cpuset.1
+++ b/usr.bin/cpuset/cpuset.1
@@ -217,6 +217,7 @@ Create a new cpuset that is restricted to CPUs 0 and 2 and move
into the new set:
.Dl cpuset -C -c -l 0,2 -p <pid>
.Sh SEE ALSO
+.Xr nproc 1 ,
.Xr cpuset 2 ,
.Xr rctl 8
.Sh HISTORY