This provides a working thread::hardware_concurrency on platforms that support pthread_num_processors_np or the "hw.ncpu" sysctl, but by testing for the features in configure rather than hardcoding OS macro tests in thread.cc
* acinclude.m4 (GLIBCXX_CHECK_SC_NPROC_ONLN): Define. (GLIBCXX_CHECK_PTHREADS_NUM_PROCESSORS_NP): Define. (GLIBCXX_CHECK_SYSCTL_HW_NCPU): Define. * configure.ac: Use new checks. * configure: Regenerate. * config.h.in: Regenerate. * src/thread.cc: Check new config macros. * testsuite/lib/libstdc++.exp: Likewise. Tested x86_64-linux and x86_64-netbsd5.1, committed to trunk
Index: acinclude.m4 =================================================================== --- acinclude.m4 (revision 181081) +++ acinclude.m4 (working copy) @@ -3459,7 +3459,95 @@ AC_LANG_RESTORE ]) +dnl +dnl Check whether sysconf(_SC_NPROC_ONLN) is available in <unistd.h>, and define _GLIBCXX_USE_SC_NPROC_ONLN. +dnl +AC_DEFUN([GLIBCXX_CHECK_SC_NPROC_ONLN], [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-exceptions" + + AC_MSG_CHECKING([for _SC_NPROC_ONLN]) + AC_CACHE_VAL(glibcxx_cv_SC_NPROC_ONLN, [ + GCC_TRY_COMPILE_OR_LINK( + [#include <unistd.h>], + [int n = sysconf(_SC_NPROC_ONLN);], + [glibcxx_cv_SC_NPROC_ONLN=yes], + [glibcxx_cv_SC_NPROC_ONLN=no]) + ]) + if test $glibcxx_cv_SC_NPROC_ONLN = yes; then + AC_DEFINE(_GLIBCXX_USE_SC_NPROC_ONLN, 1, [Define if _SC_NPROC_ONLN is available in <unistd.h>.]) + fi + AC_MSG_RESULT($glibcxx_cv_SC_NPROC_ONLN) + + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) + +dnl +dnl Check whether pthread_num_processors_np is available in <pthread.h>, and define _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP. +dnl +AC_DEFUN([GLIBCXX_CHECK_PTHREADS_NUM_PROCESSORS_NP], [ + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-exceptions" + + AC_MSG_CHECKING([for pthreads_num_processors_np]) + AC_CACHE_VAL(glibcxx_cv_PTHREADS_NUM_PROCESSORS_NP, [ + GCC_TRY_COMPILE_OR_LINK( + [#include <pthread.h>], + [int n = pthread_num_processors_np();], + [glibcxx_cv_PTHREADS_NUM_PROCESSORS_NP=yes], + [glibcxx_cv_PTHREADS_NUM_PROCESSORS_NP=no]) + ]) + if test $glibcxx_cv_PTHREADS_NUM_PROCESSORS_NP = yes; then + AC_DEFINE(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP, 1, [Define if pthreads_num_processors_np is available in <pthread.h>.]) + fi + AC_MSG_RESULT($glibcxx_cv_PTHREADS_NUM_PROCESSORS_NP) + + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) + +dnl +dnl Check whether sysctl is available in <pthread.h>, and define _GLIBCXX_USE_SYSCTL_HW_NCPU. +dnl +AC_DEFUN([GLIBCXX_CHECK_SYSCTL_HW_NCPU], [ + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -fno-exceptions" + + AC_MSG_CHECKING([for hw.ncpu sysctl]) + AC_CACHE_VAL(glibcxx_cv_SYSCTL_HW_NCPU, [ + GCC_TRY_COMPILE_OR_LINK( + [ + #include <stddef.h> + #include <sys/sysctl.h> + ], + [ + int count; + size_t size = sizeof(count); + int mib[] = { CTL_HW, HW_NCPU }; + sysctl(mib, 2, &count, &size, NULL, 0); + ], + [glibcxx_cv_SYSCTL_HW_NCPU=yes], + [glibcxx_cv_SYSCTL_HW_NCPU=no]) + ]) + if test $glibcxx_cv_SYSCTL_HW_NCPU = yes; then + AC_DEFINE(_GLIBCXX_USE_SYSCTL_HW_NCPU, 1, [Define if sysctl(), CTL_HW and HW_NCPU are available in <sys/sysctl.h>.]) + fi + AC_MSG_RESULT($glibcxx_cv_SYSCTL_HW_NCPU) + + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) + # Macros from the top-level gcc directory. m4_include([../config/gc++filt.m4]) m4_include([../config/tls.m4]) Index: configure.ac =================================================================== --- configure.ac (revision 181081) +++ configure.ac (working copy) @@ -174,6 +174,9 @@ GLIBCXX_CHECK_GET_NPROCS AC_CHECK_HEADERS(unistd.h) GLIBCXX_CHECK_SC_NPROCESSORS_ONLN +GLIBCXX_CHECK_SC_NPROC_ONLN +GLIBCXX_CHECK_PTHREADS_NUM_PROCESSORS_NP +GLIBCXX_CHECK_SYSCTL_HW_NCPU # Check for available headers. AC_CHECK_HEADERS([endian.h execinfo.h float.h fp.h ieeefp.h inttypes.h \ Index: src/thread.cc =================================================================== --- src/thread.cc (revision 181081) +++ src/thread.cc (working copy) @@ -30,9 +30,27 @@ #if defined(_GLIBCXX_USE_GET_NPROCS) # include <sys/sysinfo.h> # define _GLIBCXX_NPROCS get_nprocs() +#elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP) +# define _GLIBCXX_NPROCS pthread_num_processors_np() +#elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU) +# include <stddef.h> +# include <sys/sysctl.h> +static inline int get_nprocs() +{ + int count; + size_t size = sizeof(count); + int mib[] = { CTL_HW, HW_NCPU }; + if (!sysctl(mib, 2, &count, &size, NULL, 0)) + return count; + return 0; +} +# define _GLIBCXX_NPROCS get_nprocs() #elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN) # include <unistd.h> # define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN) +#elif defined(_GLIBCXX_USE_SC_NPROC_ONLN) +# include <unistd.h> +# define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN) #else # define _GLIBCXX_NPROCS 0 #endif Index: testsuite/lib/libstdc++.exp =================================================================== --- testsuite/lib/libstdc++.exp (revision 181081) +++ testsuite/lib/libstdc++.exp (working copy) @@ -1673,13 +1673,12 @@ set f [open $src "w"] puts $f "#include <bits/c++config.h>" puts $f "#if defined(_GLIBCXX_USE_GET_NPROCS)" - puts $f "#elif defined(_GLIBCXX_USE_SYSCONF)" - puts $f "# include <unistd.h>" - puts $f "# if !defined(_SC_NPROCESSORS_ONLN)" - puts $f "# error No sysconf option" - puts $f "# endif" + puts $f "#elif defined(_GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP)" + puts $f "#elif defined(_GLIBCXX_USE_SYSCTL_HW_NCPU)" + puts $f "#elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)" + puts $f "#elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)" puts $f "#else" - puts $f "# error No get_nprocs or sysconf" + puts $f "# error hardware_concurrency not implemented" puts $f "#endif" close $f