diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/thread/qthread.cpp | 2 | ||||
-rw-r--r-- | src/corelib/thread/qthread.h | 33 | ||||
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 28 | ||||
-rw-r--r-- | src/corelib/thread/qthread_win.cpp | 2 |
4 files changed, 59 insertions, 6 deletions
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 9fd1dd059d..eeaec7f24d 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -844,7 +844,7 @@ bool QThread::event(QEvent* event) return QObject::event(event); } -Qt::HANDLE QThread::currentThreadId() noexcept +Qt::HANDLE QThread::currentThreadIdImpl() noexcept { return Qt::HANDLE(currentThread()); } diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index c7a6dc8f1a..8141f945b6 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -161,6 +161,7 @@ private: #if QT_CONFIG(cxx11_future) static QThread *createThreadImpl(std::future<void> &&future); #endif + static Qt::HANDLE currentThreadIdImpl() noexcept Q_DECL_PURE_FUNCTION; friend class QCoreApplication; friend class QThreadData; @@ -236,6 +237,38 @@ QThread *QThread::create(Function &&f) #endif // QT_CONFIG(cxx11_future) +/* + On architectures and platforms we know, interpret the thread control + block (TCB) as a unique identifier for a thread within a process. Otherwise, + fall back to a slower but safe implementation. + + As per the documentation of currentThreadId, we return an opaque handle + as a thread identifier, and application code is not supposed to use that + value for anything. In Qt we use the handle to check if threads are identical, + for which the TCB is sufficient. + + So we use the fastest possible way, rathern than spend time on returning + some pseudo-interoperable value. +*/ +inline Qt::HANDLE QThread::currentThreadId() noexcept +{ + Qt::HANDLE tid; // typedef to void* + Q_STATIC_ASSERT(sizeof(tid) == sizeof(void*)); + // See https://akkadia.org/drepper/tls.pdf for x86 ABI +#if defined(Q_PROCESSOR_X86_32) && defined(Q_OS_LINUX) // x86 32-bit always uses GS + __asm__("movl %%gs:0, %0" : "=r" (tid) : : ); +#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN64) + // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h + __asm__("movq %%gs:0, %0" : "=r" (tid) : : ); +#elif defined(Q_PROCESSOR_X86_64) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) + // x86_64 Linux, BSD uses FS + __asm__("movq %%fs:0, %0" : "=r" (tid) : : ); +#else + tid = currentThreadIdImpl(); +#endif + return tid; +} + QT_END_NAMESPACE #endif // QTHREAD_H diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index cb3c0d6bb1..21abe372eb 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -415,16 +415,36 @@ void QThreadPrivate::finish(void *arg) } - - /************************************************************************** ** QThread *************************************************************************/ -Qt::HANDLE QThread::currentThreadId() noexcept +/* + Since each thread is guaranteed to have its own copy of + currenThreadData, the address is guaranteed to be unique for each + running thread (but likely to be reused for newly started threads). + + CI tests fails on ARM architectures if we try to use the assembler, + or the address of the thread_local (even with a recent gcc version), so + stick to the pthread version there. The assembler would be + + // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344k/Babeihid.html + asm volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid)); + + and + + // see glibc/sysdeps/aarch64/nptl/tls.h + asm volatile ("mrs %0, tpidr_el0" : "=r" (tid)); + + for 32 and 64bit versions, respectively. +*/ +Qt::HANDLE QThread::currentThreadIdImpl() noexcept { - // requires a C cast here otherwise we run into trouble on AIX +#if defined(Q_PROCESSOR_ARM) return to_HANDLE(pthread_self()); +#else + return ¤tThreadData; +#endif } #if defined(QT_LINUXBASE) && !defined(_SC_NPROCESSORS_ONLN) diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index a72df2fc40..996bcf0a71 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -449,7 +449,7 @@ void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept ** QThread *************************************************************************/ -Qt::HANDLE QThread::currentThreadId() noexcept +Qt::HANDLE QThread::currentThreadIdImpl() noexcept { return reinterpret_cast<Qt::HANDLE>(quintptr(GetCurrentThreadId())); } |