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) && !defined(Q_OS_VXWORKS)
295 terminate_on_exception([&] {
303 if (thr->d_func()->priority & ThreadPriorityResetFlag) {
304 thr->d_func()->setPriority(
QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
308 Q_ASSERT(pthread_equal(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()),
310 set_thread_data(
data);
313 data->quitNow = thr->d_func()->exited;
316 data->ensureEventDispatcher();
317 data->eventDispatcher.loadRelaxed()->startingUp();
319#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
324 if (
Q_LIKELY(thr->d_func()->objectName.isEmpty()))
325 setCurrentThreadName(thr->metaObject()->className());
327 setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit());
331 emit thr->started(QThread::QPrivateSignal());
332#ifdef PTHREAD_CANCEL_DISABLE
333 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,
nullptr);
334 pthread_testcancel();
343void QThreadPrivate::finish(
void *
arg)
345 terminate_on_exception([&] {
351 d->isInFinish =
true;
353 void *
data = &
d->data->tls;
355 emit thr->finished(QThread::QPrivateSignal());
356 qCDebug(lcDeleteLater) <<
"Sending deferred delete events as part of finishing thread" << thr;
358 QThreadStorageData::finish((
void **)
data);
362 if (eventDispatcher) {
363 d->data->eventDispatcher =
nullptr;
366 delete eventDispatcher;
372 d->interruptionRequested.store(
false, std::memory_order_relaxed);
374 d->isInFinish =
false;
375 d->data->threadId.storeRelaxed(
nullptr);
377 d->thread_done.wakeAll();
400Qt::HANDLE QThread::currentThreadIdImpl() noexcept
402 return to_HANDLE(pthread_self());
405#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
407# define _SC_NPROCESSORS_ONLN 84
411int QThreadPrivate::idealThreadCount = 1;
418#if defined(Q_OS_HPUX)
420 struct pst_dynamic psd;
421 if (pstat_getdynamic(&psd,
sizeof(psd), 1, 0) == -1) {
422 perror(
"pstat_getdynamic");
424 cores = (int)psd.psd_proc_cnt;
426#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
427# if defined(Q_OS_FREEBSD) && !defined(CPU_COUNT_S)
428# define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp))
430 using cpu_set_t = cpuset_t;
431 auto sched_getaffinity = [](pid_t,
size_t cpusetsize, cpu_set_t *
mask) {
432 return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, cpusetsize,
mask);
437 QVarLengthArray<cpu_set_t, 1> cpuset(1);
439 if (
Q_UNLIKELY(sched_getaffinity(0,
sizeof(cpu_set_t), cpuset.data()) < 0)) {
442 if (sched_getaffinity(0,
sizeof(cpu_set_t) *
size, cpuset.data()) == 0)
448 cores = CPU_COUNT_S(
sizeof(cpu_set_t) *
size, cpuset.data());
449#elif defined(Q_OS_BSD4)
451 size_t len =
sizeof(cores);
455 if (sysctl(mib, 2, &cores, &
len, NULL, 0) != 0) {
458#elif defined(Q_OS_INTEGRITY)
459#if (__INTEGRITY_MAJOR_VERSION >= 10)
461 Value processorCount;
462 if (GetProcessorCount(CurrentTask(), &processorCount) == 0)
463 cores = processorCount;
468#elif defined(Q_OS_VXWORKS)
470# if defined(QT_VXWORKS_HAS_CPUSET)
471 cpuset_t cpus = vxCpuEnabledGet();
475 for (
int i = 0;
i < 128 && !CPUSET_ISZERO(cpus); ++
i) {
476 if (CPUSET_ISSET(cpus,
i)) {
485#elif defined(Q_OS_WASM)
486 cores = QThreadPrivate::idealThreadCount;
489 cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
519 sleep(std::chrono::seconds{secs});
524 sleep(std::chrono::milliseconds{msecs});
529 sleep(std::chrono::microseconds{usecs});
539#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
541static bool calculateUnixPriority(
int priority,
int *sched_policy,
int *sched_priority)
550 int priority_norm = 10;
553 struct _sched_info
info;
554 if (SchedInfo_r(0, *sched_policy, &
info) != EOK)
558 *sched_priority =
info.priority_min;
562 if (priority_norm <
info.priority_min)
563 priority_norm =
info.priority_min;
564 if (priority_norm >
info.priority_priv)
565 priority_norm =
info.priority_priv;
568 int from_min, from_max;
571 to_min =
info.priority_min;
572 to_max = priority_norm;
576 to_min = priority_norm;
577 to_max =
info.priority_priv;
582 prio = ((priority - from_min) * (to_max - to_min)) / (from_max - from_min) + to_min;
583 prio =
qBound(to_min, prio, to_max);
585 *sched_priority = prio;
592static bool calculateUnixPriority(
int priority,
int *sched_policy,
int *sched_priority)
596 *sched_policy = SCHED_IDLE;
608#if defined(Q_OS_VXWORKS) && defined(VXWORKS_DKM)
610 prio_min = SCHED_FIFO_LOW_PRI;
611 prio_max = SCHED_FIFO_HIGH_PRI;
613 if ((*sched_policy == SCHED_RR) || (*sched_policy == SCHED_FIFO))
616 prio_min = sched_get_priority_min(*sched_policy);
617 prio_max = sched_get_priority_max(*sched_policy);
620 if (prio_min == -1 || prio_max == -1)
625 prio = ((priority - lowestPriority) * (prio_max - prio_min) / highestPriority) + prio_min;
626 prio =
qMax(prio_min,
qMin(prio_max, prio));
628 *sched_priority = prio;
640 d->thread_done.wait(locker.mutex());
649 d->interruptionRequested.store(
false, std::memory_order_relaxed);
652 pthread_attr_init(&attr);
653 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
657#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
661 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
668 if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
671 qWarning(
"QThread::start: Cannot determine default scheduler policy");
676 if (!calculateUnixPriority(
priority, &sched_policy, &prio)) {
679 qWarning(
"QThread::start: Cannot determine scheduler priority range");
684 sp.sched_priority = prio;
686 if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
687 || pthread_attr_setschedpolicy(&attr, sched_policy) != 0
688 || pthread_attr_setschedparam(&attr, &
sp) != 0) {
691 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
700 if (
d->stackSize > 0) {
701#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
702 int code = pthread_attr_setstacksize(&attr,
d->stackSize);
708 qErrnoWarning(code,
"QThread::start: Thread stack size error");
725 d->objectName =
d->extraData ?
d->extraData->objectName.valueBypassingBindings()
730 int code = pthread_create(&threadId, &attr, QThreadPrivate::start,
this);
734#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
735 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
737 code = pthread_create(&threadId, &attr, QThreadPrivate::start,
this);
739 d->data->threadId.storeRelaxed(to_HANDLE(threadId));
741 pthread_attr_destroy(&attr);
744 qErrnoWarning(code,
"QThread::start: Thread creation error");
748 d->data->threadId.storeRelaxed(
nullptr);
754#if !defined(Q_OS_ANDROID)
758 if (!
d->data->threadId.loadRelaxed())
761 int code = pthread_cancel(from_HANDLE<pthread_t>(
d->data->threadId.loadRelaxed()));
763 qErrnoWarning(code,
"QThread::start: Thread termination error");
773 if (from_HANDLE<pthread_t>(
d->data->threadId.loadRelaxed()) == pthread_self()) {
774 qWarning(
"QThread::wait: Thread tried to wait on itself");
778 if (
d->finished || !
d->running)
782 if (!
d->thread_done.wait(locker.mutex(),
deadline))
785 Q_ASSERT(
d->data->threadId.loadRelaxed() ==
nullptr);
793 Q_ASSERT_X(thr !=
nullptr,
"QThread::setTerminationEnabled()",
794 "Current thread was not started with QThread.");
797#if defined(Q_OS_ANDROID)
800 pthread_setcancelstate(
enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE,
nullptr);
802 pthread_testcancel();
809 priority = threadPriority;
813#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
817 if (pthread_getschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), &sched_policy, &
param) != 0) {
820 qWarning(
"QThread::setPriority: Cannot get scheduler parameters");
825 if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
828 qWarning(
"QThread::setPriority: Cannot determine scheduler priority range");
832 param.sched_priority = prio;
833 int status = pthread_setschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), sched_policy, &
param);
837 if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
839 pthread_getschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), &sched_policy, &
param);
840 param.sched_priority = sched_get_priority_min(sched_policy);
841 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()