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)
19# include "../kernel/qeventdispatcher_glib_p.h"
23#include <private/qeventdispatcher_unix_p.h>
38#if defined(Q_OS_FREEBSD)
39# include <sys/cpuset.h>
40#elif defined(Q_OS_BSD4)
41# include <sys/sysctl.h>
44# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6))
47# define QT_VXWORKS_HAS_CPUSET
55#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
59#if defined(Q_OS_LINUX) && !defined(SCHED_IDLE)
64#if defined(Q_OS_DARWIN) || !defined(Q_OS_ANDROID) && !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0)
65#define QT_HAS_THREAD_PRIORITY_SCHEDULING
69#include <sys/neutrino.h>
78static_assert(
sizeof(pthread_t) <=
sizeof(
Qt::HANDLE));
80enum { ThreadPriorityResetFlag = 0x80000000 };
83Q_CONSTINIT
static thread_local QThreadData *currentThreadData =
nullptr;
85Q_CONSTINIT
static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
86Q_CONSTINIT
static pthread_key_t current_thread_data_key;
88static void destroy_current_thread_data(
void *
p)
94 currentThreadData =
data;
95 if (
data->isAdopted) {
100 thread_p->finish(thread);
106 currentThreadData =
nullptr;
109static void create_current_thread_data_key()
111 pthread_key_create(¤t_thread_data_key, destroy_current_thread_data);
114static void destroy_current_thread_data_key()
116 pthread_once(¤t_thread_data_once, create_current_thread_data_key);
117 pthread_key_delete(current_thread_data_key);
122 pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
123 current_thread_data_once = pthread_once_init;
125Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
131 return currentThreadData;
136 currentThreadData =
data;
137 pthread_once(¤t_thread_data_once, create_current_thread_data_key);
138 pthread_setspecific(current_thread_data_key,
data);
141static void clear_thread_data()
143 set_thread_data(
nullptr);
147static typename std::enable_if<std::is_integral_v<T>,
Qt::HANDLE>
::type to_HANDLE(T
id)
153static typename std::enable_if<std::is_integral_v<T>, T>
::type from_HANDLE(
Qt::HANDLE id)
155 return static_cast<T
>(
reinterpret_cast<intptr_t>(
id));
159static typename std::enable_if<std::is_pointer_v<T>,
Qt::HANDLE>
::type to_HANDLE(T
id)
165static typename std::enable_if<std::is_pointer_v<T>, T>
::type from_HANDLE(
Qt::HANDLE id)
167 return static_cast<T
>(
id);
178 if (!
data && createIfNecessary) {
181 set_thread_data(
data);
190 data->isAdopted =
true;
191 data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
208typedef void *(*QtThreadCallback)(
void *);
216#if defined(Q_OS_DARWIN)
223#elif defined(Q_OS_WASM)
225#elif !defined(QT_NO_GLIB)
240#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
241static void setCurrentThreadName(
const char *
name)
243# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
244 prctl(PR_SET_NAME, (
unsigned long)
name, 0, 0, 0);
245# elif defined(Q_OS_DARWIN)
246 pthread_setname_np(
name);
247# elif defined(Q_OS_QNX)
248 pthread_setname_np(pthread_self(),
name);
255void terminate_on_exception(T &&
t)
257#ifndef QT_NO_EXCEPTIONS
260 std::forward<T>(
t)();
261#ifndef QT_NO_EXCEPTIONS
266 }
catch (abi::__forced_unwind &) {
276void *QThreadPrivate::start(
void *
arg)
278#if !defined(Q_OS_ANDROID)
279 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,
nullptr);
281 pthread_cleanup_push(QThreadPrivate::finish,
arg);
283 terminate_on_exception([&] {
291 if (thr->d_func()->
priority & ThreadPriorityResetFlag) {
296 Q_ASSERT(pthread_equal(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()),
298 set_thread_data(
data);
301 data->quitNow = thr->d_func()->exited;
304 data->ensureEventDispatcher();
307#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
313 setCurrentThreadName(thr->metaObject()->className());
315 setCurrentThreadName(std::exchange(thr->d_func()->
objectName, {}).toLocal8Bit());
320#if !defined(Q_OS_ANDROID)
321 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,
nullptr);
322 pthread_testcancel();
330 pthread_cleanup_pop(1);
335void QThreadPrivate::finish(
void *
arg)
337 terminate_on_exception([&] {
343 d->isInFinish =
true;
345 void *
data = &
d->data->tls;
349 QThreadStorageData::finish((
void **)
data);
353 if (eventDispatcher) {
354 d->data->eventDispatcher =
nullptr;
357 delete eventDispatcher;
363 d->interruptionRequested =
false;
365 d->isInFinish =
false;
366 d->data->threadId.storeRelaxed(
nullptr);
368 d->thread_done.wakeAll();
391Qt::HANDLE QThread::currentThreadIdImpl() noexcept
393 return to_HANDLE(pthread_self());
396#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
398# define _SC_NPROCESSORS_ONLN 84
402int QThreadPrivate::idealThreadCount = 1;
409#if defined(Q_OS_HPUX)
411 struct pst_dynamic psd;
412 if (pstat_getdynamic(&psd,
sizeof(psd), 1, 0) == -1) {
413 perror(
"pstat_getdynamic");
415 cores = (int)psd.psd_proc_cnt;
417#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
418# if defined(Q_OS_FREEBSD) && !defined(CPU_COUNT_S)
419# define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp))
421 using cpu_set_t = cpuset_t;
422 auto sched_getaffinity = [](pid_t,
size_t cpusetsize, cpu_set_t *
mask) {
423 return cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, cpusetsize,
mask);
430 if (
Q_UNLIKELY(sched_getaffinity(0,
sizeof(cpu_set_t), cpuset.data()) < 0)) {
433 if (sched_getaffinity(0,
sizeof(cpu_set_t) *
size, cpuset.data()) == 0)
439 cores = CPU_COUNT_S(
sizeof(cpu_set_t) *
size, cpuset.data());
440#elif defined(Q_OS_BSD4)
442 size_t len =
sizeof(cores);
446 if (sysctl(mib, 2, &cores, &
len, NULL, 0) != 0) {
449#elif defined(Q_OS_INTEGRITY)
450#if (__INTEGRITY_MAJOR_VERSION >= 10)
452 Value processorCount;
453 if (GetProcessorCount(CurrentTask(), &processorCount) == 0)
454 cores = processorCount;
459#elif defined(Q_OS_VXWORKS)
461# if defined(QT_VXWORKS_HAS_CPUSET)
462 cpuset_t cpus = vxCpuEnabledGet();
466 for (
int i = 0;
i < 128 && !CPUSET_ISZERO(cpus); ++
i) {
467 if (CPUSET_ISSET(cpus,
i)) {
476#elif defined(Q_OS_WASM)
477 cores = QThreadPrivate::idealThreadCount;
480 cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
510 sleep(std::chrono::seconds{secs});
515 sleep(std::chrono::milliseconds{msecs});
520 sleep(std::chrono::microseconds{usecs});
530#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
532static bool calculateUnixPriority(
int priority,
int *sched_policy,
int *sched_priority)
541 int priority_norm = 10;
544 struct _sched_info
info;
545 if (SchedInfo_r(0, *sched_policy, &
info) != EOK)
549 *sched_priority =
info.priority_min;
553 if (priority_norm <
info.priority_min)
554 priority_norm =
info.priority_min;
555 if (priority_norm >
info.priority_priv)
556 priority_norm =
info.priority_priv;
559 int from_min, from_max;
562 to_min =
info.priority_min;
563 to_max = priority_norm;
567 to_min = priority_norm;
568 to_max =
info.priority_priv;
573 prio = ((priority - from_min) * (to_max - to_min)) / (from_max - from_min) + to_min;
574 prio =
qBound(to_min, prio, to_max);
576 *sched_priority = prio;
583static bool calculateUnixPriority(
int priority,
int *sched_policy,
int *sched_priority)
587 *sched_policy = SCHED_IDLE;
599#if defined(Q_OS_VXWORKS) && defined(VXWORKS_DKM)
601 prio_min = SCHED_FIFO_LOW_PRI;
602 prio_max = SCHED_FIFO_HIGH_PRI;
604 if ((*sched_policy == SCHED_RR) || (*sched_policy == SCHED_FIFO))
607 prio_min = sched_get_priority_min(*sched_policy);
608 prio_max = sched_get_priority_max(*sched_policy);
611 if (prio_min == -1 || prio_max == -1)
616 prio = ((priority - lowestPriority) * (prio_max - prio_min) / highestPriority) + prio_min;
617 prio =
qMax(prio_min,
qMin(prio_max, prio));
619 *sched_priority = prio;
631 d->thread_done.wait(locker.mutex());
640 d->interruptionRequested =
false;
643 pthread_attr_init(&attr);
644 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
648#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
652 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
659 if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
662 qWarning(
"QThread::start: Cannot determine default scheduler policy");
667 if (!calculateUnixPriority(
priority, &sched_policy, &prio)) {
670 qWarning(
"QThread::start: Cannot determine scheduler priority range");
675 sp.sched_priority = prio;
677 if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0
678 || pthread_attr_setschedpolicy(&attr, sched_policy) != 0
679 || pthread_attr_setschedparam(&attr, &
sp) != 0) {
682 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
691 if (
d->stackSize > 0) {
692#if defined(_POSIX_THREAD_ATTR_STACKSIZE) && (_POSIX_THREAD_ATTR_STACKSIZE-0 > 0)
693 int code = pthread_attr_setstacksize(&attr,
d->stackSize);
699 qErrnoWarning(code,
"QThread::start: Thread stack size error");
716 d->objectName =
d->extraData ?
d->extraData->objectName.valueBypassingBindings()
721 int code = pthread_create(&threadId, &attr, QThreadPrivate::start,
this);
725#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
726 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
728 code = pthread_create(&threadId, &attr, QThreadPrivate::start,
this);
730 d->data->threadId.storeRelaxed(to_HANDLE(threadId));
732 pthread_attr_destroy(&attr);
735 qErrnoWarning(code,
"QThread::start: Thread creation error");
739 d->data->threadId.storeRelaxed(
nullptr);
745#if !defined(Q_OS_ANDROID)
749 if (!
d->data->threadId.loadRelaxed())
752 int code = pthread_cancel(from_HANDLE<pthread_t>(
d->data->threadId.loadRelaxed()));
754 qErrnoWarning(code,
"QThread::start: Thread termination error");
764 if (from_HANDLE<pthread_t>(
d->data->threadId.loadRelaxed()) == pthread_self()) {
765 qWarning(
"QThread::wait: Thread tried to wait on itself");
769 if (
d->finished || !
d->running)
773 if (!
d->thread_done.wait(locker.mutex(),
deadline))
776 Q_ASSERT(
d->data->threadId.loadRelaxed() ==
nullptr);
784 Q_ASSERT_X(thr !=
nullptr,
"QThread::setTerminationEnabled()",
785 "Current thread was not started with QThread.");
788#if defined(Q_OS_ANDROID)
791 pthread_setcancelstate(
enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE,
nullptr);
793 pthread_testcancel();
800 priority = threadPriority;
804#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
808 if (pthread_getschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), &sched_policy, &
param) != 0) {
811 qWarning(
"QThread::setPriority: Cannot get scheduler parameters");
816 if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
819 qWarning(
"QThread::setPriority: Cannot determine scheduler priority range");
823 param.sched_priority = prio;
824 int status = pthread_setschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), sched_policy, &
param);
828 if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
830 pthread_getschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), &sched_policy, &
param);
831 param.sched_priority = sched_get_priority_min(sched_policy);
832 pthread_setschedparam(from_HANDLE<pthread_t>(
data->threadId.loadRelaxed()), sched_policy, &
param);
virtual void startingUp()
virtual void closingDown()
void storeRelease(Type newValue) noexcept
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
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
static void clearCurrentThreadData()
static QThreadData * get2(QThread *thread)
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
void start(Priority=InheritPriority)
QAbstractEventDispatcher * eventDispatcher() const
static int idealThreadCount() noexcept
static void setTerminationEnabled(bool enabled=true)
static QThread * currentThread()
static void yieldCurrentThread()
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
static void usleep(unsigned long)
Priority priority() const
void finished(QPrivateSignal)
void setPriority(Priority priority)
static void msleep(unsigned long)
static void sleep(unsigned long)
void started(QPrivateSignal)
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept
#define EINTR_LOOP(var, cmd)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QT_BEGIN_NAMESPACE Q_NORETURN void qTerminate() noexcept
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]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum const GLint * param
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
#define Q_ASSERT_X(cond, x, msg)
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)
constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
const char className[16]
[1]
QFileInfo info(fileName)
[8]
QDeadlineTimer deadline(30s)
obj metaObject() -> className()