diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index a936d189f4c..4cfcab2258d 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -314,9 +314,20 @@ QThreadPrivate::~QThreadPrivate() /*! \fn int QThread::idealThreadCount() - Returns the ideal number of threads that can be run on the system. This is done querying - the number of processor cores, both real and logical, in the system. This function returns 1 - if the number of processor cores could not be detected. + Returns the ideal number of threads that this process can run in parallel. + This is done by querying the number of logical processors available to this + process (if supported by this OS) or the total number of logical processors + in the system. This function returns 1 if neither value could be + determined. + + \note On operating systems that support setting a thread's affinity to a + subset of all logical processors, the value returned by this function may + change between threads and over time. + + \note On operating systems that support CPU hotplugging and hot-unplugging, + the value returned by this function may also change over time (and note + that CPUs can be turned on and off by software, without a physical, + hardware change). */ /*! diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 8fa4e939f83..79abfe7e500 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -70,8 +70,10 @@ #include #include -#ifdef Q_OS_BSD4 -#include +#if defined(Q_OS_FREEBSD) +# include +#elif defined(Q_OS_BSD4) +# include #endif #ifdef Q_OS_VXWORKS # if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6)) @@ -455,8 +457,31 @@ int QThread::idealThreadCount() noexcept } else { cores = (int)psd.psd_proc_cnt; } +#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) +# ifdef Q_OS_FREEBSD +# define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp)) + // match the Linux API for simplicity + using cpu_set_t = cpuset_t; + auto sched_getaffinity = [](pid_t, size_t cpusetsize, cpu_set_t *mask) { + return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, cpusetsize, mask); + }; +# endif + + // get the number of threads we're assigned, not the total in the system + QVarLengthArray cpuset(1); + int size = 1; + if (Q_UNLIKELY(sched_getaffinity(0, sizeof(cpu_set_t), cpuset.data()) < 0)) { + for (size = 2; size <= 4; size *= 2) { + cpuset.resize(size); + if (sched_getaffinity(0, sizeof(cpu_set_t) * size, cpuset.data()) == 0) + break; + } + if (size > 4) + return 1; + } + cores = CPU_COUNT_S(sizeof(cpu_set_t) * size, cpuset.data()); #elif defined(Q_OS_BSD4) - // FreeBSD, OpenBSD, NetBSD, BSD/OS, OS X, iOS + // OpenBSD, NetBSD, BSD/OS, Darwin (macOS, iOS, etc.) size_t len = sizeof(cores); int mib[2]; mib[0] = CTL_HW; @@ -494,7 +519,7 @@ int QThread::idealThreadCount() noexcept #elif defined(Q_OS_WASM) cores = QThreadPrivate::idealThreadCount; #else - // the rest: Linux, Solaris, AIX, Tru64 + // the rest: Solaris, AIX, Tru64 cores = (int)sysconf(_SC_NPROCESSORS_ONLN); if (cores == -1) return 1;