summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Achtelik <mike.achtelik@gmail.com>2020-06-17 08:04:03 +0200
committerMike Achtelik <mike.achtelik@gmail.com>2020-06-28 19:12:32 +0200
commit76c3eee4020cae681857ee17406c655f61f9082c (patch)
tree18fac208110050de939943252c070ac4a290f0bb
parentf6b7b64ed0168038e365b936a1daea9b3bcda335 (diff)
Remove pthread storage for thread local data
The thread specific QThreadData is currently referenced as a thread_local variable and using a thread specific value via pthread_setspecific. Having both is not necessary, as the pthread value is never directly accessed and only used in the pthread destructor. Using a holder, we can achieve the same and get rid of the pthread handling altogether. This also fixes a bug, where the thread_local currentThreadData is already null, when entering the pthread destructor. In this case it would lead to a new QThreadData being created, when finishing an adopted thread. Pick-to: 5.15 Change-Id: Ib23b840f804637e6b7cebd89016672a34a575380 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/thread/qthread_unix.cpp80
1 files changed, 21 insertions, 59 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 35bfd35f1a..18b6caf5fc 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -109,81 +109,43 @@ static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
enum { ThreadPriorityResetFlag = 0x80000000 };
-static thread_local QThreadData *currentThreadData = nullptr;
-
-static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
-static pthread_key_t current_thread_data_key;
-
-static void destroy_current_thread_data(void *p)
+class QThreadDataHolder
{
-#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
-}
+public:
+ QThreadData* data;
-static void create_current_thread_data_key()
-{
- pthread_key_create(&current_thread_data_key, destroy_current_thread_data);
-}
+ ~QThreadDataHolder()
+ {
+ if (!data)
+ return;
-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)
+ 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 thread_local QThreadDataHolder currentThreadData;
// Utility functions for getting, setting and clearing thread specific data.
static QThreadData *get_thread_data()
{
- return currentThreadData;
+ return currentThreadData.data;
}
static void set_thread_data(QThreadData *data)
{
- currentThreadData = data;
- pthread_once(&current_thread_data_once, create_current_thread_data_key);
- pthread_setspecific(current_thread_data_key, data);
+ currentThreadData.data = data;
}
static void clear_thread_data()
{
- currentThreadData = nullptr;
- pthread_setspecific(current_thread_data_key, nullptr);
+ currentThreadData.data = nullptr;
}
template <typename T>