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>
This commit is contained in:
parent
1048d83fc2
commit
6a47b5850b
@ -109,43 +109,81 @@ static_assert(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
|
|||||||
enum { ThreadPriorityResetFlag = 0x80000000 };
|
enum { ThreadPriorityResetFlag = 0x80000000 };
|
||||||
|
|
||||||
|
|
||||||
class QThreadDataHolder
|
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)
|
||||||
{
|
{
|
||||||
public:
|
#if defined(Q_OS_VXWORKS)
|
||||||
QThreadData* data;
|
// Calling setspecific(..., 0) sets the value to 0 for ALL threads.
|
||||||
|
// The 'set to 1' workaround adds a bit of an overhead though,
|
||||||
~QThreadDataHolder()
|
// since this function is called twice now.
|
||||||
{
|
if (p == (void *)1)
|
||||||
if (!data)
|
return;
|
||||||
return;
|
#endif
|
||||||
|
// POSIX says the value in our key is set to zero before calling
|
||||||
if (data->isAdopted) {
|
// this destructor function, so we need to set it back to the
|
||||||
QThread *thread = data->thread.loadAcquire();
|
// right value...
|
||||||
Q_ASSERT(thread);
|
pthread_setspecific(current_thread_data_key, p);
|
||||||
QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
|
QThreadData *data = static_cast<QThreadData *>(p);
|
||||||
Q_ASSERT(!thread_p->finished);
|
if (data->isAdopted) {
|
||||||
thread_p->finish(thread);
|
QThread *thread = data->thread.loadAcquire();
|
||||||
}
|
Q_ASSERT(thread);
|
||||||
data->deref();
|
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.
|
// Utility functions for getting, setting and clearing thread specific data.
|
||||||
static QThreadData *get_thread_data()
|
static QThreadData *get_thread_data()
|
||||||
{
|
{
|
||||||
return currentThreadData.data;
|
return currentThreadData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_thread_data(QThreadData *data)
|
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()
|
static void clear_thread_data()
|
||||||
{
|
{
|
||||||
currentThreadData.data = nullptr;
|
currentThreadData = nullptr;
|
||||||
|
pthread_setspecific(current_thread_data_key, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user