Index: bin/Makefile =================================================================== --- bin/Makefile +++ bin/Makefile @@ -24,6 +24,7 @@ ls \ mkdir \ mv \ + nproc \ pax \ pkill \ ps \ Index: bin/nproc/Makefile =================================================================== --- /dev/null +++ bin/nproc/Makefile @@ -0,0 +1,6 @@ +.include + +PACKAGE=runtime +PROG= nproc + +.include Index: bin/nproc/nproc.c =================================================================== --- /dev/null +++ bin/nproc/nproc.c @@ -0,0 +1,126 @@ +/* + * Public domain. + * Written by Mateusz Guzik + */ + +/* + * This program is intended to be compatible with the GNU coreutils variant. + * + * In order 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#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(1); +} + +/* + * GNU utils come with a --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 is in sync with. + */ +static void +version(void) +{ + printf("nproc (neither_GNU nor_coreutils) 8.32\n"); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + cpuset_t mask; + CPU_ZERO(&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: + errno = 0; + ignore = strtol(optarg, NULL, 10); + if (errno != 0 || ignore < 0) + errx(1, "ignore count must be a non-negative integer"); + break; + case OPT_VERSION: + version(); + __builtin_unreachable(); + case OPT_HELP: + help(); + exit(0); + default: + usage(); + } + } + + argc -= optind; + argv += optind; + + if (argc != 0) + usage(); + + if (all_flag) { + cpus = sysconf(_SC_NPROCESSORS_ONLN); + } else { + if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, + sizeof(mask), &mask) != 0) + err(EXIT_FAILURE, "getaffinity"); + cpus = CPU_COUNT(&mask); + } + + if (ignore >= cpus) + cpus = 1; + else + cpus -= ignore; + + printf("%u\n", cpus); + + return 0; +}