summaryrefslogtreecommitdiffstats
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
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>
-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>