diff options
author | mread <qt-info@nokia.com> | 2010-10-21 09:39:36 (GMT) |
---|---|---|
committer | mread <qt-info@nokia.com> | 2010-10-21 10:20:45 (GMT) |
commit | 131774bb881a8a80503f4719fc7a7459521acdf0 (patch) | |
tree | ec53f72498f4580664cff5e0d9dad61fb3b4fcbb /src/corelib | |
parent | 7e7bf0449d567c99882a37bb138221dfca9a3ed0 (diff) | |
download | Qt-131774bb881a8a80503f4719fc7a7459521acdf0.zip Qt-131774bb881a8a80503f4719fc7a7459521acdf0.tar.gz Qt-131774bb881a8a80503f4719fc7a7459521acdf0.tar.bz2 |
Using TLS to store QThreadData on Symbian
TLS access on Symbian is significantly faster than using
pthread_getspecific. In the case of QThreadData, the data associated
with a thread, it makes sense to store and access the pointer in TLS
rather than using the pthread thread specific functions.
However, the pthread thread specific function have some destructor
functionality that Symbian TLS does not, so Symbian still uses the
pthread functions for setting the QThreadData to get the destruction
behaviour.
This change has wide ranging performance benefits for QML execution.
With improvements shown on a number of the declarative benchmarks.
Frame drawing times on test apps are also showing some improvement.
The qthread* autotests have been run on Symbian^3 and Ubuntu 10.10
Task-number: QT-4089
Reviewed-by: Shane Kearns
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index a7601b6..a44a0e8 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -142,6 +142,39 @@ static void destroy_current_thread_data_key() } Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key) + +// Utility functions for getting, setting and clearing thread specific data. +// In Symbian, TLS access is significantly faster than pthread_getspecific. +// However Symbian does not have the thread destruction cleanup functionality +// that pthread has, so pthread_setspecific is also used. +static QThreadData *get_thread_data() +{ +#ifdef Q_OS_SYMBIAN + return reinterpret_cast<QThreadData *>(Dll::Tls()); +#else + pthread_once(¤t_thread_data_once, create_current_thread_data_key); + return reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key)); +#endif +} + +static void set_thread_data(QThreadData *data) +{ +#ifdef Q_OS_SYMBIAN + qt_symbian_throwIfError(Dll::SetTls(data)); +#endif + pthread_once(¤t_thread_data_once, create_current_thread_data_key); + pthread_setspecific(current_thread_data_key, data); +} + +static void clear_thread_data() +{ +#ifdef Q_OS_SYMBIAN + Dll::FreeTls(); +#endif + pthread_setspecific(current_thread_data_key, 0); +} + + #ifdef Q_OS_SYMBIAN static void init_symbian_thread_handle(RThread &thread) { @@ -158,26 +191,24 @@ static void init_symbian_thread_handle(RThread &thread) QThreadData *QThreadData::current() { - pthread_once(¤t_thread_data_once, create_current_thread_data_key); - - QThreadData *data = reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key)); + QThreadData *data = get_thread_data(); if (!data) { void *a; if (QInternal::activateCallbacks(QInternal::AdoptCurrentThread, &a)) { QThread *adopted = static_cast<QThread*>(a); Q_ASSERT(adopted); data = QThreadData::get2(adopted); - pthread_setspecific(current_thread_data_key, data); + set_thread_data(data); adopted->d_func()->running = true; adopted->d_func()->finished = false; static_cast<QAdoptedThread *>(adopted)->init(); } else { data = new QThreadData; - pthread_setspecific(current_thread_data_key, data); QT_TRY { + set_thread_data(data); data->thread = new QAdoptedThread(data); } QT_CATCH(...) { - pthread_setspecific(current_thread_data_key, 0); + clear_thread_data(); data->deref(); data = 0; QT_RETHROW; @@ -268,8 +299,7 @@ void *QThreadPrivate::start(void *arg) User::SetCritical(User::EProcessCritical); #endif - pthread_once(¤t_thread_data_once, create_current_thread_data_key); - pthread_setspecific(current_thread_data_key, data); + set_thread_data(data); data->ref(); data->quitNow = false; |