From 8d2a9bcf1d22c3e48ff9dc7d8aaac9d4fcac0c64 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 2 Dec 2013 19:22:57 -0800 Subject: [PATCH] Ensure that the pointer-sized QAtomicInteger specialization exists This is already implemented in qatomic_x86.h, qatomic_ia64.h, qatomic_mips.h, qatomic_armv6.h, and qatomic_cxx11.h. For qatomic_msvc.h, we've just fixed it. For qatomic_gcc.h, we know that the compiler supports it, so just add it. According to the GCC manual, it might print a warning on some platforms, so we only enable that on 64-bit builds. For qatomic_unix.h, the support was missing (along with support for unsigned 32-bit), so this commits adds it. For qatomic_armv5.h, the platform does not always support 64-bit atomics, but ARMv5 cannot compile in 64-bit mode anyway. Change-Id: Ia8b3b5c641f11e5df05937fe7442be0a223174ef Reviewed-by: Lars Knoll --- src/corelib/arch/qatomic_gcc.h | 10 ++++++++ src/corelib/arch/qatomic_unix.cpp | 13 ++++++++++ src/corelib/arch/qatomic_unix.h | 40 +++++++++++++++++++++++++++++++ src/corelib/thread/qatomic.cpp | 16 ++++++++++++- 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/corelib/arch/qatomic_gcc.h b/src/corelib/arch/qatomic_gcc.h index 61e709655d0..4038c6dee08 100644 --- a/src/corelib/arch/qatomic_gcc.h +++ b/src/corelib/arch/qatomic_gcc.h @@ -75,6 +75,16 @@ template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +#if QT_POINTER_SIZE == 8 +# define Q_ATOMIC_INT64_IS_SUPPORTED +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +#endif + template struct QAtomicOps: QGenericAtomicOps > { // The GCC intrinsics all have fully-ordered memory semantics, so we define diff --git a/src/corelib/arch/qatomic_unix.cpp b/src/corelib/arch/qatomic_unix.cpp index 4acf43d6a5b..7a5c48c2359 100644 --- a/src/corelib/arch/qatomic_unix.cpp +++ b/src/corelib/arch/qatomic_unix.cpp @@ -64,6 +64,19 @@ bool QAtomicOps::testAndSetRelaxed(int &_q_value, int expectedValue, int ne return returnValue; } +Q_CORE_EXPORT +bool QAtomicOps::testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW +{ + bool returnValue = false; + pthread_mutex_lock(&qAtomicMutex); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} + Q_CORE_EXPORT bool QAtomicOps::testAndSetRelaxed(void *&_q_value, void *expectedValue, void *newValue) Q_DECL_NOTHROW { diff --git a/src/corelib/arch/qatomic_unix.h b/src/corelib/arch/qatomic_unix.h index 02583297f9d..017adabbe24 100644 --- a/src/corelib/arch/qatomic_unix.h +++ b/src/corelib/arch/qatomic_unix.h @@ -64,15 +64,25 @@ QT_END_NAMESPACE #define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NOT_NATIVE #define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NOT_NATIVE +#define Q_ATOMIC_INT64_IS_SUPPORTED +#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NOT_NATIVE +#define Q_ATOMIC_INT64_TEST_AND_SET_IS_NOT_NATIVE +#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NOT_NATIVE +#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NOT_NATIVE + #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; +template<> struct QAtomicIntegerTraits { enum { IsInteger = 1 }; }; // No definition, needs specialization template struct QAtomicOps; +// 32-bit version template <> struct QAtomicOps : QGenericAtomicOps > { @@ -83,6 +93,18 @@ struct QAtomicOps : QGenericAtomicOps > Q_CORE_EXPORT static bool testAndSetRelaxed(int &_q_value, int expectedValue, int newValue) Q_DECL_NOTHROW; }; +// 64-bit version +template <> +struct QAtomicOps : QGenericAtomicOps > +{ + typedef long long Type; + + static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return false; } + static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } + Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW; +}; + +// pointer version template <> struct QAtomicOps : QGenericAtomicOps > { @@ -113,5 +135,23 @@ struct QAtomicOps : QGenericAtomicOps > } }; +// 32- and 64-bit unsigned versions +template <> struct QAtomicOps : QAtomicOps +{ + typedef unsigned Type; + Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW + { + return QAtomicOps::testAndSetRelaxed(reinterpret_cast(_q_value), int(expectedValue), int(newValue)); + } +}; +template <> struct QAtomicOps : QAtomicOps +{ + typedef unsigned long longType; + Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW + { + return QAtomicOps::testAndSetRelaxed(reinterpret_cast(_q_value), int(expectedValue), int(newValue)); + } +}; + QT_END_NAMESPACE #endif // QATOMIC_UNIX_H diff --git a/src/corelib/thread/qatomic.cpp b/src/corelib/thread/qatomic.cpp index f70b58d25b2..36cdfdb369b 100644 --- a/src/corelib/thread/qatomic.cpp +++ b/src/corelib/thread/qatomic.cpp @@ -72,9 +72,10 @@ \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11) \li 64-bit: long long, unsigned long long, qint64, quint64 \li platform-specific size: long, unsigned long + \li pointer size: qintptr, quintptr, qptrdiff \endlist - Of the list above, only the 32-bit-sized instantiations are guaranteed to + Of the list above, only the 32-bit- and pointer-sized instantiations are guaranteed to work on all platforms. Support for other sizes depends on the compiler and processor architecture the code is being compiled for. To test whether the other types are supported, check the macro \c Q_ATOMIC_INT\e{nn}_IS_SUPPORTED, @@ -1213,3 +1214,16 @@ #ifndef Q_ATOMIC_INT32_IS_SUPPORTED # error "Q_ATOMIC_INT32_IS_SUPPORTED must be defined" #endif +#if !defined(Q_ATOMIC_INT64_IS_SUPPORTED) && QT_POINTER_SIZE == 8 +// 64-bit platform +# error "Q_ATOMIC_INT64_IS_SUPPORTED must be defined on a 64-bit platform" +#endif + +QT_BEGIN_NAMESPACE + +// The following three specializations must always be defined +Q_STATIC_ASSERT(sizeof(QAtomicInteger)); +Q_STATIC_ASSERT(sizeof(QAtomicInteger)); +Q_STATIC_ASSERT(sizeof(QAtomicInteger)); + +QT_END_NAMESPACE