diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2020-07-02 10:53:10 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2020-07-02 10:57:20 +0200 |
commit | 6a47b5850be2768742b1f83f637ffd8c348f836e (patch) | |
tree | 3483054da19f7b05d9ab0893706cd7cd6cd70a1f /src | |
parent | 1048d83fc29d77e7a8def35ba41454fe35f4747b (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.cpp | 80 |
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(¤t_thread_data_key, destroy_current_thread_data); +} + +static void destroy_current_thread_data_key() +{ + pthread_once(¤t_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(¤t_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> |