7#include "qplatformdefs.h"
9#include <private/qcoreapplication_p.h>
10#include <private/qcore_unix_p.h>
11#include <private/qtools_p.h>
13#if defined(Q_OS_DARWIN)
14# include <private/qeventdispatcher_cf_p.h>
15#elif defined(Q_OS_WASM)
16# include <private/qeventdispatcher_wasm_p.h>
18# if !defined(QT_NO_GLIB)
23#if !defined(Q_OS_WASM)
24# include <private/qeventdispatcher_unix_p.h>
40#if defined(Q_OS_FREEBSD)
41# include <sys/cpuset.h>
42#elif defined(Q_OS_BSD4)
43# include <sys/sysctl.h>
46# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6))
49# define QT_VXWORKS_HAS_CPUSET
57#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
61#if defined(Q_OS_LINUX) && !defined(SCHED_IDLE)
66#if defined(Q_OS_DARWIN) || !defined(Q_OS_ANDROID) && !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0)
67#define QT_HAS_THREAD_PRIORITY_SCHEDULING
71#include <sys/neutrino.h>
80static_assert(
sizeof(pthread_t) <=
sizeof(
Qt::HANDLE));
82enum { ThreadPriorityResetFlag = 0x80000000 };
85Q_CONSTINIT
static thread_local QThreadData *currentThreadData =
nullptr;
87Q_CONSTINIT
static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
88Q_CONSTINIT
static pthread_key_t current_thread_data_key;
90static void destroy_current_thread_data(
void *
p)
96 currentThreadData =
data;
97 if (
data->isAdopted) {
102 thread_p->finish(thread);
108 currentThreadData =
nullptr;
111static void create_current_thread_data_key()
113 pthread_key_create(¤t_thread_data_key, destroy_current_thread_data);
116static void destroy_current_thread_data_key()
118 pthread_once(¤t_thread_data_once, create_current_thread_data_key);
119 pthread_key_delete(current_thread_data_key);
124 pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
125 current_thread_data_once = pthread_once_init;
127Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
133 return currentThreadData;
138 currentThreadData =
data;
139 pthread_once(¤t_thread_data_once, create_current_thread_data_key);
140 pthread_setspecific(current_thread_data_key,
data);
143static void clear_thread_data()
145 set_thread_data(
nullptr);
149static typename std::enable_if<std::is_integral_v<T>,
Qt::HANDLE>
::type to_HANDLE(T
id)
155static typename std::enable_if<std::is_integral_v<T>, T>
::type from_HANDLE(
Qt::HANDLE id)
157 return static_cast<T
>(
reinterpret_cast<intptr_t>(
id));
161static typename std::enable_if<std::is_pointer_v<T>,
Qt::HANDLE>
::type to_HANDLE(T
id)
167static typename std::enable_if<std::is_pointer_v<T>, T>
::type from_HANDLE(
Qt::HANDLE id)
169 return static_cast<T
>(
id);
180 if (!
data && createIfNecessary) {
183 set_thread_data(
data);
192 data->isAdopted =
true;
193 data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
212typedef void *(*QtThreadCallback)(
void *);
220#if defined(Q_OS_DARWIN)
227#elif defined(Q_OS_WASM)
229#elif !defined(QT_NO_GLIB)
244#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
245static void setCurrentThreadName(
const char *
name)
247# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
248 prctl(PR_SET_NAME, (
unsigned long)
name, 0, 0, 0);
249# elif defined(Q_OS_DARWIN)
250 pthread_setname_np(
name);
251# elif defined(Q_OS_QNX)
252 pthread_setname_np(pthread_self(),
name);
259void terminate_on_exception(T &&
t)
261#ifndef QT_NO_EXCEPTIONS
264 std::forward<T>(
t)();
265#ifndef QT_NO_EXCEPTIONS
270 }
catch (abi::__forced_unwind &) {
280void *QThreadPrivate::start(
void *
arg)
282#ifdef PTHREAD_CANCEL_DISABLE
283 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
nullptr);
285#if !defined(Q_OS_QNX)
291 terminate_on_exception([&] {
299 if (thr->d_func()->priority & ThreadPriorityResetFlag) {
300 thr->d_func()->setPriority(
QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
304 Q_ASSERT(pthread_equal(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()),
306 set_thread_data(
data);
309 data->quitNow = thr->d_func()->exited;
312 data->ensureEventDispatcher();
313 data->eventDispatcher.loadRelaxed()->startingUp();
315#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
320 if (
Q_LIKELY(thr->d_func()->objectName.isEmpty()))
321 setCurrentThreadName(thr->metaObject()->className());
323 setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit());
327 emit thr->started(QThread::QPrivateSignal());
328#ifdef PTHREAD_CANCEL_DISABLE
329 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,
nullptr);
330 pthread_testcancel();
339void QThreadPrivate::finish(
void *
arg)
341 terminate_on_exception([&] {
347 d->isInFinish =
true;
349 void *
data = &
d->data->tls;
351 emit thr->finished(QThread::QPrivateSignal());
352 qCDebug(lcDeleteLater) <<
"Sending deferred delete events as part of finishing thread" << thr;
354 QThreadStorageData::finish((
void **)
data);
358 if (eventDispatcher) {
359 d->data->eventDispatcher =
nullptr;
362 delete eventDispatcher;
368 d->interruptionRequested.store(
false, std::memory_order_relaxed);
370 d->isInFinish =
false;
371 d->data->threadId.storeRelaxed(
nullptr);
373 d->thread_done.wakeAll();
396Qt::HANDLE QThread::currentThreadIdImpl() noexcept
398 return to_HANDLE(pthread_self());
401#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
403# define _SC_NPROCESSORS_ONLN 84
407int QThreadPrivate::idealThreadCount = 1;
414#if defined(Q_OS_HPUX)
416 struct pst_dynamic psd;
417 if (pstat_getdynamic(&psd,
sizeof(psd), 1, 0) == -1) {
418 perror(
"pstat_getdynamic");
420 cores = (int)psd.psd_proc_cnt;
422#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
423# if defined(Q_OS_FREEBSD) && !defined(CPU_COUNT_S)
424# define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp))
426 using cpu_set_t = cpuset_t;
427 auto sched_getaffinity = [](pid_t,
size_t cpusetsize, cpu_set_t *
mask) {
428 return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, cpusetsize,
mask);
433 QVarLengthArray<cpu_set_t, 1> cpuset(1);
435 if (
Q_UNLIKELY(sched_getaffinity(0,
sizeof(cpu_set_t), cpuset.data()) < 0)) {
438 if (sched_getaffinity(0,
sizeof(cpu_set_t) *
size, cpuset.data()) == 0)
444 cores = CPU_COUNT_S(
sizeof(cpu_set_t) *
size, cpuset.data());
445#elif defined(Q_OS_BSD4)
447 size_t len =
sizeof(cores);
451 if (sysctl(mib, 2, &cores, &
len, NULL, 0) != 0) {
454#elif defined(Q_OS_INTEGRITY)
455#if (__INTEGRITY_MAJOR_VERSION >= 10)
457 Value processorCount;
458 if (GetProcessorCount(CurrentTask(), &processorCount) == 0)
459 cores = processorCount;
464#elif defined(Q_OS_VXWORKS)
466# if defined(QT_VXWORKS_HAS_CPUSET)
467 cpuset_t cpus = vxCpuEnabledGet();
471 for (
int i = 0;
i < 128 && !CPUSET_ISZERO(cpus); ++
i) {
472 if (CPUSET_ISSET(cpus,
i)) {
481#elif defined(Q_OS_WASM)
482 cores = QThreadPrivate::idealThreadCount;
485 cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
515 sleep(std::chrono::seconds{secs});
520 sleep(std::chrono::milliseconds{msecs});
525 sleep(std::chrono::microseconds{usecs});
535#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
537static bool calculateUnixPriority(
int priority,
int *sched_policy,
int *sched_priority)
546 int priority_norm = 10;
549 struct _sched_info
info;
550 if (SchedInfo_r(0, *sched_policy, &
info) != EOK)
554 *sched_priority =
info.priority_min;
558 if (priority_norm <
info.priority_min)
559 priority_norm =
info.priority_min;
560 if (priority_norm >
info.priority_priv)
561 priority_norm =
info.priority_priv;
564 int from_min, from_max;
567 to_min =
info.priority_min;
568 to_max = priority_norm;
572 to_min = priority_norm;
573 to_max =
info.priority_priv;
578 prio = ((priority - from_min) * (to_max - to_min)) / (from_max - from_min) + to_min;
579 prio =
qBound(to_min, prio, to_max);
581 *sched_priority = prio;
588static bool calculateUnixPriority(
int priority,
int *sched_policy,
int *sched_priority)
592 *sched_policy = SCHED_IDLE;
604#if defined(Q_OS_VXWORKS) && defined(VXWORKS_DKM)
606 prio_min = SCHED_FIFO_LOW_PRI;
607 prio_max = SCHED_FIFO_HIGH_PRI;
609 if ((*sched_policy == SCHED_RR) || (*sched_policy == SCHED_FIFO))
612 prio_min = sched_get_priority_min(*sched_policy);
613 prio_max = sched_get_priority_max(*sched_policy);
616 if (prio_min == -1 || prio_max == -1)
621 prio = ((priority - lowestPriority) * (prio_max - prio_min) / highestPriority) + prio_min;
622 prio =
qMax(prio_min,
qMin(prio_max, prio));
624 *sched_priority = prio;
636 d->thread_done.wait(locker.mutex());
645 d->interruptionRequested.store(
false, std::memory_order_relaxed);
648 pthread_attr_init(&attr);
649 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
653#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
657 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
664 if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
667 qWarning(
"QThread::start: Cannot determine default scheduler policy");
672 if (!calculateUnixPriority(
priority, &sched_policy, &prio)) {
675 qWarning(
"QThread::start: Cannot determine scheduler priority range");
680 sp.sched_priority = prio;
682 if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
683 || pthread_attr_setschedpolicy(&attr, sched_policy) != 0
684 || pthread_attr_setschedparam(&attr, &
sp) != 0) {
687 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
696 if (
d->stackSize > 0) {
697#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
698 int code = pthread_attr_setstacksize(&attr,
d->stackSize);
704 qErrnoWarning(code,
"QThread::start: Thread stack size error");
721 d->objectName =
d->extraData ?
d->extraData->objectName.valueBypassingBindings()
726 int code = pthread_create(&threadId, &attr, QThreadPrivate::start,
this);
730#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
731 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
733 code = pthread_create(&threadId, &attr, QThreadPrivate::start,
this);
735 d->data->threadId.storeRelaxed(to_HANDLE(threadId));
737 pthread_attr_destroy(&attr);
740 qErrnoWarning(code,
"QThread::start: Thread creation error");
744 d->data->threadId.storeRelaxed(
nullptr);
750#if !defined(Q_OS_ANDROID)
754 if (!
d->data->threadId.loadRelaxed())
757 int code = pthread_cancel(from_HANDLE<pthread_t>(
d->data->threadId.loadRelaxed()));
759 qErrnoWarning(code,
"QThread::start: Thread termination error");
769 if (from_HANDLE<pthread_t>(
d->data->threadId.loadRelaxed()) == pthread_self()) {
770 qWarning(
"QThread::wait: Thread tried to wait on itself");
774 if (
d->finished || !
d->running)
778 if (!
d->thread_done.wait(locker.mutex(),
deadline))
781 Q_ASSERT(
d->data->threadId.loadRelaxed() ==
nullptr);
789 Q_ASSERT_X(thr !=
nullptr,
"QThread::setTerminationEnabled()",
790 "Current thread was not started with QThread.");
793#if defined(Q_OS_ANDROID)
796 pthread_setcancelstate(
enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE,
nullptr);
798 pthread_testcancel();
805 priority = threadPriority;
809#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
813 if (pthread_getschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), &sched_policy, &
param) != 0) {
816 qWarning(
"QThread::setPriority: Cannot get scheduler parameters");
821 if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
824 qWarning(
"QThread::setPriority: Cannot determine scheduler priority range");
828 param.sched_priority = prio;
829 int status = pthread_setschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), sched_policy, &
param);
833 if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
835 pthread_getschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), &sched_policy, &
param);
836 param.sched_priority = sched_get_priority_min(sched_policy);
837 pthread_setschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), sched_policy, &
param);
virtual void closingDown()
static QBasicAtomicPointer< void > theMainThreadId
static QThread * mainThread()
static QBasicAtomicPointer< QThread > theMainThread
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
static bool versionSupported()
static QObjectPrivate * get(QObject *o)
QString objectName
the name of this object
QThread * thread() const
Returns the thread in which the object lives.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
QThreadData(int initialRefCount=1)
static void clearCurrentThreadData()
static QThreadData * get2(QThread *thread)
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
void start(Priority=InheritPriority)
static int idealThreadCount() noexcept
static QThread * currentThread()
static void setTerminationEnabled(bool enabled=true)
static void yieldCurrentThread()
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
static void usleep(unsigned long)
Priority priority() const
static void msleep(unsigned long)
static void sleep(unsigned long)
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
#define QT_EINTR_LOOP(var, cmd)
timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QT_BEGIN_NAMESPACE Q_NORETURN void qTerminate() noexcept
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum const GLint * param
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
#define Q_ASSERT_X(cond, x, msg)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
static void qt_nanosleep(timespec amount)
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
const char className[16]
[1]
QDeadlineTimer deadline(30s)
obj metaObject() -> className()