config/linux/proc.c

Go to the documentation of this file.
00001 /* Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
00002    Free Software Foundation, Inc.
00003    Contributed by Jakub Jelinek <jakub@redhat.com>.
00004 
00005    This file is part of the GNU OpenMP Library (libgomp).
00006 
00007    Libgomp is free software; you can redistribute it and/or modify it
00008    under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3, or (at your option)
00010    any later version.
00011 
00012    Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
00013    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00015    more details.
00016 
00017    Under Section 7 of GPL version 3, you are granted additional
00018    permissions described in the GCC Runtime Library Exception, version
00019    3.1, as published by the Free Software Foundation.
00020 
00021    You should have received a copy of the GNU General Public License and
00022    a copy of the GCC Runtime Library Exception along with this program;
00023    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00024    <http://www.gnu.org/licenses/>.  */
00025 
00026 /* This file contains system specific routines related to counting
00027    online processors and dynamic load balancing.  */
00028 
00029 #ifndef _GNU_SOURCE
00030 #define _GNU_SOURCE 1
00031 #endif
00032 #include "libgomp.h"
00033 #include <sched.h>
00034 #include <stdlib.h>
00035 #include <unistd.h>
00036 #ifdef HAVE_GETLOADAVG
00037 # ifdef HAVE_SYS_LOADAVG_H
00038 #  include <sys/loadavg.h>
00039 # endif
00040 #endif
00041 
00042 #ifdef HAVE_PTHREAD_AFFINITY_NP
00043 static unsigned long
00044 cpuset_popcount (cpu_set_t *cpusetp)
00045 {
00046 #ifdef CPU_COUNT
00047   /* glibc 2.6 and above provide a macro for this.  */
00048   return CPU_COUNT (cpusetp);
00049 #else
00050   size_t i;
00051   unsigned long ret = 0;
00052   extern int check[sizeof (cpusetp->__bits[0]) == sizeof (unsigned long int)];
00053 
00054   (void) check;
00055   for (i = 0; i < sizeof (*cpusetp) / sizeof (cpusetp->__bits[0]); i++)
00056     {
00057       unsigned long int mask = cpusetp->__bits[i];
00058       if (mask == 0)
00059     continue;
00060       ret += __builtin_popcountl (mask);
00061     }
00062   return ret;
00063 #endif
00064 }
00065 #endif
00066 
00067 /* At startup, determine the default number of threads.  It would seem
00068    this should be related to the number of cpus online.  */
00069 
00070 void
00071 gomp_init_num_threads (void)
00072 {
00073 #ifdef HAVE_PTHREAD_AFFINITY_NP
00074   cpu_set_t cpuset;
00075 
00076   if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset), &cpuset) == 0)
00077     {
00078       /* Count only the CPUs this process can use.  */
00079       gomp_global_icv.nthreads_var = cpuset_popcount (&cpuset);
00080       if (gomp_global_icv.nthreads_var == 0)
00081     gomp_global_icv.nthreads_var = 1;
00082       return;
00083     }
00084 #endif
00085 #ifdef _SC_NPROCESSORS_ONLN
00086   gomp_global_icv.nthreads_var = sysconf (_SC_NPROCESSORS_ONLN);
00087 #endif
00088 }
00089 
00090 static int
00091 get_num_procs (void)
00092 {
00093 #ifdef HAVE_PTHREAD_AFFINITY_NP
00094   cpu_set_t cpuset;
00095 
00096   if (gomp_cpu_affinity == NULL)
00097     {
00098       /* Count only the CPUs this process can use.  */
00099       if (pthread_getaffinity_np (pthread_self (), sizeof (cpuset),
00100                   &cpuset) == 0)
00101     {
00102       int ret = cpuset_popcount (&cpuset);
00103       return ret != 0 ? ret : 1;
00104     }
00105     }
00106   else
00107     {
00108       /* We can't use pthread_getaffinity_np in this case
00109      (we have changed it ourselves, it binds to just one CPU).
00110      Count instead the number of different CPUs we are
00111      using.  gomp_init_affinity updated gomp_available_cpus to
00112      the number of CPUs in the GOMP_AFFINITY mask that we are
00113      allowed to use though.  */
00114       return gomp_available_cpus;
00115     }
00116 #endif
00117 #ifdef _SC_NPROCESSORS_ONLN
00118   return sysconf (_SC_NPROCESSORS_ONLN);
00119 #else
00120   return gomp_icv (false)->nthreads_var;
00121 #endif
00122 }
00123 
00124 /* When OMP_DYNAMIC is set, at thread launch determine the number of
00125    threads we should spawn for this team.  */
00126 /* ??? I have no idea what best practice for this is.  Surely some
00127    function of the number of processors that are *still* online and
00128    the load average.  Here I use the number of processors online
00129    minus the 15 minute load average.  */
00130 
00131 unsigned
00132 gomp_dynamic_max_threads (void)
00133 {
00134   unsigned n_onln, loadavg, nthreads_var = gomp_icv (false)->nthreads_var;
00135 
00136   n_onln = get_num_procs ();
00137   if (n_onln > nthreads_var)
00138     n_onln = nthreads_var;
00139 
00140   loadavg = 0;
00141 #ifdef HAVE_GETLOADAVG
00142   {
00143     double dloadavg[3];
00144     if (getloadavg (dloadavg, 3) == 3)
00145       {
00146     /* Add 0.1 to get a kind of biased rounding.  */
00147     loadavg = dloadavg[2] + 0.1;
00148       }
00149   }
00150 #endif
00151 
00152   if (loadavg >= n_onln)
00153     return 1;
00154   else
00155     return n_onln - loadavg;
00156 }
00157 
00158 int
00159 omp_get_num_procs (void)
00160 {
00161   return get_num_procs ();
00162 }
00163 
00164 ialias (omp_get_num_procs)

Generated on Fri Apr 5 05:38:09 2013 for Libgomp by  doxygen 1.4.7