On 10/01/10 01:14, Giuseppe Scrivano wrote:
when --all fails for any reason, I think we should try with the number
of available processing units, at least it is a more accurate value than
return 1 (and document this behaviour).

Bruno, Jim, what do you think?

Just to summarize what's happening here...

There are 3 CPU counts possible:

total >= online >= available

"online" corresponds to the CPUs enabled system wide,
whereas "available" is what's available to a particular
process which may be less due to affinity config.

"online" is not currently exposed through nproc
but for reference is got on linux using:
$ strace -e open getconf _NPROCESSORS_ONLN
  open("/proc/stat"
    for_each_online_cpu() //available to scheduler

"available" on linux is determined using:
nproc
  glibc::sched_getaffinity()
    return corresponding_syscall();

"total" on linux is determined using:
nproc --all
  glibc::sysconf(_NPROCESSORS_CONF)
    __get_nprocs_conf ()
    {
      int result = 1;
      /* XXX Here will come a test for the new system call.  */
      if (open("/sys/devices/system/cpu"))
        result = parse();
      else if (open("/proc/cpuinfo"))
        result = parse();
      return result;
    }

The last one above is giving the issue as
it relies on /sys or /proc being available.
The XXX comment above suggests that there might
be a new syscall to get the total count, but
`man syscalls` doesn't show anything obvious to me.
Now we don't get a failure from sysconf(_NPROCESSORS_CONF),
so really that needs to be fixed. I think in the unusual
case where one can't open /proc/ or /sys/ that it should
try sched_getaffinity() as that will be at least as
accurate as hard coding "1" and will maintain the
expected count ordering above.
I will log a bug against glibc for this.

So what about a possible work around?
How about doing this in nproc(1):

if (num_processors(NPROC_ALL) == 1)
    return num_processors(NPROC_CURRENT_OVERRIDABLE)

That would of course do a redundant syscall in certain cases
but that might be OK actually as relative to the cost
of a process it's not much, and --all wouldn't
be the usual usage anyway.

The alternative of adding skips to the test seem
a bit more messy to me.

Proposed fix is attached.

cheers,
Pádraig.
>From 9eb8bf9a70a1390f894844020a5ff6ae74209a89 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Sun, 10 Jan 2010 02:04:34 +0000
Subject: [PATCH] nproc: return a possibly more accurate total CPU count

GNU/Linux systems that don't have /sys/ or /proc/ mounted
may return "1" for the total CPU count.  Incur the overhead of
the sched_getaffinity syscall in this case as though not
accurate may be more accurate than "1".  This addresses a
misc/nproc-avail test failure noticed by Dmitry V. Levin.
---
 src/nproc.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/src/nproc.c b/src/nproc.c
index 8092df7..d7b0305 100644
--- a/src/nproc.c
+++ b/src/nproc.c
@@ -116,6 +116,13 @@ main (int argc, char **argv)
 
   nproc = num_processors (mode);
 
+  /* On certain GNU/Linux systems where /sys/ or /proc/ are not mounted,
+   * num_processors (NPROC_ALL) will always return 1.  So in this case always
+   * call using NPROC_CURRENT_OVERRIDABLE as that uses a syscall
+   * to determine the count, and so may be more accurate in this case.  */
+  if (mode == NPROC_ALL && nproc == 1)
+    nproc = num_processors (NPROC_CURRENT_OVERRIDABLE);
+
   if (ignore < nproc)
     nproc -= ignore;
   else
-- 
1.6.2.5

Reply via email to