summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2020-07-02 10:53:10 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2020-07-02 10:57:20 +0200
commit6a47b5850be2768742b1f83f637ffd8c348f836e (patch)
tree3483054da19f7b05d9ab0893706cd7cd6cd70a1f /src
parent1048d83fc29d77e7a8def35ba41454fe35f4747b (diff)
Revert "Remove pthread storage for thread local data"
The change introduced crashes in some tests that only surfaced in certain CMake configurations. This reverts commit 76c3eee4020cae681857ee17406c655f61f9082c. Pick-to: 5.15 Task-number: QTBUG-85357 Change-Id: Ief93aa41e2d487d73b879133e7df0fd5ce0451bd Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/thread/qthread_unix.cpp80
1 files changed, 59 insertions, 21 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 18b6caf5fc..35bfd35f1a 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -109,43 +109,81 @@ static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
enum { ThreadPriorityResetFlag = 0x80000000 };
-class QThreadDataHolder
-{
-public:
- QThreadData* data;
+static thread_local QThreadData *currentThreadData = nullptr;
- ~QThreadDataHolder()
- {
- if (!data)
- return;
+static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
+static pthread_key_t current_thread_data_key;
- if (data->isAdopted) {
- QThread *thread = data->thread.loadAcquire();
- Q_ASSERT(thread);
- QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
- Q_ASSERT(!thread_p->finished);
- thread_p->finish(thread);
- }
- data->deref();
+static void destroy_current_thread_data(void *p)
+{
+#if defined(Q_OS_VXWORKS)
+ // Calling setspecific(..., 0) sets the value to 0 for ALL threads.
+ // The 'set to 1' workaround adds a bit of an overhead though,
+ // since this function is called twice now.
+ if (p == (void *)1)
+ return;
+#endif
+ // POSIX says the value in our key is set to zero before calling
+ // this destructor function, so we need to set it back to the
+ // right value...
+ pthread_setspecific(current_thread_data_key, p);
+ QThreadData *data = static_cast<QThreadData *>(p);
+ if (data->isAdopted) {
+ QThread *thread = data->thread.loadAcquire();
+ Q_ASSERT(thread);
+ QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
+ Q_ASSERT(!thread_p->finished);
+ thread_p->finish(thread);
}
-};
+ data->deref();
+
+ // ... but we must reset it to zero before returning so we aren't
+ // called again (POSIX allows implementations to call destructor
+ // functions repeatedly until all values are zero)
+ pthread_setspecific(current_thread_data_key,
+#if defined(Q_OS_VXWORKS)
+ (void *)1);
+#else
+ nullptr);
+#endif
+}
+
+static void create_current_thread_data_key()
+{
+ pthread_key_create(&current_thread_data_key, destroy_current_thread_data);
+}
+
+static void destroy_current_thread_data_key()
+{
+ pthread_once(&current_thread_data_once, create_current_thread_data_key);
+ pthread_key_delete(current_thread_data_key);
+
+ // Reset current_thread_data_once in case we end up recreating
+ // the thread-data in the rare case of QObject construction
+ // after destroying the QThreadData.
+ pthread_once_t pthread_once_init = PTHREAD_ONCE_INIT;
+ current_thread_data_once = pthread_once_init;
+}
+Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
-static thread_local QThreadDataHolder currentThreadData;
// Utility functions for getting, setting and clearing thread specific data.
static QThreadData *get_thread_data()
{
- return currentThreadData.data;
+ return currentThreadData;
}
static void set_thread_data(QThreadData *data)
{
- currentThreadData.data = data;
+ currentThreadData = data;
+ pthread_once(&current_thread_data_once, create_current_thread_data_key);
+ pthread_setspecific(current_thread_data_key, data);
}
static void clear_thread_data()
{
- currentThreadData.data = nullptr;
+ currentThreadData = nullptr;
+ pthread_setspecific(current_thread_data_key, nullptr);
}
template <typename T>