summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormread <qt-info@nokia.com>2010-10-21 10:39:36 +0100
committermread <qt-info@nokia.com>2010-10-21 11:20:45 +0100
commit131774bb881a8a80503f4719fc7a7459521acdf0 (patch)
treeec53f72498f4580664cff5e0d9dad61fb3b4fcbb
parent7e7bf0449d567c99882a37bb138221dfca9a3ed0 (diff)
downloadqt4-tools-131774bb881a8a80503f4719fc7a7459521acdf0.tar.gz
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
-rw-r--r--src/corelib/thread/qthread_unix.cpp46
1 files changed, 38 insertions, 8 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index a7601b654a..a44a0e811a 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(&current_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(&current_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(&current_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(&current_thread_data_once, create_current_thread_data_key);
- pthread_setspecific(current_thread_data_key, data);
+ set_thread_data(data);
data->ref();
data->quitNow = false;