Split the futexFlags() function in two: a hot and a cold path
authorThiago Macieira <thiago.macieira@intel.com>
Fri, 10 Aug 2012 14:06:41 +0000 (16:06 +0200)
committerQt by Nokia <qt-info@nokia.com>
Sat, 25 Aug 2012 08:35:34 +0000 (10:35 +0200)
We could mark the cold path with __attribute__((cold)) (since GCC 4.3),
but quick tests locally indicate that the compiler is smart enough to
determine that by itself.

It will inline the hot path in _q_futex, which in turn is inlined in the
lockInternal and unlockInternal functions, whereas the cold path is kept
outside.

Change-Id: I8ae7d851d4f050498bfb491ba87d3e25453a14f8
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
src/corelib/thread/qmutex_linux.cpp

index 3ccaeff..3fb3db2 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
-static inline int futexFlags()
+static QBasicAtomicInt futexFlagSupport = Q_BASIC_ATOMIC_INITIALIZER(-1);
+
+static int checkFutexPrivateSupport()
 {
     int value = 0;
 #if defined(FUTEX_PRIVATE_FLAG)
     // check if the kernel supports extra futex flags
     // FUTEX_PRIVATE_FLAG appeared in v2.6.22
-    static QBasicAtomicInt futexFlagSupport = Q_BASIC_ATOMIC_INITIALIZER(-1);
-
-    value = futexFlagSupport.load();
-    if (value == -1) {
-        // try an operation that has no side-effects: wake up 42 threads
-        // futex will return -1 (errno==ENOSYS) if the flag isn't supported
-        // there should be no other error conditions
-        value = syscall(__NR_futex, &futexFlagSupport,
-                        FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
-                        42, 0, 0, 0);
-        if (value != -1) {
-            value = FUTEX_PRIVATE_FLAG;
-            futexFlagSupport.store(value);
-            return value;
-        }
+    Q_STATIC_ASSERT(FUTEX_PRIVATE_FLAG != 0x80000000);
+
+    // try an operation that has no side-effects: wake up 42 threads
+    // futex will return -1 (errno==ENOSYS) if the flag isn't supported
+    // there should be no other error conditions
+    value = syscall(__NR_futex, &futexFlagSupport,
+                    FUTEX_WAKE | FUTEX_PRIVATE_FLAG,
+                    42, 0, 0, 0);
+    if (value != -1)
+        value = FUTEX_PRIVATE_FLAG;
+    else
         value = 0;
-        futexFlagSupport.store(value);
-    }
+
+#else
+    value = 0;
 #endif
+    futexFlagSupport.store(value);
     return value;
 }
 
+static inline int futexFlags()
+{
+    int value = futexFlagSupport.load();
+    if (Q_LIKELY(value != -1))
+        return value;
+    return checkFutexPrivateSupport();
+}
+
 static inline int _q_futex(void *addr, int op, int val, const struct timespec *timeout) Q_DECL_NOTHROW
 {
     volatile int *int_addr = reinterpret_cast<volatile int *>(addr);