This source file includes following definitions.
- num_processors_via_affinity_mask
- num_processors_ignoring_omp
- parse_omp_threads
- num_processors
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 #include <config.h>
  21 #include "nproc.h"
  22 
  23 #include <limits.h>
  24 #include <stdlib.h>
  25 #include <unistd.h>
  26 
  27 #if HAVE_PTHREAD_GETAFFINITY_NP && 0
  28 # include <pthread.h>
  29 # include <sched.h>
  30 #endif
  31 #if HAVE_SCHED_GETAFFINITY_LIKE_GLIBC || HAVE_SCHED_GETAFFINITY_NP
  32 # include <sched.h>
  33 #endif
  34 
  35 #include <sys/types.h>
  36 
  37 #if HAVE_SYS_PSTAT_H
  38 # include <sys/pstat.h>
  39 #endif
  40 
  41 #if HAVE_SYS_SYSMP_H
  42 # include <sys/sysmp.h>
  43 #endif
  44 
  45 #if HAVE_SYS_PARAM_H
  46 # include <sys/param.h>
  47 #endif
  48 
  49 #if HAVE_SYS_SYSCTL_H && ! defined __GLIBC__
  50 # include <sys/sysctl.h>
  51 #endif
  52 
  53 #if defined _WIN32 && ! defined __CYGWIN__
  54 # define WIN32_LEAN_AND_MEAN
  55 # include <windows.h>
  56 #endif
  57 
  58 #include "c-ctype.h"
  59 
  60 #include "minmax.h"
  61 
  62 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
  63 
  64 
  65 
  66 
  67 
  68 static unsigned long
  69 num_processors_via_affinity_mask (void)
     
  70 {
  71   
  72 
  73 
  74 
  75 
  76 #if HAVE_PTHREAD_GETAFFINITY_NP && defined __GLIBC__ && 0
  77   {
  78     cpu_set_t set;
  79 
  80     if (pthread_getaffinity_np (pthread_self (), sizeof (set), &set) == 0)
  81       {
  82         unsigned long count;
  83 
  84 # ifdef CPU_COUNT
  85         
  86         count = CPU_COUNT (&set);
  87 # else
  88         size_t i;
  89 
  90         count = 0;
  91         for (i = 0; i < CPU_SETSIZE; i++)
  92           if (CPU_ISSET (i, &set))
  93             count++;
  94 # endif
  95         if (count > 0)
  96           return count;
  97       }
  98   }
  99 #elif HAVE_PTHREAD_GETAFFINITY_NP && defined __NetBSD__ && 0
 100   {
 101     cpuset_t *set;
 102 
 103     set = cpuset_create ();
 104     if (set != NULL)
 105       {
 106         unsigned long count = 0;
 107 
 108         if (pthread_getaffinity_np (pthread_self (), cpuset_size (set), set)
 109             == 0)
 110           {
 111             cpuid_t i;
 112 
 113             for (i = 0;; i++)
 114               {
 115                 int ret = cpuset_isset (i, set);
 116                 if (ret < 0)
 117                   break;
 118                 if (ret > 0)
 119                   count++;
 120               }
 121           }
 122         cpuset_destroy (set);
 123         if (count > 0)
 124           return count;
 125       }
 126   }
 127 #elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC 
 128   {
 129     cpu_set_t set;
 130 
 131     if (sched_getaffinity (0, sizeof (set), &set) == 0)
 132       {
 133         unsigned long count;
 134 
 135 # ifdef CPU_COUNT
 136         
 137         count = CPU_COUNT (&set);
 138 # else
 139         size_t i;
 140 
 141         count = 0;
 142         for (i = 0; i < CPU_SETSIZE; i++)
 143           if (CPU_ISSET (i, &set))
 144             count++;
 145 # endif
 146         if (count > 0)
 147           return count;
 148       }
 149   }
 150 #elif HAVE_SCHED_GETAFFINITY_NP 
 151   {
 152     cpuset_t *set;
 153 
 154     set = cpuset_create ();
 155     if (set != NULL)
 156       {
 157         unsigned long count = 0;
 158 
 159         if (sched_getaffinity_np (getpid (), cpuset_size (set), set) == 0)
 160           {
 161             cpuid_t i;
 162 
 163             for (i = 0;; i++)
 164               {
 165                 int ret = cpuset_isset (i, set);
 166                 if (ret < 0)
 167                   break;
 168                 if (ret > 0)
 169                   count++;
 170               }
 171           }
 172         cpuset_destroy (set);
 173         if (count > 0)
 174           return count;
 175       }
 176   }
 177 #endif
 178 
 179 #if defined _WIN32 && ! defined __CYGWIN__
 180   { 
 181     DWORD_PTR process_mask;
 182     DWORD_PTR system_mask;
 183 
 184     if (GetProcessAffinityMask (GetCurrentProcess (),
 185                                 &process_mask, &system_mask))
 186       {
 187         DWORD_PTR mask = process_mask;
 188         unsigned long count = 0;
 189 
 190         for (; mask != 0; mask = mask >> 1)
 191           if (mask & 1)
 192             count++;
 193         if (count > 0)
 194           return count;
 195       }
 196   }
 197 #endif
 198 
 199   return 0;
 200 }
 201 
 202 
 203 
 204 
 205 static unsigned long int
 206 num_processors_ignoring_omp (enum nproc_query query)
     
 207 {
 208   
 209 
 210 
 211 
 212 
 213 
 214 
 215 
 216 
 217 
 218 
 219 
 220 
 221 
 222 
 223   if (query == NPROC_CURRENT)
 224     {
 225       
 226       {
 227         unsigned long nprocs = num_processors_via_affinity_mask ();
 228 
 229         if (nprocs > 0)
 230           return nprocs;
 231       }
 232 
 233 #if defined _SC_NPROCESSORS_ONLN
 234       { 
 235 
 236         long int nprocs = sysconf (_SC_NPROCESSORS_ONLN);
 237         if (nprocs > 0)
 238           return nprocs;
 239       }
 240 #endif
 241     }
 242   else 
 243     {
 244 #if defined _SC_NPROCESSORS_CONF
 245       { 
 246 
 247         long int nprocs = sysconf (_SC_NPROCESSORS_CONF);
 248 
 249 # if __GLIBC__ >= 2 && defined __linux__
 250         
 251 
 252 
 253 
 254 
 255         if (nprocs == 1 || nprocs == 2)
 256           {
 257             unsigned long nprocs_current = num_processors_via_affinity_mask ();
 258 
 259             if ( nprocs_current > nprocs)
 260               nprocs = nprocs_current;
 261           }
 262 # endif
 263 
 264         if (nprocs > 0)
 265           return nprocs;
 266       }
 267 #endif
 268     }
 269 
 270 #if HAVE_PSTAT_GETDYNAMIC
 271   { 
 272     struct pst_dynamic psd;
 273     if (pstat_getdynamic (&psd, sizeof psd, 1, 0) >= 0)
 274       {
 275         
 276 
 277 
 278         if (query == NPROC_CURRENT)
 279           {
 280             if (psd.psd_proc_cnt > 0)
 281               return psd.psd_proc_cnt;
 282           }
 283         else
 284           {
 285             if (psd.psd_max_proc_cnt > 0)
 286               return psd.psd_max_proc_cnt;
 287           }
 288       }
 289   }
 290 #endif
 291 
 292 #if HAVE_SYSMP && defined MP_NAPROCS && defined MP_NPROCS
 293   { 
 294     
 295 
 296 
 297     int nprocs =
 298       sysmp (query == NPROC_CURRENT && getuid () != 0
 299              ? MP_NAPROCS
 300              : MP_NPROCS);
 301     if (nprocs > 0)
 302       return nprocs;
 303   }
 304 #endif
 305 
 306   
 307 
 308 
 309 #if HAVE_SYSCTL && ! defined __GLIBC__ && defined HW_NCPU
 310   { 
 311     int nprocs;
 312     size_t len = sizeof (nprocs);
 313     static int const mib[][2] = {
 314 # ifdef HW_NCPUONLINE
 315       { CTL_HW, HW_NCPUONLINE },
 316 # endif
 317       { CTL_HW, HW_NCPU }
 318     };
 319     for (int i = 0; i < ARRAY_SIZE (mib); i++)
 320       {
 321         if (sysctl (mib[i], ARRAY_SIZE (mib[i]), &nprocs, &len, NULL, 0) == 0
 322             && len == sizeof (nprocs)
 323             && 0 < nprocs)
 324           return nprocs;
 325       }
 326   }
 327 #endif
 328 
 329 #if defined _WIN32 && ! defined __CYGWIN__
 330   { 
 331     SYSTEM_INFO system_info;
 332     GetSystemInfo (&system_info);
 333     if (0 < system_info.dwNumberOfProcessors)
 334       return system_info.dwNumberOfProcessors;
 335   }
 336 #endif
 337 
 338   return 1;
 339 }
 340 
 341 
 342 
 343 static unsigned long int
 344 parse_omp_threads (char const* threads)
     
 345 {
 346   unsigned long int ret = 0;
 347 
 348   if (threads == NULL)
 349     return ret;
 350 
 351   
 352 
 353   while (*threads != '\0' && c_isspace (*threads))
 354     threads++;
 355 
 356   
 357   if (c_isdigit (*threads))
 358     {
 359       char *endptr = NULL;
 360       unsigned long int value = strtoul (threads, &endptr, 10);
 361 
 362       if (endptr != NULL)
 363         {
 364           while (*endptr != '\0' && c_isspace (*endptr))
 365             endptr++;
 366           if (*endptr == '\0')
 367             return value;
 368           
 369 
 370           else if (*endptr == ',')
 371             return value;
 372         }
 373     }
 374 
 375   return ret;
 376 }
 377 
 378 unsigned long int
 379 num_processors (enum nproc_query query)
     
 380 {
 381   unsigned long int omp_env_limit = ULONG_MAX;
 382 
 383   if (query == NPROC_CURRENT_OVERRIDABLE)
 384     {
 385       unsigned long int omp_env_threads;
 386       
 387 
 388       omp_env_threads = parse_omp_threads (getenv ("OMP_NUM_THREADS"));
 389       omp_env_limit = parse_omp_threads (getenv ("OMP_THREAD_LIMIT"));
 390       if (! omp_env_limit)
 391         omp_env_limit = ULONG_MAX;
 392 
 393       if (omp_env_threads)
 394         return MIN (omp_env_threads, omp_env_limit);
 395 
 396       query = NPROC_CURRENT;
 397     }
 398   
 399   {
 400     unsigned long nprocs = num_processors_ignoring_omp (query);
 401     return MIN (nprocs, omp_env_limit);
 402   }
 403 }