1*8feb0f0bSmrg /* Copyright (C) 2005-2020 Free Software Foundation, Inc.
236ac495dSmrg Contributed by Richard Henderson <rth@redhat.com>.
336ac495dSmrg
436ac495dSmrg This file is part of the GNU Offloading and Multi Processing Library
536ac495dSmrg (libgomp).
636ac495dSmrg
736ac495dSmrg Libgomp is free software; you can redistribute it and/or modify it
836ac495dSmrg under the terms of the GNU General Public License as published by
936ac495dSmrg the Free Software Foundation; either version 3, or (at your option)
1036ac495dSmrg any later version.
1136ac495dSmrg
1236ac495dSmrg Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
1336ac495dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1436ac495dSmrg FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1536ac495dSmrg more details.
1636ac495dSmrg
1736ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1836ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1936ac495dSmrg 3.1, as published by the Free Software Foundation.
2036ac495dSmrg
2136ac495dSmrg You should have received a copy of the GNU General Public License and
2236ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2336ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2436ac495dSmrg <http://www.gnu.org/licenses/>. */
2536ac495dSmrg
2636ac495dSmrg /* This file contains system specific routines related to counting
2736ac495dSmrg online processors and dynamic load balancing. It is expected that
2836ac495dSmrg a system may well want to write special versions of each of these.
2936ac495dSmrg
3036ac495dSmrg The following implementation uses a mix of POSIX and BSD routines. */
3136ac495dSmrg
3236ac495dSmrg #include "libgomp.h"
3336ac495dSmrg #include <unistd.h>
3436ac495dSmrg #include <stdlib.h>
3536ac495dSmrg #ifdef HAVE_GETLOADAVG
3636ac495dSmrg # ifdef HAVE_SYS_LOADAVG_H
3736ac495dSmrg # include <sys/loadavg.h>
3836ac495dSmrg # endif
3936ac495dSmrg #endif
4036ac495dSmrg #ifdef HAVE_SYS_SYSCTL_H
4136ac495dSmrg # include <sys/sysctl.h>
4236ac495dSmrg #endif
4336ac495dSmrg
4436ac495dSmrg static int
get_num_procs(void)4536ac495dSmrg get_num_procs (void)
4636ac495dSmrg {
4736ac495dSmrg #ifdef _SC_NPROCESSORS_ONLN
4836ac495dSmrg return sysconf (_SC_NPROCESSORS_ONLN);
4936ac495dSmrg #elif defined HW_NCPU
5036ac495dSmrg int ncpus = 1;
5136ac495dSmrg size_t len = sizeof(ncpus);
5236ac495dSmrg sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
5336ac495dSmrg return ncpus;
5436ac495dSmrg #else
5536ac495dSmrg return 0;
5636ac495dSmrg #endif
5736ac495dSmrg }
5836ac495dSmrg
5936ac495dSmrg /* At startup, determine the default number of threads. It would seem
6036ac495dSmrg this should be related to the number of cpus online. */
6136ac495dSmrg
6236ac495dSmrg void
gomp_init_num_threads(void)6336ac495dSmrg gomp_init_num_threads (void)
6436ac495dSmrg {
6536ac495dSmrg int ncpus = get_num_procs ();
6636ac495dSmrg
6736ac495dSmrg if (ncpus > 0)
6836ac495dSmrg gomp_global_icv.nthreads_var = ncpus;
6936ac495dSmrg }
7036ac495dSmrg
7136ac495dSmrg /* When OMP_DYNAMIC is set, at thread launch determine the number of
7236ac495dSmrg threads we should spawn for this team. */
7336ac495dSmrg /* ??? I have no idea what best practice for this is. Surely some
7436ac495dSmrg function of the number of processors that are *still* online and
7536ac495dSmrg the load average. Here I use the number of processors online
7636ac495dSmrg minus the 15 minute load average. */
7736ac495dSmrg
7836ac495dSmrg unsigned
gomp_dynamic_max_threads(void)7936ac495dSmrg gomp_dynamic_max_threads (void)
8036ac495dSmrg {
8136ac495dSmrg unsigned n_onln, loadavg;
8236ac495dSmrg unsigned nthreads_var = gomp_icv (false)->nthreads_var;
8336ac495dSmrg
8436ac495dSmrg n_onln = get_num_procs ();
8536ac495dSmrg if (!n_onln || n_onln > nthreads_var)
8636ac495dSmrg n_onln = nthreads_var;
8736ac495dSmrg
8836ac495dSmrg loadavg = 0;
8936ac495dSmrg #ifdef HAVE_GETLOADAVG
9036ac495dSmrg {
9136ac495dSmrg double dloadavg[3];
9236ac495dSmrg if (getloadavg (dloadavg, 3) == 3)
9336ac495dSmrg {
9436ac495dSmrg /* Add 0.1 to get a kind of biased rounding. */
9536ac495dSmrg loadavg = dloadavg[2] + 0.1;
9636ac495dSmrg }
9736ac495dSmrg }
9836ac495dSmrg #endif
9936ac495dSmrg
10036ac495dSmrg if (loadavg >= n_onln)
10136ac495dSmrg return 1;
10236ac495dSmrg else
10336ac495dSmrg return n_onln - loadavg;
10436ac495dSmrg }
10536ac495dSmrg
10636ac495dSmrg int
omp_get_num_procs(void)10736ac495dSmrg omp_get_num_procs (void)
10836ac495dSmrg {
10936ac495dSmrg int ncpus = get_num_procs ();
11036ac495dSmrg if (ncpus <= 0)
11136ac495dSmrg ncpus = gomp_icv (false)->nthreads_var;
11236ac495dSmrg return ncpus;
11336ac495dSmrg }
11436ac495dSmrg
11536ac495dSmrg ialias (omp_get_num_procs)
116