X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fnproc.c;h=6fdaea0d09aa4ff2337cea6b7ee456b09775eca0;hb=1276a2c5f24c0c932426aca9c899fa524d2443f2;hp=af4da75d188f775c6852ae62de7e2eedf2b00097;hpb=b2e2010c7c902235b5efb5bd3c6529f61b093aa4;p=gnulib.git
diff --git a/lib/nproc.c b/lib/nproc.c
index af4da75d1..6fdaea0d0 100644
--- a/lib/nproc.c
+++ b/lib/nproc.c
@@ -1,6 +1,6 @@
/* Detect the number of processors.
- Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2009-2014 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -13,8 +13,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program; if not, see . */
/* Written by Glen Lenker and Bruno Haible. */
@@ -24,7 +23,7 @@
#include
#include
-#if HAVE_PTHREAD_AFFINITY_NP && 0
+#if HAVE_PTHREAD_GETAFFINITY_NP && 0
# include
# include
#endif
@@ -59,6 +58,144 @@
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+/* Return the number of processors available to the current process, based
+ on a modern system call that returns the "affinity" between the current
+ process and each CPU. Return 0 if unknown or if such a system call does
+ not exist. */
+static unsigned long
+num_processors_via_affinity_mask (void)
+{
+ /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np,
+ but with different APIs. Also it requires linking with -lpthread.
+ Therefore this code is not enabled.
+ glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has
+ sched_getaffinity_np. */
+#if HAVE_PTHREAD_GETAFFINITY_NP && defined __GLIBC__ && 0
+ {
+ cpu_set_t set;
+
+ if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
+ {
+ unsigned long count;
+
+# ifdef CPU_COUNT
+ /* glibc >= 2.6 has the CPU_COUNT macro. */
+ count = CPU_COUNT (&set);
+# else
+ size_t i;
+
+ count = 0;
+ for (i = 0; i < CPU_SETSIZE; i++)
+ if (CPU_ISSET (i, &set))
+ count++;
+# endif
+ if (count > 0)
+ return count;
+ }
+ }
+#elif HAVE_PTHREAD_GETAFFINITY_NP && defined __NetBSD__ && 0
+ {
+ cpuset_t *set;
+
+ set = cpuset_create ();
+ if (set != NULL)
+ {
+ unsigned long count = 0;
+
+ if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
+ == 0)
+ {
+ cpuid_t i;
+
+ for (i = 0;; i++)
+ {
+ int ret = cpuset_isset (i, set);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ count++;
+ }
+ }
+ cpuset_destroy (set);
+ if (count > 0)
+ return count;
+ }
+ }
+#elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */
+ {
+ cpu_set_t set;
+
+ if (sched_getaffinity (0, sizeof (set), &set) == 0)
+ {
+ unsigned long count;
+
+# ifdef CPU_COUNT
+ /* glibc >= 2.6 has the CPU_COUNT macro. */
+ count = CPU_COUNT (&set);
+# else
+ size_t i;
+
+ count = 0;
+ for (i = 0; i < CPU_SETSIZE; i++)
+ if (CPU_ISSET (i, &set))
+ count++;
+# endif
+ if (count > 0)
+ return count;
+ }
+ }
+#elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */
+ {
+ cpuset_t *set;
+
+ set = cpuset_create ();
+ if (set != NULL)
+ {
+ unsigned long count = 0;
+
+ if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
+ {
+ cpuid_t i;
+
+ for (i = 0;; i++)
+ {
+ int ret = cpuset_isset (i, set);
+ if (ret < 0)
+ break;
+ if (ret > 0)
+ count++;
+ }
+ }
+ cpuset_destroy (set);
+ if (count > 0)
+ return count;
+ }
+ }
+#endif
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ { /* This works on native Windows platforms. */
+ DWORD_PTR process_mask;
+ DWORD_PTR system_mask;
+
+ if (GetProcessAffinityMask (GetCurrentProcess (),
+ &process_mask, &system_mask))
+ {
+ DWORD_PTR mask = process_mask;
+ unsigned long count = 0;
+
+ for (; mask != 0; mask = mask >> 1)
+ if (mask & 1)
+ count++;
+ if (count > 0)
+ return count;
+ }
+ }
+#endif
+
+ return 0;
+}
+
unsigned long int
num_processors (enum nproc_query query)
{
@@ -94,138 +231,32 @@ num_processors (enum nproc_query query)
}
/* Here query is one of NPROC_ALL, NPROC_CURRENT. */
- if (query == NPROC_CURRENT)
- {
- /* glibc >= 2.3.3 with NPTL and NetBSD 5 have pthread_getaffinity_np,
- but with different APIs. Also it requires linking with -lpthread.
- Therefore this code is not enabled.
- glibc >= 2.3.4 has sched_getaffinity whereas NetBSD 5 has
- sched_getaffinity_np. */
-#if HAVE_PTHREAD_AFFINITY_NP && defined __GLIBC__ && 0
- {
- cpu_set_t set;
-
- if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
- {
- unsigned long count;
-
-# ifdef CPU_COUNT
- /* glibc >= 2.6 has the CPU_COUNT macro. */
- count = CPU_COUNT (&set);
-# else
- size_t i;
-
- count = 0;
- for (i = 0; i < CPU_SETSIZE; i++)
- if (CPU_ISSET (i, &set))
- count++;
-# endif
- if (count > 0)
- return count;
- }
- }
-#elif HAVE_PTHREAD_AFFINITY_NP && defined __NetBSD__ && 0
- {
- cpuset_t *set;
-
- set = cpuset_create ();
- if (set != NULL)
- {
- unsigned long count = 0;
+ /* On systems with a modern affinity mask system call, we have
+ sysconf (_SC_NPROCESSORS_CONF)
+ >= sysconf (_SC_NPROCESSORS_ONLN)
+ >= num_processors_via_affinity_mask ()
+ The first number is the number of CPUs configured in the system.
+ The second number is the number of CPUs available to the scheduler.
+ The third number is the number of CPUs available to the current process.
- if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
- == 0)
- {
- cpuid_t i;
-
- for (i = 0;; i++)
- {
- int ret = cpuset_isset (i, set);
- if (ret < 0)
- break;
- if (ret > 0)
- count++;
- }
- }
- cpuset_destroy (set);
- if (count > 0)
- return count;
- }
- }
-#elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */
- {
- cpu_set_t set;
+ Note! On Linux systems with glibc, the first and second number come from
+ the /sys and /proc file systems (see
+ glibc/sysdeps/unix/sysv/linux/getsysstats.c).
+ In some situations these file systems are not mounted, and the sysconf
+ call returns 1, which does not reflect the reality. */
- if (sched_getaffinity (0, sizeof (set), &set) == 0)
- {
- unsigned long count;
-
-# ifdef CPU_COUNT
- /* glibc >= 2.6 has the CPU_COUNT macro. */
- count = CPU_COUNT (&set);
-# else
- size_t i;
-
- count = 0;
- for (i = 0; i < CPU_SETSIZE; i++)
- if (CPU_ISSET (i, &set))
- count++;
-# endif
- if (count > 0)
- return count;
- }
- }
-#elif HAVE_SCHED_GETAFFINITY_NP /* NetBSD >= 5 */
+ if (query == NPROC_CURRENT)
+ {
+ /* Try the modern affinity mask system call. */
{
- cpuset_t *set;
-
- set = cpuset_create ();
- if (set != NULL)
- {
- unsigned long count = 0;
-
- if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
- {
- cpuid_t i;
-
- for (i = 0;; i++)
- {
- int ret = cpuset_isset (i, set);
- if (ret < 0)
- break;
- if (ret > 0)
- count++;
- }
- }
- cpuset_destroy (set);
- if (count > 0)
- return count;
- }
- }
-#endif
+ unsigned long nprocs = num_processors_via_affinity_mask ();
-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
- { /* This works on native Windows platforms. */
- DWORD_PTR process_mask;
- DWORD_PTR system_mask;
-
- if (GetProcessAffinityMask (GetCurrentProcess (),
- &process_mask, &system_mask))
- {
- DWORD_PTR mask = process_mask;
- unsigned long count = 0;
-
- for (; mask != 0; mask = mask >> 1)
- if (mask & 1)
- count++;
- if (count > 0)
- return count;
- }
+ if (nprocs > 0)
+ return nprocs;
}
-#endif
#if defined _SC_NPROCESSORS_ONLN
- { /* This works on glibc, MacOS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
+ { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
Cygwin, Haiku. */
long int nprocs = sysconf (_SC_NPROCESSORS_ONLN);
if (nprocs > 0)
@@ -236,9 +267,25 @@ num_processors (enum nproc_query query)
else /* query == NPROC_ALL */
{
#if defined _SC_NPROCESSORS_CONF
- { /* This works on glibc, MacOS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
+ { /* This works on glibc, Mac OS X 10.5, FreeBSD, AIX, OSF/1, Solaris,
Cygwin, Haiku. */
long int nprocs = sysconf (_SC_NPROCESSORS_CONF);
+
+# if __GLIBC__ >= 2 && defined __linux__
+ /* On Linux systems with glibc, this information comes from the /sys and
+ /proc file systems (see glibc/sysdeps/unix/sysv/linux/getsysstats.c).
+ In some situations these file systems are not mounted, and the
+ sysconf call returns 1. But we wish to guarantee that
+ num_processors (NPROC_ALL) >= num_processors (NPROC_CURRENT). */
+ if (nprocs == 1)
+ {
+ unsigned long nprocs_current = num_processors_via_affinity_mask ();
+
+ if (nprocs_current > 0)
+ nprocs = nprocs_current;
+ }
+# endif
+
if (nprocs > 0)
return nprocs;
}
@@ -285,7 +332,7 @@ num_processors (enum nproc_query query)
NPROC_CURRENT and NPROC_ALL. */
#if HAVE_SYSCTL && defined HW_NCPU
- { /* This works on MacOS X, FreeBSD, NetBSD, OpenBSD. */
+ { /* This works on Mac OS X, FreeBSD, NetBSD, OpenBSD. */
int nprocs;
size_t len = sizeof (nprocs);
static int mib[2] = { CTL_HW, HW_NCPU };