diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2023-03-08 09:08:42 +0200 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2023-03-30 13:58:04 +0300 |
commit | deaebd0c89a6d453bb971fd8f5a3b858e7a95733 (patch) | |
tree | 726f04d7216e10057f13c31cef44d9399d617d90 /rpmio/macro.c | |
parent | 0dad385cbcd7a9731b0cba44a4b4dcc89558ff89 (diff) | |
download | rpm-deaebd0c89a6d453bb971fd8f5a3b858e7a95733.tar.gz |
Add optional total/proc/thread arguments to %{getncpus} macro
"total" equals calling with no arguments, "proc" and "thread" consider
further constraints, what is implemented here is heuristics based on
available physical memory and address-space and %_smp_tasksize_proc /
%_smp_tasksize_thread tunables.
Change the previous %getncpus related tests to use %getconfdir instead,
they are testing unexpected arguments behavior for this type of macro,
not %getncpus itself. Add a test for the actual functionality: if nproc
is available, test that our total matches with that, and that defining
tasksize to total memory only allocates one thread. Optimally we'd
test separately for 32bit address space limitations but that gets tough
when we have no idea where this will be executed.
Diffstat (limited to 'rpmio/macro.c')
-rw-r--r-- | rpmio/macro.c | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/rpmio/macro.c b/rpmio/macro.c index d86b84608..5dc926213 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -9,6 +9,9 @@ #ifdef HAVE_SCHED_GETAFFINITY #include <sched.h> #endif +#if defined(__linux__) +#include <sys/personality.h> +#endif #if !defined(isblank) #define isblank(_c) ((_c) == ' ' || (_c) == '\t') @@ -1174,6 +1177,89 @@ static void doShescape(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parse mbAppend(mb, '\''); } +static unsigned long getmem_total(void) +{ + unsigned long mem = 0; + long int pagesize = sysconf(_SC_PAGESIZE); + long int pages = sysconf(_SC_PHYS_PAGES); + + if (pagesize < 0) + pagesize = 4096; + if (pages > 0) + mem = pages * pagesize; + + return mem; +} + +static unsigned long getmem_proc(int thread) +{ + unsigned long mem = getmem_total(); + /* + * Conservative estimates for thread use on 32bit systems where address + * space is an issue: 2GB for bare metal, 3GB for a 32bit process + * on a 64bit system. + */ + if (thread) { + unsigned long vmem = mem; +#if __WORDSIZE == 32 + vmem = UINT32_MAX / 2; +#else +#if defined(__linux__) + if ((personality(0xffffffff) & PER_MASK) == PER_LINUX32) + vmem = (UINT32_MAX / 4) * 3; +#endif +#endif + if (vmem < mem) + mem = vmem; + } + /* Fixup to get nice even numbers */ + mem = mem / (1024*1024) + 1; + + return mem; +} + +static void doGetncpus(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed) +{ + const char *sizemacro = NULL; + const char *arg = argv[1] ? argv[1] : "total"; + char buf[32]; + unsigned int ncpus = getncpus(); + unsigned long mem = 0; + + if (rstreq(arg, "total")) { + /* nothing */ + } else if (rstreq(arg, "proc")) { + mem = getmem_proc(0); + sizemacro = "%{?_smp_tasksize_proc}"; + } else if (rstreq(arg, "thread")) { + mem = getmem_proc(1); + sizemacro = "%{?_smp_tasksize_thread}"; + } else { + mbErr(mb, 1, _("invalid argument: %s\n"), arg); + return; + } + + if (sizemacro) { + unsigned int mcpus; + unsigned long tasksize = rpmExpandNumeric(sizemacro); + + if (tasksize == 0) + tasksize = 512; + + if (mem == 0) { + mbErr(mb, 1, _("failed to get available memory for %s\n"), arg); + return; + } + + mcpus = mem / tasksize; + if (mcpus < ncpus) + ncpus = mcpus; + } + + sprintf(buf, "%u", ncpus); + mbAppendStr(mb, buf); +} + static void doFoo(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed) { char *buf = NULL; @@ -1227,9 +1313,6 @@ static void doFoo(MacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed) b = getenv(argv[1]); } else if (rstreq("getconfdir", me->name)) { b = (char *)rpmConfigDir(); - } else if (rstreq("getncpus", me->name)) { - b = buf = xmalloc(MACROBUFSIZ); - sprintf(buf, "%u", getncpus()); } else if (rstreq("exists", me->name)) { b = (access(argv[1], F_OK) == 0) ? "1" : "0"; } @@ -1276,7 +1359,7 @@ static struct builtins_s { { "expr", doFoo, 1, 0 }, { "getconfdir", doFoo, 0, 0 }, { "getenv", doFoo, 1, 0 }, - { "getncpus", doFoo, 0, 0 }, + { "getncpus", doGetncpus, -1, 0 }, { "global", doGlobal, 1, ME_PARSE }, { "gsub", doString, 1, 0 }, { "len", doString, 1, 0 }, |