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>
This commit is contained in:
Mike Achtelik 2020-06-17 08:04:03 +02:00
parent f6b7b64ed0
commit 76c3eee402

View File

@ -109,81 +109,43 @@ static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
enum { ThreadPriorityResetFlag = 0x80000000 }; enum { ThreadPriorityResetFlag = 0x80000000 };
static thread_local QThreadData *currentThreadData = nullptr; class QThreadDataHolder
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)
{ {
#if defined(Q_OS_VXWORKS) public:
// Calling setspecific(..., 0) sets the value to 0 for ALL threads. QThreadData* data;
// The 'set to 1' workaround adds a bit of an overhead though,
// since this function is called twice now. ~QThreadDataHolder()
if (p == (void *)1) {
return; if (!data)
#endif return;
// 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 if (data->isAdopted) {
// right value... QThread *thread = data->thread.loadAcquire();
pthread_setspecific(current_thread_data_key, p); Q_ASSERT(thread);
QThreadData *data = static_cast<QThreadData *>(p); QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
if (data->isAdopted) { Q_ASSERT(!thread_p->finished);
QThread *thread = data->thread.loadAcquire(); thread_p->finish(thread);
Q_ASSERT(thread); }
QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); data->deref();
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. // Utility functions for getting, setting and clearing thread specific data.
static QThreadData *get_thread_data() static QThreadData *get_thread_data()
{ {
return currentThreadData; return currentThreadData.data;
} }
static void set_thread_data(QThreadData *data) static void set_thread_data(QThreadData *data)
{ {
currentThreadData = data; currentThreadData.data = data;
pthread_once(&current_thread_data_once, create_current_thread_data_key);
pthread_setspecific(current_thread_data_key, data);
} }
static void clear_thread_data() static void clear_thread_data()
{ {
currentThreadData = nullptr; currentThreadData.data = nullptr;
pthread_setspecific(current_thread_data_key, nullptr);
} }
template <typename T> template <typename T>