Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qthread_unix.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qthread.h"
6
7#include "qplatformdefs.h"
8
9#include <private/qcoreapplication_p.h>
10#include <private/qcore_unix_p.h>
11#include <private/qtools_p.h>
12
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>
17#else
18# if !defined(QT_NO_GLIB)
20# endif
21#endif
22
23#if !defined(Q_OS_WASM)
24# include <private/qeventdispatcher_unix_p.h>
25#endif
26
27#include "qthreadstorage.h"
28
29#include "qthread_p.h"
30
31#include "qdebug.h"
32
33#ifdef __GLIBCXX__
34#include <cxxabi.h>
35#endif
36
37#include <sched.h>
38#include <errno.h>
39
40#if defined(Q_OS_FREEBSD)
41# include <sys/cpuset.h>
42#elif defined(Q_OS_BSD4)
43# include <sys/sysctl.h>
44#endif
45#ifdef Q_OS_VXWORKS
46# if (_WRS_VXWORKS_MAJOR > 6) || ((_WRS_VXWORKS_MAJOR == 6) && (_WRS_VXWORKS_MINOR >= 6))
47# include <vxCpuLib.h>
48# include <cpuset.h>
49# define QT_VXWORKS_HAS_CPUSET
50# endif
51#endif
52
53#ifdef Q_OS_HPUX
54#include <sys/pstat.h>
55#endif
56
57#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
58#include <sys/prctl.h>
59#endif
60
61#if defined(Q_OS_LINUX) && !defined(SCHED_IDLE)
62// from linux/sched.h
63# define SCHED_IDLE 5
64#endif
65
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
68#endif
69
70#if defined(Q_OS_QNX)
71#include <sys/neutrino.h>
72#endif
73
75
76using namespace QtMiscUtils;
77
78#if QT_CONFIG(thread)
79
80static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
81
82enum { ThreadPriorityResetFlag = 0x80000000 };
83
84
85Q_CONSTINIT static thread_local QThreadData *currentThreadData = nullptr;
86
87Q_CONSTINIT static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
88Q_CONSTINIT static pthread_key_t current_thread_data_key;
89
90static void destroy_current_thread_data(void *p)
91{
92 QThreadData *data = static_cast<QThreadData *>(p);
93 // thread_local variables are set to zero before calling this destructor function,
94 // if they are internally using pthread-specific data management,
95 // so we need to set it back to the right value...
96 currentThreadData = data;
97 if (data->isAdopted) {
98 QThread *thread = data->thread.loadAcquire();
99 Q_ASSERT(thread);
100 QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
101 Q_ASSERT(!thread_p->finished);
102 thread_p->finish(thread);
103 }
104 data->deref();
105
106 // ... but we must reset it to zero before returning so we aren't
107 // leaving a dangling pointer.
108 currentThreadData = nullptr;
109}
110
111static void create_current_thread_data_key()
112{
113 pthread_key_create(&current_thread_data_key, destroy_current_thread_data);
114}
115
116static void destroy_current_thread_data_key()
117{
118 pthread_once(&current_thread_data_once, create_current_thread_data_key);
119 pthread_key_delete(current_thread_data_key);
120
121 // Reset current_thread_data_once in case we end up recreating
122 // the thread-data in the rare case of QObject construction
123 // after destroying the QThreadData.
124 pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
125 current_thread_data_once = pthread_once_init;
126}
127Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
128
129
130// Utility functions for getting, setting and clearing thread specific data.
131static QThreadData *get_thread_data()
132{
133 return currentThreadData;
134}
135
136static void set_thread_data(QThreadData *data)
137{
138 currentThreadData = data;
139 pthread_once(&current_thread_data_once, create_current_thread_data_key);
140 pthread_setspecific(current_thread_data_key, data);
141}
142
143static void clear_thread_data()
144{
145 set_thread_data(nullptr);
146}
147
148template <typename T>
149static typename std::enable_if<std::is_integral_v<T>, Qt::HANDLE>::type to_HANDLE(T id)
150{
151 return reinterpret_cast<Qt::HANDLE>(static_cast<intptr_t>(id));
152}
153
154template <typename T>
155static typename std::enable_if<std::is_integral_v<T>, T>::type from_HANDLE(Qt::HANDLE id)
156{
157 return static_cast<T>(reinterpret_cast<intptr_t>(id));
158}
159
160template <typename T>
161static typename std::enable_if<std::is_pointer_v<T>, Qt::HANDLE>::type to_HANDLE(T id)
162{
163 return id;
164}
165
166template <typename T>
167static typename std::enable_if<std::is_pointer_v<T>, T>::type from_HANDLE(Qt::HANDLE id)
168{
169 return static_cast<T>(id);
170}
171
173{
174 clear_thread_data();
175}
176
177QThreadData *QThreadData::current(bool createIfNecessary)
178{
179 QThreadData *data = get_thread_data();
180 if (!data && createIfNecessary) {
181 data = new QThreadData;
182 QT_TRY {
183 set_thread_data(data);
184 data->thread = new QAdoptedThread(data);
185 } QT_CATCH(...) {
186 clear_thread_data();
187 data->deref();
188 data = nullptr;
190 }
191 data->deref();
192 data->isAdopted = true;
193 data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
194 if (!QCoreApplicationPrivate::theMainThreadId.loadAcquire()) {
195 QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
196 QCoreApplicationPrivate::theMainThreadId.storeRelaxed(data->threadId.loadRelaxed());
197 }
198 }
199 return data;
200}
201
202
204{
205}
206
207/*
208 QThreadPrivate
209*/
210
211extern "C" {
212typedef void *(*QtThreadCallback)(void *);
213}
214
215#endif // QT_CONFIG(thread)
216
218{
219 Q_UNUSED(data);
220#if defined(Q_OS_DARWIN)
221 bool ok = false;
222 int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok);
223 if (ok && value > 0)
225 else
226 return new QEventDispatcherUNIX;
227#elif defined(Q_OS_WASM)
228 return new QEventDispatcherWasm();
229#elif !defined(QT_NO_GLIB)
230 const bool isQtMainThread = data->thread.loadAcquire() == QCoreApplicationPrivate::mainThread();
231 if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
232 && (isQtMainThread || qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB"))
234 return new QEventDispatcherGlib;
235 else
236 return new QEventDispatcherUNIX;
237#else
238 return new QEventDispatcherUNIX;
239#endif
240}
241
242#if QT_CONFIG(thread)
243
244#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
245static void setCurrentThreadName(const char *name)
246{
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);
253# endif
254}
255#endif
256
257namespace {
258template <typename T>
259void terminate_on_exception(T &&t)
260{
261#ifndef QT_NO_EXCEPTIONS
262 try {
263#endif
264 std::forward<T>(t)();
265#ifndef QT_NO_EXCEPTIONS
266#ifdef __GLIBCXX__
267 // POSIX thread cancellation under glibc is implemented by throwing an exception
268 // of this type. Do what libstdc++ is doing and handle it specially in order not to
269 // abort the application if user's code calls a cancellation function.
270 } catch (abi::__forced_unwind &) {
271 throw;
272#endif // __GLIBCXX__
273 } catch (...) {
274 qTerminate();
275 }
276#endif // QT_NO_EXCEPTIONS
277}
278} // unnamed namespace
279
280void *QThreadPrivate::start(void *arg)
281{
282#ifdef PTHREAD_CANCEL_DISABLE
283 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
284#endif
285#if !defined(Q_OS_QNX)
286 // On QNX, calling finish() from a thread_local destructor causes the C
287 // library to hang.
288 static thread_local
289#endif
290 auto cleanup = qScopeGuard([=] { finish(arg); });
291 terminate_on_exception([&] {
292 QThread *thr = reinterpret_cast<QThread *>(arg);
294
295 {
296 QMutexLocker locker(&thr->d_func()->mutex);
297
298 // do we need to reset the thread priority?
299 if (thr->d_func()->priority & ThreadPriorityResetFlag) {
300 thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
301 }
302
303 // threadId is set in QThread::start()
304 Q_ASSERT(pthread_equal(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()),
305 pthread_self()));
306 set_thread_data(data);
307
308 data->ref();
309 data->quitNow = thr->d_func()->exited;
310 }
311
312 data->ensureEventDispatcher();
313 data->eventDispatcher.loadRelaxed()->startingUp();
314
315#if (defined(Q_OS_LINUX) || defined(Q_OS_DARWIN) || defined(Q_OS_QNX))
316 {
317 // Sets the name of the current thread. We can only do this
318 // when the thread is starting, as we don't have a cross
319 // platform way of setting the name of an arbitrary thread.
320 if (Q_LIKELY(thr->d_func()->objectName.isEmpty()))
321 setCurrentThreadName(thr->metaObject()->className());
322 else
323 setCurrentThreadName(std::exchange(thr->d_func()->objectName, {}).toLocal8Bit());
324 }
325#endif
326
327 emit thr->started(QThread::QPrivateSignal());
328#ifdef PTHREAD_CANCEL_DISABLE
329 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr);
330 pthread_testcancel();
331#endif
332 thr->run();
333 });
334
335 // The qScopeGuard above call runs finish() below.
336 return nullptr;
337}
338
339void QThreadPrivate::finish(void *arg)
340{
341 terminate_on_exception([&] {
342 QThread *thr = reinterpret_cast<QThread *>(arg);
343 QThreadPrivate *d = thr->d_func();
344
345 QMutexLocker locker(&d->mutex);
346
347 d->isInFinish = true;
348 d->priority = QThread::InheritPriority;
349 void *data = &d->data->tls;
350 locker.unlock();
351 emit thr->finished(QThread::QPrivateSignal());
352 qCDebug(lcDeleteLater) << "Sending deferred delete events as part of finishing thread" << thr;
354 QThreadStorageData::finish((void **)data);
355 locker.relock();
356
357 QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.loadRelaxed();
358 if (eventDispatcher) {
359 d->data->eventDispatcher = nullptr;
360 locker.unlock();
361 eventDispatcher->closingDown();
362 delete eventDispatcher;
363 locker.relock();
364 }
365
366 d->running = false;
367 d->finished = true;
368 d->interruptionRequested.store(false, std::memory_order_relaxed);
369
370 d->isInFinish = false;
371 d->data->threadId.storeRelaxed(nullptr);
372
373 d->thread_done.wakeAll();
374 });
375}
376
377
378/**************************************************************************
379 ** QThread
380 *************************************************************************/
381
382/*
383 CI tests fails on ARM architectures if we try to use the assembler, so
384 stick to the pthread version there. The assembler would be
385
386 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babeihid.html
387 asm volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid));
388
389 and
390
391 // see glibc/sysdeps/aarch64/nptl/tls.h
392 asm volatile ("mrs %0, tpidr_el0" : "=r" (tid));
393
394 for 32 and 64bit versions, respectively.
395*/
396Qt::HANDLE QThread::currentThreadIdImpl() noexcept
397{
398 return to_HANDLE(pthread_self());
399}
400
401#if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN)
402// LSB doesn't define _SC_NPROCESSORS_ONLN.
403# define _SC_NPROCESSORS_ONLN 84
404#endif
405
406#ifdef Q_OS_WASM
407int QThreadPrivate::idealThreadCount = 1;
408#endif
409
410int QThread::idealThreadCount() noexcept
411{
412 int cores = 1;
413
414#if defined(Q_OS_HPUX)
415 // HP-UX
416 struct pst_dynamic psd;
417 if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) == -1) {
418 perror("pstat_getdynamic");
419 } else {
420 cores = (int)psd.psd_proc_cnt;
421 }
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))
425 // match the Linux API for simplicity
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);
429 };
430# endif
431
432 // get the number of threads we're assigned, not the total in the system
433 QVarLengthArray<cpu_set_t, 1> cpuset(1);
434 int size = 1;
435 if (Q_UNLIKELY(sched_getaffinity(0, sizeof(cpu_set_t), cpuset.data()) < 0)) {
436 for (size = 2; size <= 4; size *= 2) {
437 cpuset.resize(size);
438 if (sched_getaffinity(0, sizeof(cpu_set_t) * size, cpuset.data()) == 0)
439 break;
440 }
441 if (size > 4)
442 return 1;
443 }
444 cores = CPU_COUNT_S(sizeof(cpu_set_t) * size, cpuset.data());
445#elif defined(Q_OS_BSD4)
446 // OpenBSD, NetBSD, BSD/OS, Darwin (macOS, iOS, etc.)
447 size_t len = sizeof(cores);
448 int mib[2];
449 mib[0] = CTL_HW;
450 mib[1] = HW_NCPU;
451 if (sysctl(mib, 2, &cores, &len, NULL, 0) != 0) {
452 perror("sysctl");
453 }
454#elif defined(Q_OS_INTEGRITY)
455#if (__INTEGRITY_MAJOR_VERSION >= 10)
456 // Integrity V10+ does support multicore CPUs
457 Value processorCount;
458 if (GetProcessorCount(CurrentTask(), &processorCount) == 0)
459 cores = processorCount;
460 else
461#endif
462 // as of aug 2008 Integrity only supports one single core CPU
463 cores = 1;
464#elif defined(Q_OS_VXWORKS)
465 // VxWorks
466# if defined(QT_VXWORKS_HAS_CPUSET)
467 cpuset_t cpus = vxCpuEnabledGet();
468 cores = 0;
469
470 // 128 cores should be enough for everyone ;)
471 for (int i = 0; i < 128 && !CPUSET_ISZERO(cpus); ++i) {
472 if (CPUSET_ISSET(cpus, i)) {
473 CPUSET_CLR(cpus, i);
474 cores++;
475 }
476 }
477# else
478 // as of aug 2008 VxWorks < 6.6 only supports one single core CPU
479 cores = 1;
480# endif
481#elif defined(Q_OS_WASM)
482 cores = QThreadPrivate::idealThreadCount;
483#else
484 // the rest: Solaris, AIX, Tru64
485 cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
486 if (cores == -1)
487 return 1;
488#endif
489 return cores;
490}
491
493{
494 sched_yield();
495}
496
497#endif // QT_CONFIG(thread)
498
499static void qt_nanosleep(timespec amount)
500{
501 // We'd like to use clock_nanosleep.
502 //
503 // But clock_nanosleep is from POSIX.1-2001 and both are *not*
504 // affected by clock changes when using relative sleeps, even for
505 // CLOCK_REALTIME.
506 //
507 // nanosleep is POSIX.1-1993
508
509 int r;
510 QT_EINTR_LOOP(r, nanosleep(&amount, &amount));
511}
512
513void QThread::sleep(unsigned long secs)
514{
515 sleep(std::chrono::seconds{secs});
516}
517
518void QThread::msleep(unsigned long msecs)
519{
520 sleep(std::chrono::milliseconds{msecs});
521}
522
523void QThread::usleep(unsigned long usecs)
524{
525 sleep(std::chrono::microseconds{usecs});
526}
527
528void QThread::sleep(std::chrono::nanoseconds nsec)
529{
531}
532
533#if QT_CONFIG(thread)
534
535#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
536#if defined(Q_OS_QNX)
537static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority)
538{
539 // On QNX, NormalPriority is mapped to 10. A QNX system could use a value different
540 // than 10 for the "normal" priority but it's difficult to achieve this so we'll
541 // assume that no one has ever created such a system. This makes the mapping from
542 // Qt priorities to QNX priorities lopsided. There's usually more space available
543 // to map into above the "normal" priority than below it. QNX also has a privileged
544 // priority range (for threads that assist the kernel). We'll assume that no Qt
545 // thread needs to use priorities in that range.
546 int priority_norm = 10;
547 // _sched_info::priority_priv isn't documented. You'd think that it's the start of the
548 // privileged priority range but it's actually the end of the unpriviledged range.
549 struct _sched_info info;
550 if (SchedInfo_r(0, *sched_policy, &info) != EOK)
551 return false;
552
553 if (priority == QThread::IdlePriority) {
554 *sched_priority = info.priority_min;
555 return true;
556 }
557
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;
562
563 int to_min, to_max;
564 int from_min, from_max;
565 int prio;
566 if (priority < QThread::NormalPriority) {
567 to_min = info.priority_min;
568 to_max = priority_norm;
569 from_min = QThread::LowestPriority;
570 from_max = QThread::NormalPriority;
571 } else {
572 to_min = priority_norm;
573 to_max = info.priority_priv;
574 from_min = QThread::NormalPriority;
576 }
577
578 prio = ((priority - from_min) * (to_max - to_min)) / (from_max - from_min) + to_min;
579 prio = qBound(to_min, prio, to_max);
580
581 *sched_priority = prio;
582 return true;
583}
584#else
585// Does some magic and calculate the Unix scheduler priorities
586// sched_policy is IN/OUT: it must be set to a valid policy before calling this function
587// sched_priority is OUT only
588static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority)
589{
590#ifdef SCHED_IDLE
591 if (priority == QThread::IdlePriority) {
592 *sched_policy = SCHED_IDLE;
593 *sched_priority = 0;
594 return true;
595 }
596 const int lowestPriority = QThread::LowestPriority;
597#else
598 const int lowestPriority = QThread::IdlePriority;
599#endif
600 const int highestPriority = QThread::TimeCriticalPriority;
601
602 int prio_min;
603 int prio_max;
604#if defined(Q_OS_VXWORKS) && defined(VXWORKS_DKM)
605 // for other scheduling policies than SCHED_RR or SCHED_FIFO
606 prio_min = SCHED_FIFO_LOW_PRI;
607 prio_max = SCHED_FIFO_HIGH_PRI;
608
609 if ((*sched_policy == SCHED_RR) || (*sched_policy == SCHED_FIFO))
610#endif
611 {
612 prio_min = sched_get_priority_min(*sched_policy);
613 prio_max = sched_get_priority_max(*sched_policy);
614 }
615
616 if (prio_min == -1 || prio_max == -1)
617 return false;
618
619 int prio;
620 // crudely scale our priority enum values to the prio_min/prio_max
621 prio = ((priority - lowestPriority) * (prio_max - prio_min) / highestPriority) + prio_min;
622 prio = qMax(prio_min, qMin(prio_max, prio));
623
624 *sched_priority = prio;
625 return true;
626}
627#endif
628#endif
629
630void QThread::start(Priority priority)
631{
632 Q_D(QThread);
633 QMutexLocker locker(&d->mutex);
634
635 if (d->isInFinish)
636 d->thread_done.wait(locker.mutex());
637
638 if (d->running)
639 return;
640
641 d->running = true;
642 d->finished = false;
643 d->returnCode = 0;
644 d->exited = false;
645 d->interruptionRequested.store(false, std::memory_order_relaxed);
646
647 pthread_attr_t attr;
648 pthread_attr_init(&attr);
649 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
650
651 d->priority = priority;
652
653#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
654 switch (priority) {
655 case InheritPriority:
656 {
657 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
658 break;
659 }
660
661 default:
662 {
663 int sched_policy;
664 if (pthread_attr_getschedpolicy(&attr, &sched_policy) != 0) {
665 // failed to get the scheduling policy, don't bother
666 // setting the priority
667 qWarning("QThread::start: Cannot determine default scheduler policy");
668 break;
669 }
670
671 int prio;
672 if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
673 // failed to get the scheduling parameters, don't
674 // bother setting the priority
675 qWarning("QThread::start: Cannot determine scheduler priority range");
676 break;
677 }
678
679 sched_param sp;
680 sp.sched_priority = prio;
681
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) {
685 // could not set scheduling hints, fallback to inheriting them
686 // we'll try again from inside the thread
687 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
688 d->priority = qToUnderlying(priority) | ThreadPriorityResetFlag;
689 }
690 break;
691 }
692 }
693#endif // QT_HAS_THREAD_PRIORITY_SCHEDULING
694
695
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);
699#else
700 int code = ENOSYS; // stack size not supported, automatically fail
701#endif // _POSIX_THREAD_ATTR_STACKSIZE
702
703 if (code) {
704 qErrnoWarning(code, "QThread::start: Thread stack size error");
705
706 // we failed to set the stacksize, and as the documentation states,
707 // the thread will fail to run...
708 d->running = false;
709 d->finished = false;
710 return;
711 }
712 }
713
714#ifdef Q_OS_INTEGRITY
715 if (Q_LIKELY(objectName().isEmpty()))
716 pthread_attr_setthreadname(&attr, metaObject()->className());
717 else
718 pthread_attr_setthreadname(&attr, objectName().toLocal8Bit());
719#else
720 // avoid interacting with the binding system
721 d->objectName = d->extraData ? d->extraData->objectName.valueBypassingBindings()
722 : QString();
723#endif
724
725 pthread_t threadId;
726 int code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
727 if (code == EPERM) {
728 // caller does not have permission to set the scheduling
729 // parameters/policy
730#if defined(QT_HAS_THREAD_PRIORITY_SCHEDULING)
731 pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
732#endif
733 code = pthread_create(&threadId, &attr, QThreadPrivate::start, this);
734 }
735 d->data->threadId.storeRelaxed(to_HANDLE(threadId));
736
737 pthread_attr_destroy(&attr);
738
739 if (code) {
740 qErrnoWarning(code, "QThread::start: Thread creation error");
741
742 d->running = false;
743 d->finished = false;
744 d->data->threadId.storeRelaxed(nullptr);
745 }
746}
747
749{
750#if !defined(Q_OS_ANDROID)
751 Q_D(QThread);
752 QMutexLocker locker(&d->mutex);
753
754 if (!d->data->threadId.loadRelaxed())
755 return;
756
757 int code = pthread_cancel(from_HANDLE<pthread_t>(d->data->threadId.loadRelaxed()));
758 if (code) {
759 qErrnoWarning(code, "QThread::start: Thread termination error");
760 }
761#endif
762}
763
765{
766 Q_D(QThread);
767 QMutexLocker locker(&d->mutex);
768
769 if (from_HANDLE<pthread_t>(d->data->threadId.loadRelaxed()) == pthread_self()) {
770 qWarning("QThread::wait: Thread tried to wait on itself");
771 return false;
772 }
773
774 if (d->finished || !d->running)
775 return true;
776
777 while (d->running) {
778 if (!d->thread_done.wait(locker.mutex(), deadline))
779 return false;
780 }
781 Q_ASSERT(d->data->threadId.loadRelaxed() == nullptr);
782
783 return true;
784}
785
787{
788 QThread *thr = currentThread();
789 Q_ASSERT_X(thr != nullptr, "QThread::setTerminationEnabled()",
790 "Current thread was not started with QThread.");
791
792 Q_UNUSED(thr);
793#if defined(Q_OS_ANDROID)
795#else
796 pthread_setcancelstate(enabled ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, nullptr);
797 if (enabled)
798 pthread_testcancel();
799#endif
800}
801
802// Caller must lock the mutex
803void QThreadPrivate::setPriority(QThread::Priority threadPriority)
804{
805 priority = threadPriority;
806
807 // copied from start() with a few modifications:
808
809#ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING
810 int sched_policy;
811 sched_param param;
812
813 if (pthread_getschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), &sched_policy, &param) != 0) {
814 // failed to get the scheduling policy, don't bother setting
815 // the priority
816 qWarning("QThread::setPriority: Cannot get scheduler parameters");
817 return;
818 }
819
820 int prio;
821 if (!calculateUnixPriority(priority, &sched_policy, &prio)) {
822 // failed to get the scheduling parameters, don't
823 // bother setting the priority
824 qWarning("QThread::setPriority: Cannot determine scheduler priority range");
825 return;
826 }
827
828 param.sched_priority = prio;
829 int status = pthread_setschedparam(from_HANDLE<pthread_t>(data->threadId.loadRelaxed()), sched_policy, &param);
830
831# ifdef SCHED_IDLE
832 // were we trying to set to idle priority and failed?
833 if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) {
834 // reset to lowest priority possible
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);
838 }
839# else
840 Q_UNUSED(status);
841# endif // SCHED_IDLE
842#endif
843}
844
845#endif // QT_CONFIG(thread)
846
848
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(...
\inmodule QtCore
@ DeferredDelete
Definition qcoreevent.h:100
\inmodule QtCore
Definition qmutex.h:313
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
QString objectName
the name of this object
Definition qobject.h:107
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static Q_AUTOTEST_EXPORT QThreadData * current(bool createIfNecessary=true)
Definition qthread.cpp:1087
QThreadData(int initialRefCount=1)
Definition qthread.cpp:48
static void clearCurrentThreadData()
Definition qthread.cpp:1103
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:291
static QAbstractEventDispatcher * createEventDispatcher(QThreadData *data)
void terminate()
Definition qthread.cpp:1003
void start(Priority=InheritPriority)
Definition qthread.cpp:996
static int idealThreadCount() noexcept
Definition qthread.cpp:1049
static QThread * currentThread()
Definition qthread.cpp:1039
static void setTerminationEnabled(bool enabled=true)
Definition qthread.cpp:1080
@ LowestPriority
Definition qthread.h:43
@ TimeCriticalPriority
Definition qthread.h:49
@ InheritPriority
Definition qthread.h:51
@ IdlePriority
Definition qthread.h:41
@ NormalPriority
Definition qthread.h:45
static void yieldCurrentThread()
Definition qthread.cpp:1054
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition qthread.cpp:1023
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.
void * HANDLE
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
#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 QT_RETHROW
#define QT_CATCH(A)
#define QT_TRY
INT_PTR intptr_t
#define qWarning
Definition qlogging.h:166
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLenum GLuint id
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum type
GLenum const GLint * param
GLuint name
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLdouble GLdouble t
Definition qopenglext.h:243
GLfloat GLfloat p
[1]
GLenum GLsizei len
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
SSL_CTX int void * arg
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
#define sp
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)
#define emit
#define Q_UNUSED(x)
QT_BEGIN_NAMESPACE constexpr std::underlying_type_t< Enum > qToUnderlying(Enum e) noexcept
const char className[16]
[1]
Definition qwizard.cpp:100
QDeadlineTimer deadline(30s)
obj metaObject() -> className()
QObject::connect nullptr
QHostInfo info
[0]