busybox/coreutils/nproc.c
Denys Vlasenko 2075553a1b libbb: add bit counting function, use where appropriate
Although "naive" counting function is not too slow and is smaller,
using it on e.g. each of 1024 words of CPU mask feels wrong.

function                                             old     new   delta
bb_popcnt_32                                           -      52     +52
get_prefix                                           323     321      -2
nproc_main                                           206     199      -7
d4_run_script                                        739     731      -8
ipcalc_main                                          533     507     -26
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/4 up/down: 52/-43)              Total: 9 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2024-05-31 16:03:23 +02:00

73 lines
1.7 KiB
C

/*
* Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
*
* Licensed under GPLv2, see LICENSE in this source tree
*/
//config:config NPROC
//config: bool "nproc (3.9 kb)"
//config: default y
//config: help
//config: Print number of CPUs
//applet:IF_NPROC(APPLET_NOFORK(nproc, nproc, BB_DIR_USR_BIN, BB_SUID_DROP, nproc))
//kbuild:lib-$(CONFIG_NPROC) += nproc.o
//usage:#define nproc_trivial_usage
//usage: ""IF_LONG_OPTS("[--all] [--ignore=N]")
//usage:#define nproc_full_usage "\n\n"
//usage: "Print number of available CPUs"
//usage: IF_LONG_OPTS(
//usage: "\n"
//usage: "\n --all Number of installed CPUs"
//usage: "\n --ignore=N Exclude N CPUs"
//usage: )
#include "libbb.h"
int nproc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int nproc_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
{
int count = 0;
#if ENABLE_LONG_OPTS
int ignore = 0;
int opts = getopt32long(argv, "\xfe:+",
"ignore\0" Required_argument "\xfe"
"all\0" No_argument "\xff"
, &ignore
);
if (opts & (1 << 1)) {
DIR *cpusd = opendir("/sys/devices/system/cpu");
if (cpusd) {
struct dirent *de;
while (NULL != (de = readdir(cpusd))) {
char *cpuid = strstr(de->d_name, "cpu");
if (cpuid && isdigit(cpuid[strlen(cpuid) - 1]))
count++;
}
IF_FEATURE_CLEAN_UP(closedir(cpusd);)
}
} else
#endif
{
int i;
unsigned sz = 2 * 1024;
unsigned long *mask = get_malloc_cpu_affinity(0, &sz);
sz /= sizeof(long);
for (i = 0; i < sz; i++) {
if (mask[i] != 0) /* most mask[i] are usually 0 */
count += bb_popcnt_long(mask[i]);
}
IF_FEATURE_CLEAN_UP(free(mask);)
}
IF_LONG_OPTS(count -= ignore;)
if (count <= 0)
count = 1;
printf("%u\n", count);
return 0;
}