diff options
Diffstat (limited to 'src/corelib/arch')
-rw-r--r-- | src/corelib/arch/arch.pri | 12 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_armv5.h | 204 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_armv6.h | 833 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_armv7.h | 57 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_bootstrap.h | 34 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_cxx11.h | 220 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_gcc.h | 145 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_ia64.h | 1084 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_msvc.h | 35 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_unix.cpp | 87 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_unix.h | 144 | ||||
-rw-r--r-- | src/corelib/arch/qatomic_x86.h | 433 | ||||
-rw-r--r-- | src/corelib/arch/sparc/arch.pri | 10 | ||||
-rw-r--r-- | src/corelib/arch/sparc/qatomic32.s | 95 | ||||
-rw-r--r-- | src/corelib/arch/sparc/qatomic64.s | 319 | ||||
-rw-r--r-- | src/corelib/arch/sparc/qatomic_sparc.cpp | 84 |
16 files changed, 217 insertions, 3579 deletions
diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 083d912331..ec617386a4 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -1,19 +1,7 @@ win32|wince:HEADERS += arch/qatomic_msvc.h HEADERS += \ - arch/qatomic_armv5.h \ - arch/qatomic_armv6.h \ - arch/qatomic_armv7.h \ arch/qatomic_bootstrap.h \ - arch/qatomic_ia64.h \ - arch/qatomic_x86.h \ - arch/qatomic_gcc.h \ arch/qatomic_cxx11.h atomic64-libatomic: LIBS += -latomic - -unix { - # fallback implementation when no other appropriate qatomic_*.h exists - HEADERS += arch/qatomic_unix.h - SOURCES += arch/qatomic_unix.cpp -} diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h deleted file mode 100644 index 8a1b78aec7..0000000000 --- a/src/corelib/arch/qatomic_armv5.h +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_ARMV5_H -#define QATOMIC_ARMV5_H - -#include <QtCore/qgenericatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT32_IS_SUPPORTED -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE - -#ifdef QT_NO_ARM_EABI -# error "Sorry, ARM without EABI is no longer supported" -#endif -#ifndef Q_OS_LINUX -# error "Qt is misconfigured: this ARMv5 implementation is only possible on Linux" -#endif - -template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> > -{ - // kernel places a restartable cmpxchg implementation at a fixed address - template <typename T> - static int _q_cmpxchg(T oldval, T newval, volatile T *ptr) Q_DECL_NOTHROW - { - typedef int (* kernel_cmpxchg_t)(T oldval, T newval, volatile T *ptr); - kernel_cmpxchg_t kernel_cmpxchg = *reinterpret_cast<kernel_cmpxchg_t>(0xffff0fc0); - return kernel_cmpxchg(oldval, newval, ptr); - } - static void _q_dmb() Q_DECL_NOTHROW - { - typedef void (* kernel_dmb_t)(); - kernel_dmb_t kernel_dmb = *reinterpret_cast<kernel_dmb_t>(0xffff0fa0); - kernel_dmb(); - } - - template <typename T> - static void orderedMemoryFence(const T &) Q_DECL_NOTHROW { _q_dmb(); } - - template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW; - template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW; - - static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return false; } - static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW; - template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW; - template <typename T> static - T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; -}; - -template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)> -{ - typedef T Type; -}; - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - do { - originalValue = _q_value; - newValue = originalValue + 1; - } while (_q_cmpxchg(originalValue, newValue, &_q_value) != 0); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - do { - originalValue = _q_value; - newValue = originalValue - 1; - } while (_q_cmpxchg(originalValue, newValue, &_q_value) != 0); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - T originalValue; - do { - originalValue = _q_value; - if (originalValue != expectedValue) - return false; - } while (_q_cmpxchg(expectedValue, newValue, &_q_value) != 0); - return true; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T originalValue; - do { - originalValue = _q_value; - if (originalValue != expectedValue) { - if (currentValue) - *currentValue = originalValue; - return false; - } - } while (_q_cmpxchg(expectedValue, newValue, &_q_value) != 0); - return true; -} - -// Fetch and store for integers -#ifdef Q_CC_RVCT -template<> template <typename T> inline -__asm T QBasicAtomicOps<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - add r2, pc, #0 - bx r2 - arm - swp r2,r1,[r0] - mov r0, r2 - bx lr - thumb -} -#else -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ -#if defined(__thumb__) - T originalValue; - do { - originalValue = _q_value; - } while (_q_cmpxchg(originalValue, newValue, &_q_value) != 0); - return originalValue; -#else - T originalValue; - asm volatile("swp %0,%2,[%3]" - : "=&r"(originalValue), "=m" (_q_value) - : "r"(newValue), "r"(&_q_value) - : "cc", "memory"); - return originalValue; -#endif -} -#endif // Q_CC_RVCT - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - do { - originalValue = _q_value; - newValue = originalValue + valueToAdd; - } while (_q_cmpxchg(originalValue, newValue, &_q_value) != 0); - return originalValue; -} - -QT_END_NAMESPACE - -#endif // QATOMIC_ARMV5_H diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h deleted file mode 100644 index b2ea85ada2..0000000000 --- a/src/corelib/arch/qatomic_armv6.h +++ /dev/null @@ -1,833 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_ARMV6_H -#define QATOMIC_ARMV6_H - -#include <QtCore/qgenericatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT32_IS_SUPPORTED -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> > -{ - template <typename T> - static void orderedMemoryFence(const T &) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; } - template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW; - template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, - T newValue, T *currentValue) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; } - template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; } - template <typename T> static - T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; - -private: - template <typename T> static inline T shrinkFrom32Bit(T value); - template <typename T> static inline T extendTo32Bit(T value); -}; - -template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)> -{ - // this is GCC or GCC-like, so we can use extensions: - // force the alignment to be the size of the type, as on some ABIs the alignment - // of 64-bit types is 32-bit. We need proper alignment for LDREX / STREX. - typedef __attribute__((__aligned__(sizeof(T)))) T Type; -}; - -#ifndef Q_CC_RVCT - -#ifndef Q_DATA_MEMORY_BARRIER -# define Q_DATA_MEMORY_BARRIER asm volatile("mcr p15, 0, r0, c7, c10, 5":::"memory") -#endif -#ifndef Q_COMPILER_MEMORY_BARRIER -# define Q_COMPILER_MEMORY_BARRIER asm volatile("":::"memory") -#endif - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrex %[newValue], [%[_q_value]]\n" - "add %[newValue], %[newValue], #1\n" - "strex %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrex %[newValue], [%[_q_value]]\n" - "sub %[newValue], %[newValue], #1\n" - "strex %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - int result; - asm volatile("0:\n" - "ldrex %[result], [%[_q_value]]\n" - "eors %[result], %[result], %[expectedValue]\n" - "itt eq\n" - "strexeq %[result], %[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return result == 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T tempValue; - int result; - asm volatile("0:\n" - "ldrex %[tempValue], [%[_q_value]]\n" - "eors %[result], %[tempValue], %[expectedValue]\n" - "itt eq\n" - "strexeq %[result], %[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - [tempValue] "=&r" (tempValue), - "+m" (_q_value) - : [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - *currentValue = tempValue; - return result == 0; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T originalValue; - int result; - asm volatile("0:\n" - "ldrex %[originalValue], [%[_q_value]]\n" - "strex %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [result] "=&r" (result), - "+m" (_q_value) - : [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return originalValue; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - int result; - asm volatile("0:\n" - "ldrex %[originalValue], [%[_q_value]]\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - "strex %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale), - [_q_value] "r" (&_q_value) - : "cc"); - return originalValue; -} - -#if defined(__ARM_ARCH_7__) \ - || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) \ - || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_6K__) -// LDREXB, LDREXH and LDREXD are available on ARMv6K or higher - -template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; - -#define Q_ATOMIC_INT8_IS_SUPPORTED -#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT16_IS_SUPPORTED -#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT64_IS_SUPPORTED -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -// note: if T is signed, parameters are passed sign-extended in the -// registers. However, our 8- and 16-bit operations don't do sign -// extension. So we need to clear out the input on entry and sign-extend again -// on exit. -template<int Size> template <typename T> -T QBasicAtomicOps<Size>::shrinkFrom32Bit(T value) -{ - Q_STATIC_ASSERT(Size == 1 || Size == 2); - if (T(-1) > T(0)) - return value; // unsigned, ABI will zero extend - if (Size == 1) - asm volatile("and %0, %0, %1" : "+r" (value) : "I" (0xff)); - else - asm volatile("and %0, %0, %1" : "+r" (value) : "r" (0xffff)); - return value; -} - -template<int Size> template <typename T> -T QBasicAtomicOps<Size>::extendTo32Bit(T value) -{ - Q_STATIC_ASSERT(Size == 1 || Size == 2); - if (T(-1) > T(0)) - return value; // unsigned, ABI will zero extend - if (Size == 1) - asm volatile("sxtb %0, %0" : "+r" (value)); - else - asm volatile("sxth %0, %0" : "+r" (value)); - return value; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<1>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrexb %[newValue], [%[_q_value]]\n" - "add %[newValue], %[newValue], #1\n" - "strexb %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrexb %[newValue], [%[_q_value]]\n" - "sub %[newValue], %[newValue], #1\n" - "strexb %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - T result; - asm volatile("0:\n" - "ldrexb %[result], [%[_q_value]]\n" - "eors %[result], %[result], %[expectedValue]\n" - "itt eq\n" - "strexbeq %[result], %[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return result == 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T tempValue; - T result; - asm volatile("0:\n" - "ldrexb %[tempValue], [%[_q_value]]\n" - "eors %[result], %[tempValue], %[expectedValue]\n" - "itt eq\n" - "strexbeq %[result], %[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - [tempValue] "=&r" (tempValue), - "+m" (_q_value) - : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - *currentValue = extendTo32Bit(tempValue); - return result == 0; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T originalValue; - int result; - asm volatile("0:\n" - "ldrexb %[originalValue], [%[_q_value]]\n" - "strexb %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [result] "=&r" (result), - "+m" (_q_value) - : [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return extendTo32Bit(originalValue); -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - int result; - asm volatile("0:\n" - "ldrexb %[originalValue], [%[_q_value]]\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - "strexb %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale), - [_q_value] "r" (&_q_value) - : "cc"); - return extendTo32Bit(originalValue); -} - -template<> template<typename T> inline -bool QBasicAtomicOps<2>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrexh %[newValue], [%[_q_value]]\n" - "add %[newValue], %[newValue], #1\n" - "strexh %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrexh %[newValue], [%[_q_value]]\n" - "sub %[newValue], %[newValue], #1\n" - "strexh %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - T result; - asm volatile("0:\n" - "ldrexh %[result], [%[_q_value]]\n" - "eors %[result], %[result], %[expectedValue]\n" - "itt eq\n" - "strexheq %[result], %[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return result == 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T tempValue; - T result; - asm volatile("0:\n" - "ldrexh %[tempValue], [%[_q_value]]\n" - "eors %[result], %[tempValue], %[expectedValue]\n" - "itt eq\n" - "strexheq %[result], %[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - [tempValue] "=&r" (tempValue), - "+m" (_q_value) - : [expectedValue] "r" (shrinkFrom32Bit(expectedValue)), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - *currentValue = extendTo32Bit(tempValue); - return result == 0; -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T originalValue; - int result; - asm volatile("0:\n" - "ldrexh %[originalValue], [%[_q_value]]\n" - "strexh %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [result] "=&r" (result), - "+m" (_q_value) - : [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return extendTo32Bit(originalValue); -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - int result; - asm volatile("0:\n" - "ldrexh %[originalValue], [%[_q_value]]\n" - "add %[newValue], %[originalValue], %[valueToAdd]\n" - "strexh %[result], %[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale), - [_q_value] "r" (&_q_value) - : "cc"); - return extendTo32Bit(originalValue); -} - -// Explanation from GCC's source code (config/arm/arm.c) on the modifiers below: -// Whenever you use "r" (dwordVariable), you get assigned a register pair: -// %[reg] - lower-numbered register -// %H[reg] - higher-numbered register -// %Q[reg] - low part of the value -// %R[reg] - high part of the value -// If this is a little-endian build, H and R are the same; otherwise, H and Q are the same. - -template<> template<typename T> inline -bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrexd %[newValue], %H[newValue], [%[_q_value]]\n" - "adds %Q[newValue], %Q[newValue], #1\n" - "adc %R[newValue], %R[newValue], #0\n" - "strexd %[result], %[newValue], %H[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T newValue; - int result; - asm volatile("0:\n" - "ldrexd %[newValue], %H[newValue], [%[_q_value]]\n" - "subs %Q[newValue], %Q[newValue], #1\n" - "sbc %R[newValue], %R[newValue], #0\n" - "strexd %[result], %[newValue], %H[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [_q_value] "r" (&_q_value) - : "cc", "memory"); - return newValue != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - T result; - asm volatile("0:\n" - "ldrexd %[result], %H[result], [%[_q_value]]\n" - "eor %[result], %[result], %[expectedValue]\n" - "eor %H[result], %H[result], %H[expectedValue]\n" - "orrs %[result], %[result], %H[result]\n" - "itt eq\n" - "strexdeq %[result], %[newValue], %H[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - "+m" (_q_value) - : [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return quint32(result) == 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T tempValue; - T result; - asm volatile("0:\n" - "ldrexd %[tempValue], %H[tempValue], [%[_q_value]]\n" - "eor %[result], %[tempValue], %[expectedValue]\n" - "eor %H[result], %H[tempValue], %H[expectedValue]\n" - "orrs %[result], %[result], %H[result]\n" - "itt eq\n" - "strexdeq %[result], %[newValue], %H[newValue], [%[_q_value]]\n" - "teqeq %[result], #1\n" - "beq 0b\n" - : [result] "=&r" (result), - [tempValue] "=&r" (tempValue), - "+m" (_q_value) - : [expectedValue] "r" (expectedValue), - [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - *currentValue = tempValue; - return quint32(result) == 0; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T originalValue; - int result; - asm volatile("0:\n" - "ldrexd %[originalValue], %H[originalValue], [%[_q_value]]\n" - "strexd %[result], %[newValue], %H[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [result] "=&r" (result), - "+m" (_q_value) - : [newValue] "r" (newValue), - [_q_value] "r" (&_q_value) - : "cc"); - return originalValue; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T originalValue; - T newValue; - int result; - asm volatile("0:\n" - "ldrexd %[originalValue], %H[originalValue], [%[_q_value]]\n" - "adds %Q[newValue], %Q[originalValue], %Q[valueToAdd]\n" - "adc %R[newValue], %R[originalValue], %R[valueToAdd]\n" - "strexd %[result], %[newValue], %H[newValue], [%[_q_value]]\n" - "teq %[result], #0\n" - "bne 0b\n" - : [originalValue] "=&r" (originalValue), - [newValue] "=&r" (newValue), - [result] "=&r" (result), - "+m" (_q_value) - : [valueToAdd] "r" (valueToAdd * QAtomicAdditiveType<T>::AddScale), - [_q_value] "r" (&_q_value) - : "cc"); - return originalValue; -} - -#endif - -#else -// This is Q_CC_RVCT - -// RVCT inline assembly documentation: -// http://www.keil.com/support/man/docs/armcc/armcc_chdcffdb.htm -// RVCT embedded assembly documentation: -// http://www.keil.com/support/man/docs/armcc/armcc_chddbeib.htm - -#if __TARGET_ARCH_THUMB-0 < 4 -// save our pragma state and switch to ARM mode (unless using Thumb2) -# pragma push -# pragma arm -#endif - -#ifndef Q_DATA_MEMORY_BARRIER -# define Q_DATA_MEMORY_BARRIER __schedule_barrier() -#endif -#ifndef Q_COMPILER_MEMORY_BARRIER -# define Q_COMPILER_MEMORY_BARRIER __schedule_barrier() -#endif - -inline bool QBasicAtomicInt::ref() Q_DECL_NOTHROW -{ - int newValue; - int result; - retry: - __asm { - ldrex newValue, [&_q_value] - add newValue, newValue, #1 - strex result, newValue, [&_q_value] - teq result, #0 - bne retry - } - return newValue != 0; -} - -inline bool QBasicAtomicInt::deref() Q_DECL_NOTHROW -{ - int newValue; - int result; - retry: - __asm { - ldrex newValue, [&_q_value] - sub newValue, newValue, #1 - strex result, newValue, [&_q_value] - teq result, #0 - bne retry - } - return newValue != 0; -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) Q_DECL_NOTHROW -{ - int result; - retry: - __asm { - ldrex result, [&_q_value] - eors result, result, expectedValue - strexeq result, newValue, [&_q_value] - teqeq result, #1 - beq retry - } - return result == 0; -} - -inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) Q_DECL_NOTHROW -{ - int originalValue; - int result; - retry: - __asm { - ldrex originalValue, [&_q_value] - strex result, newValue, [&_q_value] - teq result, #0 - bne retry - } - return originalValue; -} - -inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) Q_DECL_NOTHROW -{ - int originalValue; - int newValue; - int result; - retry: - __asm { - ldrex originalValue, [&_q_value] - add newValue, originalValue, valueToAdd - strex result, newValue, [&_q_value] - teq result, #0 - bne retry - } - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) Q_DECL_NOTHROW -{ - T *result; - retry: - __asm { - ldrex result, [&_q_value] - eors result, result, expectedValue - strexeq result, newValue, [&_q_value] - teqeq result, #1 - beq retry - } - return result == 0; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) Q_DECL_NOTHROW -{ - T *originalValue; - int result; - retry: - __asm { - ldrex originalValue, [&_q_value] - strex result, newValue, [&_q_value] - teq result, #0 - bne retry - } - return originalValue; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) Q_DECL_NOTHROW -{ - T *originalValue; - T *newValue; - int result; - retry: - __asm { - ldrex originalValue, [&_q_value] - add newValue, originalValue, valueToAdd * sizeof(T) - strex result, newValue, [&_q_value] - teq result, #0 - bne retry - } - return originalValue; -} - -#if __TARGET_ARCH_THUMB-0 < 4 -# pragma pop -#endif - -#endif - -// common code - -template <int size> template <typename T> inline -void QBasicAtomicOps<size>::orderedMemoryFence(const T &) Q_DECL_NOTHROW -{ - Q_DATA_MEMORY_BARRIER; -} - -#undef Q_DATA_MEMORY_BARRIER -#undef Q_COMPILER_MEMORY_BARRIER - -QT_END_NAMESPACE - -#endif // QATOMIC_ARMV6_H diff --git a/src/corelib/arch/qatomic_armv7.h b/src/corelib/arch/qatomic_armv7.h deleted file mode 100644 index 07ef91edbc..0000000000 --- a/src/corelib/arch/qatomic_armv7.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_ARMV7_H -#define QATOMIC_ARMV7_H - -// use the DMB instruction when compiling for ARMv7, ... -#ifndef Q_CC_RCVT -# define Q_DATA_MEMORY_BARRIER asm volatile("dmb\n":::"memory") -#else -# define Q_DATA_MEMORY_BARRIER do{__asm { dmb } __schedule_barrier();}while(0) -#endif - -// ... but the implementation is otherwise identical to that for ARMv6 -#include "QtCore/qatomic_armv6.h" - -#if 0 -// silence syncqt warnings -QT_BEGIN_NAMESPACE - -QT_END_NAMESPACE - -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#endif // QATOMIC_ARMV7_H diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h index 852cd0a83a..b463f817bd 100644 --- a/src/corelib/arch/qatomic_bootstrap.h +++ b/src/corelib/arch/qatomic_bootstrap.h @@ -1,32 +1,38 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index baa3d65faf..63b23b71ab 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -1,31 +1,38 @@ /**************************************************************************** ** ** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 Intel Corporation. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -46,44 +53,168 @@ QT_END_NAMESPACE #pragma qt_sync_stop_processing #endif -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +/* Attempt to detect whether the atomic operations exist in hardware + * or whether they are emulated by way of a lock. + * + * C++11 29.4 [atomics.lockfree] p1 says + * + * The ATOMIC_..._LOCK_FREE macros indicate the lock-free property of the + * corresponding atomic types, with the signed and unsigned variants grouped + * together. The properties also apply to the corresponding (partial) + * specializations of the atomic template. A value of 0 indicates that the + * types are never lock-free. A value of 1 indicates that the types are + * sometimes lock-free. A value of 2 indicates that the types are always + * lock-free. + * + * We have a problem when the value is 1: we'd need to check at runtime, but + * QAtomicInteger requires a constexpr answer (defect introduced in Qt 5.0). So + * we'll err in the side of caution and say it isn't. + */ + +// ### Qt 6: make non-constexpr (see above) +template <int N> struct QAtomicTraits +{ static Q_DECL_CONSTEXPR inline bool isLockFree(); }; #define Q_ATOMIC_INT32_IS_SUPPORTED -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +#if ATOMIC_INT_LOCK_FREE == 2 +# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() +{ return true; } +#elif ATOMIC_INT_LOCK_FREE == 1 +# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() +{ return false; } +#else +# define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<4>::isLockFree() +{ return false; } +#endif -#define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +#if ATOMIC_POINTER_LOCK_FREE == 2 +# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#elif ATOMIC_POINTER_LOCK_FREE == 1 +# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +#else +# define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NEVER_NATIVE +#endif template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; - #define Q_ATOMIC_INT8_IS_SUPPORTED -#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#if ATOMIC_CHAR_LOCK_FREE == 2 +# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() +{ return true; } +#elif ATOMIC_CHAR_LOCK_FREE == 1 +# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT8_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<1>::isLockFree() +{ return false; } +#else +# define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT8_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_NEVER_NATIVE +template <> Q_DECL_CONSTEXPR bool QAtomicTraits<1>::isLockFree() +{ return false; } +#endif + +template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT16_IS_SUPPORTED -#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#if ATOMIC_SHORT_LOCK_FREE == 2 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() +{ return false; } +#elif ATOMIC_SHORT_LOCK_FREE == 1 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() +{ return false; } +#else +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() +{ return false; } +#endif #ifndef QT_NO_STD_ATOMIC64 +template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; # define Q_ATOMIC_INT64_IS_SUPPORTED -# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +# if ATOMIC_LLONG_LOCK_FREE == 2 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() +{ return true; } +# elif ATOMIC_LLONG_LOCK_FREE == 1 +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() +{ return false; } +# else +# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE + +template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() +{ return false; } +# endif #endif template <typename X> struct QAtomicOps @@ -126,7 +257,7 @@ template <typename X> struct QAtomicOps _q_value.store(newValue, std::memory_order_release); } - static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; } + static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return false; } template <typename T> static inline bool ref(std::atomic<T> &_q_value) @@ -140,7 +271,8 @@ template <typename X> struct QAtomicOps return --_q_value != 0; } - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return false; } + static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW + { return QAtomicTraits<sizeof(X)>::isLockFree(); } static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } template <typename T> @@ -179,7 +311,7 @@ template <typename X> struct QAtomicOps return tmp; } - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return false; } + static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return false; } template <typename T> @@ -206,7 +338,7 @@ template <typename X> struct QAtomicOps return _q_value.exchange(newValue, std::memory_order_acq_rel); } - static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return false; } + static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return isTestAndSetNative(); } static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; } template <typename T> static inline diff --git a/src/corelib/arch/qatomic_gcc.h b/src/corelib/arch/qatomic_gcc.h deleted file mode 100644 index b671ac48db..0000000000 --- a/src/corelib/arch/qatomic_gcc.h +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_GCC_H -#define QATOMIC_GCC_H - -#include <QtCore/qgenericatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - -#define Q_ATOMIC_INT32_IS_SUPPORTED -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_SOMETIMES_NATIVE - -#define Q_ATOMIC_POINTER_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE -#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 QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; -#endif - -template <typename X> struct QAtomicOps: QGenericAtomicOps<QAtomicOps<X> > -{ - // The GCC intrinsics all have fully-ordered memory semantics, so we define - // only the xxxRelaxed functions. The exception is __sync_lock_and_test, - // which has acquire semantics, so we need to define the Release and - // Ordered versions too. - - typedef X Type; - -#ifndef __ia64__ - template <typename T> - static T loadAcquire(const T &_q_value) Q_DECL_NOTHROW - { - T tmp = _q_value; - __sync_synchronize(); - return tmp; - } - - template <typename T> - static void storeRelease(T &_q_value, T newValue) Q_DECL_NOTHROW - { - __sync_synchronize(); - _q_value = newValue; - } -#endif - - static Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return false; } - static Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } - template <typename T> - static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW - { - return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue); - } - - template <typename T> - static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW - { - bool tmp = __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue); - if (tmp) - *currentValue = expectedValue; - else - *currentValue = _q_value; - return tmp; - } - - template <typename T> - static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW - { - return __sync_lock_test_and_set(&_q_value, newValue); - } - - template <typename T> - static T fetchAndStoreRelease(T &_q_value, T newValue) Q_DECL_NOTHROW - { - __sync_synchronize(); - return __sync_lock_test_and_set(&_q_value, newValue); - } - - template <typename T> - static T fetchAndStoreOrdered(T &_q_value, T newValue) Q_DECL_NOTHROW - { - return fetchAndStoreRelease(_q_value, newValue); - } - - template <typename T> static - T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW - { - return __sync_fetch_and_add(&_q_value, valueToAdd * QAtomicAdditiveType<T>::AddScale); - } -}; - -QT_END_NAMESPACE -#endif // QATOMIC_GCC_H diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h deleted file mode 100644 index 2ba6d127d9..0000000000 --- a/src/corelib/arch/qatomic_ia64.h +++ /dev/null @@ -1,1084 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_IA64_H -#define QATOMIC_IA64_H - -#include <QtCore/qgenericatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT32_IS_SUPPORTED - -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT8_IS_SUPPORTED - -#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT16_IS_SUPPORTED - -#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -#define Q_ATOMIC_INT64_IS_SUPPORTED - -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE - -template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; - -template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> > -{ - template <typename T> - static void orderedMemoryFence(const T &) Q_DECL_NOTHROW; - - template <typename T> static inline - T loadAcquire(const T &_q_value) Q_DECL_NOTHROW - { - return *static_cast<const volatile T *>(&_q_value); - } - - template <typename T> static inline - void storeRelease(T &_q_value, T newValue) Q_DECL_NOTHROW - { - *static_cast<volatile T *>(&_q_value) = newValue; - } - static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return size == 4 || size == 8; } - template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW; - template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; - template <typename T> static bool testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue = 0) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW; - template <typename T> static T fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW; - template <typename T> static T fetchAndStoreRelease(T &_q_value, T newValue) Q_DECL_NOTHROW; - template <typename T> static T fetchAndStoreOrdered(T &_q_value, T newValue) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return false; } - template <typename T> static - T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; - template <typename T> static - T fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; - template <typename T> static - T fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; - template <typename T> static - T fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; -}; - -template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)> -{ - typedef T Type; -}; - -inline bool _q_ia64_fetchadd_immediate(int value) -{ - return value == 1 || value == -1 - || value == 4 || value == -4 - || value == 8 || value == -8 - || value == 16 || value == -16; -} - -#if defined(Q_CC_INTEL) - -// intrinsics provided by the Intel C++ Compiler -#include <ia64intrin.h> - -template<int size> template <typename T> inline -void QBasicAtomicOps<size>::orderedMemoryFence(const T &) -{ - __memory_barrier(); -} - -inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) -{ - return static_cast<int>(_InterlockedExchange(&_q_value, newValue)); -} - -inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) -{ - int expectedValueCopy = expectedValue; - return (static_cast<int>(_InterlockedCompareExchange(&_q_value, - newValue, - expectedValueCopy)) - == expectedValue); -} - -inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) -{ - int expectedValueCopy = expectedValue; - return (static_cast<int>(_InterlockedCompareExchange_acq(reinterpret_cast<volatile uint *>(&_q_value), - newValue, - expectedValueCopy)) - == expectedValue); -} - -inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) -{ - int expectedValueCopy = expectedValue; - return (static_cast<int>(_InterlockedCompareExchange_rel(reinterpret_cast<volatile uint *>(&_q_value), - newValue, - expectedValueCopy)) - == expectedValue); -} - -inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) -{ - if (__builtin_constant_p(valueToAdd)) { - if (valueToAdd == 1) - return __fetchadd4_acq((unsigned int *)&_q_value, 1); - if (valueToAdd == -1) - return __fetchadd4_acq((unsigned int *)&_q_value, -1); - } - return _InterlockedExchangeAdd(&_q_value, valueToAdd); -} - -inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) -{ - if (__builtin_constant_p(valueToAdd)) { - if (valueToAdd == 1) - return __fetchadd4_rel((unsigned int *)&_q_value, 1); - if (valueToAdd == -1) - return __fetchadd4_rel((unsigned int *)&_q_value, -1); - } - __memory_barrier(); - return _InterlockedExchangeAdd(&_q_value, valueToAdd); -} - -inline bool QBasicAtomicInt::ref() -{ - return _InterlockedIncrement(&_q_value) != 0; -} - -inline bool QBasicAtomicInt::deref() -{ - return _InterlockedDecrement(&_q_value) != 0; -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) -{ - return (T *)_InterlockedExchangePointer(reinterpret_cast<void * volatile*>(&_q_value), newValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) -{ - T *expectedValueCopy = expectedValue; - return (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile*>(&_q_value), - newValue, - expectedValueCopy) - == expectedValue); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) -{ - union { - volatile void *x; - volatile unsigned long *p; - }; - x = &_q_value; - T *expectedValueCopy = expectedValue; - return (_InterlockedCompareExchange64_acq(p, quintptr(newValue), quintptr(expectedValueCopy)) - == quintptr(expectedValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) -{ - union { - volatile void *x; - volatile unsigned long *p; - }; - x = &_q_value; - T *expectedValueCopy = expectedValue; - return (_InterlockedCompareExchange64_rel(p, quintptr(newValue), quintptr(expectedValueCopy)) - == quintptr(expectedValue)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) -{ - return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value, - valueToAdd * sizeof(T)); -} - -template <typename T> -Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) -{ - __memory_barrier(); - return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value, - valueToAdd * sizeof(T)); -} - -#elif defined(Q_CC_GNU) - -template<int size> template <typename T> inline -void QBasicAtomicOps<size>::orderedMemoryFence(const T &) Q_DECL_NOTHROW -{ - asm volatile("mf" ::: "memory"); -} - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T ret; - asm volatile("fetchadd4.acq %0=%1,1\n" - : "=r" (ret), "+m" (_q_value) - : - : "memory"); - return ret != -1; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T ret; - asm volatile("fetchadd4.rel %0=%1,-1\n" - : "=r" (ret), "+m" (_q_value) - : - : "memory"); - return ret != 1; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW -{ - T ret; - asm volatile("fetchadd8.acq %0=%1,1\n" - : "=r" (ret), "+m" (_q_value) - : - : "memory"); - return ret != -1; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW -{ - T ret; - asm volatile("fetchadd8.rel %0=%1,-1\n" - : "=r" (ret), "+m" (_q_value) - : - : "memory"); - return ret != 1; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg1.acq %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg1.rel %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg2.acq %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg2.rel %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg4.acq %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg4.rel %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg8.acq %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetRelease(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("mov ar.ccv=%2\n" - ";;\n" - "cmpxchg8.rel %0=%1,%3,ar.ccv\n" - : "=r" (ret), "+m" (_q_value) - : "r" (expectedValue), "r" (newValue) - : "memory"); - if (currentValue) - *currentValue = ret; - return ret == expectedValue; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("xchg1 %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("xchg2 %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("xchg4 %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - T ret; - asm volatile("xchg8 %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "r" (newValue) - : "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg1.acq %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg1.rel %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg2.acq %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg2.rel %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - -#if (__GNUC__ >= 4) - // We implement a fast fetch-and-add when we can - if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) { - asm volatile("fetchadd4.acq %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "i" (valueToAdd) - : "memory"); - return ret; - } -#endif - - // otherwise, use a loop around test-and-set - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg4.acq %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - -#if (__GNUC__ >= 4) - // We implement a fast fetch-and-add when we can - if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) { - asm volatile("fetchadd4.rel %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "i" (valueToAdd) - : "memory"); - return ret; - } -#endif - - // otherwise, use a loop around test-and-set - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg4.rel %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - -#if (__GNUC__ >= 4) - // We implement a fast fetch-and-add when we can - if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) { - asm volatile("fetchadd8.acq %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "i" (valueToAdd) - : "memory"); - return ret; - } -#endif - - // otherwise, use a loop around test-and-set - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg8.acq %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndAddRelease(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T ret; - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - -#if (__GNUC__ >= 4) - // We implement a fast fetch-and-add when we can - if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) { - asm volatile("fetchadd8.rel %0=%1,%2\n" - : "=r" (ret), "+m" (_q_value) - : "i" (valueToAdd) - : "memory"); - return ret; - } -#endif - - // otherwise, use a loop around test-and-set - ret = _q_value; - asm volatile("0:\n" - " mov r9=%0\n" - " mov ar.ccv=%0\n" - " add %0=%0, %2\n" - " ;;\n" - " cmpxchg8.rel %0=%1,%0,ar.ccv\n" - " ;;\n" - " cmp.ne p6,p0 = %0, r9\n" - "(p6) br.dptk 0b\n" - "1:\n" - : "+r" (ret), "+m" (_q_value) - : "r" (valueToAdd) - : "r9", "p6", "memory"); - return ret; -} - -#elif defined Q_CC_HPACC - -QT_BEGIN_INCLUDE_NAMESPACE -#include <ia64/sys/inline.h> -QT_END_INCLUDE_NAMESPACE - -#define FENCE (_Asm_fence)(_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE) - -template <int size> inline -void QBasicAtomicOps<size>::orderedMemoryFence() Q_DECL_NOTHROW -{ - _Asm_mf(FENCE); -} - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW -{ - return (T)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, - &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != -1; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW -{ - return (T)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL, - &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != 1; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW -{ - return (T)_Asm_fetchadd((_Asm_fasz)_FASZ_D, (_Asm_sem)_SEM_ACQ, - &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != -1; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW -{ - return (T)_Asm_fetchadd((_Asm_fasz)_FASZ_D, (_Asm_sem)_SEM_REL, - &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != 1; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint8)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_B, (_Asm_sem)_SEM_ACQ, - &_q_value, (quint8)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint8)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_B, (_Asm_sem)_SEM_REL, - &_q_value, (quint8)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint16)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_H, (_Asm_sem)_SEM_ACQ, - &_q_value, (quint16)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint16)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_H, (_Asm_sem)_SEM_REL, - &_q_value, (quint16)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ, - &_q_value, (unsigned)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<4>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL, - &_q_value, newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetAcquire(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ, - &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::testAndSetRelease(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE); - T ret = (T)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL, - &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE); - return ret == expectedValue; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - return (T)_Asm_xchg((_Asm_sz)_SZ_B, &_q_value, (quint8)newValue, - (_Asm_ldhint)_LDHINT_NONE, FENCE); -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - return (T)_Asm_xchg((_Asm_sz)_SZ_H, &_q_value, (quint16)newValue, - (_Asm_ldhint)_LDHINT_NONE, FENCE); -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - return (T)_Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue, - (_Asm_ldhint)_LDHINT_NONE, FENCE); -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndStoreAcquire(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - return (T)_Asm_xchg((_Asm_sz)_SZ_D, &_q_value, (quint64)newValue, - (_Asm_ldhint)_LDHINT_NONE, FENCE); -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint8)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_B, (_Asm_sem)_SEM_ACQ, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint8)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_B, (_Asm_sem)_SEM_REL, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint16)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_H, (_Asm_sem)_SEM_ACQ, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<2>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint16)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_H, (_Asm_sem)_SEM_REL, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<4>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndAddAcquire(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - valueToAdd *= QAtomicAdditiveType<T>::AddScale; - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -template<> template <typename T> inline -T QBasicAtomicOps<8>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - // implement the test-and-set loop - T old, ret; - do { - old = _q_value; - _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE); - ret = _Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL, - &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); - } while (ret != old); - return old; -} - -#endif - -template<int size> template<typename T> inline -bool QBasicAtomicOps<size>::ref(T &_q_value) Q_DECL_NOTHROW -{ - // no fetchadd for 1 or 2 bytes - return fetchAndAddRelaxed(_q_value, 1) == -1; -} - -template<int size> template<typename T> inline -bool QBasicAtomicOps<size>::deref(T &_q_value) Q_DECL_NOTHROW -{ - // no fetchadd for 1 or 2 bytes - return fetchAndAddRelaxed(_q_value, -1) == 1; -} - -template<int size> template <typename T> inline -bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue); -} - -template<int size> template <typename T> inline -bool QBasicAtomicOps<size>::testAndSetOrdered(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW -{ - orderedMemoryFence(_q_value); - return testAndSetAcquire(_q_value, expectedValue, newValue, currentValue); -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - return fetchAndStoreAcquire(_q_value, newValue); -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndStoreRelease(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - orderedMemoryFence(_q_value); - return fetchAndStoreAcquire(_q_value, newValue); -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndStoreOrdered(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - return fetchAndStoreRelease(_q_value, newValue); -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - return fetchAndAddAcquire(_q_value, valueToAdd); -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndAddOrdered(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - orderedMemoryFence(_q_value); - return fetchAndAddRelease(_q_value, valueToAdd); -} - -QT_END_NAMESPACE - -#endif // QATOMIC_IA64_H diff --git a/src/corelib/arch/qatomic_msvc.h b/src/corelib/arch/qatomic_msvc.h index fc4d5a466a..62d54ded55 100644 --- a/src/corelib/arch/qatomic_msvc.h +++ b/src/corelib/arch/qatomic_msvc.h @@ -1,31 +1,38 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/corelib/arch/qatomic_unix.cpp b/src/corelib/arch/qatomic_unix.cpp deleted file mode 100644 index b96dacc0b0..0000000000 --- a/src/corelib/arch/qatomic_unix.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qplatformdefs.h" - -#include <QtCore/qatomic.h> - -// If operating system, processor, and compiler detection fails, we fall back -// to this generic, out-of-line implementation - -#if defined(QATOMIC_UNIX_H) - -QT_BEGIN_NAMESPACE -static pthread_mutex_t qAtomicMutex = PTHREAD_MUTEX_INITIALIZER; - -Q_CORE_EXPORT -bool QAtomicOps<int>::testAndSetRelaxed(int &_q_value, int expectedValue, int 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<long long>::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<void *>::testAndSetRelaxed(void *&_q_value, void *expectedValue, void *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; -} - -QT_END_NAMESPACE - -#endif // QATOMIC_UNIX_H diff --git a/src/corelib/arch/qatomic_unix.h b/src/corelib/arch/qatomic_unix.h deleted file mode 100644 index 59beaaf365..0000000000 --- a/src/corelib/arch/qatomic_unix.h +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_UNIX_H -#define QATOMIC_UNIX_H - -#include <QtCore/qgenericatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE - -#define Q_ATOMIC_INT32_IS_SUPPORTED -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_NOT_NATIVE -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_NOT_NATIVE -#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 - -// No definition, needs specialization -template <typename T> struct QAtomicOps; - -// 32-bit version -template <> -struct QAtomicOps<int> : QGenericAtomicOps<QAtomicOps<int> > -{ - typedef int 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(int &_q_value, int expectedValue, int newValue) Q_DECL_NOTHROW; -}; - -// 64-bit version -template <> -struct QAtomicOps<long long> : QGenericAtomicOps<QAtomicOps<long long> > -{ - 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<void *> : QGenericAtomicOps<QAtomicOps<void *> > -{ - typedef void *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(void *&_q_value, void *expectedValue, void *newValue) Q_DECL_NOTHROW; -}; - -template <typename T> -struct QAtomicOps<T *> : QGenericAtomicOps<QAtomicOps<T *> > -{ - typedef T *Type; - - // helper to strip cv qualifiers - static inline void *nocv(const T *p) { return const_cast<void *>(static_cast<const volatile void *>(p)); } - - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return false; } - static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return false; } - static inline bool testAndSetRelaxed(T *&_q_value, T *expectedValue, T *newValue) Q_DECL_NOTHROW - { - // forward to the void* specialization - void *voidp = nocv(_q_value); - bool returnValue = QAtomicOps<void *>::testAndSetRelaxed(voidp, nocv(expectedValue), nocv(newValue)); - _q_value = reinterpret_cast<T *>(voidp); - return returnValue; - } -}; - -// 32- and 64-bit unsigned versions -template <> struct QAtomicOps<unsigned> : QAtomicOps<int> -{ - typedef unsigned Type; - Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW - { - return QAtomicOps<int>::testAndSetRelaxed(reinterpret_cast<int &>(_q_value), int(expectedValue), int(newValue)); - } -}; -template <> struct QAtomicOps<unsigned long long> : QAtomicOps<long long> -{ - typedef unsigned long longType; - Q_CORE_EXPORT static bool testAndSetRelaxed(Type &_q_value, Type expectedValue, Type newValue) Q_DECL_NOTHROW - { - return QAtomicOps<long long>::testAndSetRelaxed(reinterpret_cast<long long &>(_q_value), int(expectedValue), int(newValue)); - } -}; - -QT_END_NAMESPACE -#endif // QATOMIC_UNIX_H diff --git a/src/corelib/arch/qatomic_x86.h b/src/corelib/arch/qatomic_x86.h deleted file mode 100644 index ccbc8fd61d..0000000000 --- a/src/corelib/arch/qatomic_x86.h +++ /dev/null @@ -1,433 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2011 Thiago Macieira <thiago@kde.org> -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QATOMIC_X86_H -#define QATOMIC_X86_H - -#include <QtCore/qgenericatomic.h> - -QT_BEGIN_NAMESPACE - -#if 0 -// silence syncqt warnings -QT_END_NAMESPACE -#pragma qt_sync_skip_header_check -#pragma qt_sync_stop_processing -#endif - -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_IS_SUPPORTED - -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT32_FETCH_AND_ADD_IS_WAIT_FREE - -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE - -template <int size> struct QBasicAtomicOps: QGenericAtomicOps<QBasicAtomicOps<size> > -{ - static inline Q_DECL_CONSTEXPR bool isReferenceCountingNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isReferenceCountingWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static bool ref(T &_q_value) Q_DECL_NOTHROW; - template <typename T> static bool deref(T &_q_value) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW; - template <typename T> static bool - testAndSetRelaxed(T &_q_value, T expectedValue, T newValue, T *currentValue) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isFetchAndStoreWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static T fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW; - - static inline Q_DECL_CONSTEXPR bool isFetchAndAddNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isFetchAndAddWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static - T fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW; -}; - -template <typename T> struct QAtomicOps : QBasicAtomicOps<sizeof(T)> -{ - typedef T Type; -}; - -#if defined(Q_CC_GNU) - -template<> struct QAtomicOpsSupport<1> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<2> { enum { IsSupported = 1 }; }; -template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; - -/* - * Guide for the inline assembly below: - * - * x86 instructions are in the form "{opcode}{length} {source}, {destination}", - * where the length is one of the letters "b" (byte), "w" (word, 16-bit), "l" - * (dword, 32-bit), "q" (qword, 64-bit). - * - * In most cases, we can omit the length because it's inferred from one of the - * registers. For example, "xchg %0,%1" doesn't need the length suffix because - * we can only exchange data of the same size and one of the operands must be a - * register. - * - * The exception is the increment and decrement functions, where we add and - * subtract an immediate value (1). For those, we need to specify the length. - * GCC and ICC support the syntax "add%z0 $1, %0", where "%z0" expands to the - * length of the operand. Unfortunately, clang as of 3.0 doesn't support that. - * For that reason, the ref() and deref() functions are rolled out for all - * sizes. - * - * The functions are also rolled out for the 1-byte operations since those - * require a special register constraint "q" to force the compiler to schedule - * one of the 8-bit registers. It's probably a compiler bug that it tries to - * use a register that doesn't exist. - * - * Finally, 64-bit operations are supported via the cmpxchg8b instruction on - * 32-bit processors, via specialisation below. - */ - -template<> template<typename T> inline -bool QBasicAtomicOps<1>::ref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "addb $1, %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<2>::ref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "incw %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} - -template<> template<typename T> inline -bool QBasicAtomicOps<4>::ref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "addl $1, %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::deref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "subb $1, %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<2>::deref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "decw %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} -template<> template <typename T> inline -bool QBasicAtomicOps<4>::deref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "subl $1, %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} - -template<int size> template <typename T> inline -bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "cmpxchg %3,%2\n" - "sete %1\n" - : "=a" (newValue), "=qm" (ret), "+m" (_q_value) - : "r" (newValue), "0" (expectedValue) - : "memory"); - return ret != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "cmpxchg %3,%2\n" - "sete %1\n" - : "=a" (newValue), "=qm" (ret), "+m" (_q_value) - : "q" (newValue), "0" (expectedValue) - : "memory"); - return ret != 0; -} - -template<int size> template <typename T> inline -bool QBasicAtomicOps<size>::testAndSetRelaxed(T &_q_value, T expectedValue, - T newValue, T *currentValue) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "cmpxchg %3,%2\n" - "sete %1\n" - : "=a" (newValue), "=qm" (ret), "+m" (_q_value) - : "r" (newValue), "0" (expectedValue) - : "memory"); - *currentValue = newValue; - return ret != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<1>::testAndSetRelaxed(T &_q_value, T expectedValue, - T newValue, T *currentValue) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "cmpxchg %3,%2\n" - "sete %1\n" - : "=a" (newValue), "=qm" (ret), "+m" (_q_value) - : "q" (newValue), "0" (expectedValue) - : "memory"); - *currentValue = newValue; - return ret != 0; -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - asm volatile("xchg %0,%1" - : "=r" (newValue), "+m" (_q_value) - : "0" (newValue) - : "memory"); - return newValue; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndStoreRelaxed(T &_q_value, T newValue) Q_DECL_NOTHROW -{ - asm volatile("xchg %0,%1" - : "=q" (newValue), "+m" (_q_value) - : "0" (newValue) - : "memory"); - return newValue; -} - -template<int size> template <typename T> inline -T QBasicAtomicOps<size>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T result; - asm volatile("lock\n" - "xadd %0,%1" - : "=r" (result), "+m" (_q_value) - : "0" (T(valueToAdd * QAtomicAdditiveType<T>::AddScale)) - : "memory"); - return result; -} - -template<> template <typename T> inline -T QBasicAtomicOps<1>::fetchAndAddRelaxed(T &_q_value, typename QAtomicAdditiveType<T>::AdditiveT valueToAdd) Q_DECL_NOTHROW -{ - T result; - asm volatile("lock\n" - "xadd %0,%1" - : "=q" (result), "+m" (_q_value) - : "0" (T(valueToAdd * QAtomicAdditiveType<T>::AddScale)) - : "memory"); - return result; -} - -#define Q_ATOMIC_INT8_IS_SUPPORTED - -#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT8_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT8_FETCH_AND_ADD_IS_WAIT_FREE - -#define Q_ATOMIC_INT16_IS_SUPPORTED - -#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_WAIT_FREE - -#ifdef Q_PROCESSOR_X86_64 - -#define Q_ATOMIC_INT64_IS_SUPPORTED - -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_WAIT_FREE - -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_WAIT_FREE - -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_WAIT_FREE - -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_WAIT_FREE - -// native support for 64-bit types -template<> template<typename T> inline -bool QBasicAtomicOps<8>::ref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "addq $1, %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} - -template<> template <typename T> inline -bool QBasicAtomicOps<8>::deref(T &_q_value) Q_DECL_NOTHROW -{ - unsigned char ret; - asm volatile("lock\n" - "subq $1, %0\n" - "setne %1" - : "=m" (_q_value), "=qm" (ret) - : "m" (_q_value) - : "memory"); - return ret != 0; -} -#else -// i386 architecture, emulate 64-bit support via cmpxchg8b -template <> struct QBasicAtomicOps<8>: QGenericAtomicOps<QBasicAtomicOps<8> > -{ - static inline Q_DECL_CONSTEXPR bool isTestAndSetNative() Q_DECL_NOTHROW { return true; } - static inline Q_DECL_CONSTEXPR bool isTestAndSetWaitFree() Q_DECL_NOTHROW { return true; } - template <typename T> static inline - bool testAndSetRelaxed(T &_q_value, T expectedValue, T newValue) Q_DECL_NOTHROW - { -#ifdef __PIC__ -# define EBX_reg "r" -# define EBX_load(reg) "xchg " reg ", %%ebx\n" -#else -# define EBX_reg "b" -# define EBX_load(reg) -#endif - quint32 highExpectedValue = quint32(newValue >> 32); // ECX - asm volatile(EBX_load("%3") - "lock\n" - "cmpxchg8b %0\n" - EBX_load("%3") - "sete %%cl\n" - : "+m" (_q_value), "+c" (highExpectedValue), "+&A" (expectedValue) - : EBX_reg (quint32(newValue & 0xffffffff)) - : "memory"); - // if the comparison failed, expectedValue here contains the current value - return quint8(highExpectedValue) != 0; -#undef EBX_reg -#undef EBX_load - } -}; -#endif - -#else -# error "This compiler for x86 is not supported" -#endif - - -QT_END_NAMESPACE - -#endif // QATOMIC_X86_H diff --git a/src/corelib/arch/sparc/arch.pri b/src/corelib/arch/sparc/arch.pri deleted file mode 100644 index a201c83c6a..0000000000 --- a/src/corelib/arch/sparc/arch.pri +++ /dev/null @@ -1,10 +0,0 @@ -# -# SPARC architecture -# -*-64* { - SOURCES += $$PWD/qatomic64.s -} -else { - SOURCES += $$PWD/qatomic32.s \ - $$PWD/qatomic_sparc.cpp -} diff --git a/src/corelib/arch/sparc/qatomic32.s b/src/corelib/arch/sparc/qatomic32.s deleted file mode 100644 index ec53a461d9..0000000000 --- a/src/corelib/arch/sparc/qatomic32.s +++ /dev/null @@ -1,95 +0,0 @@ -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! -!! Copyright (C) 2015 The Qt Company Ltd. -!! Contact: http://www.qt.io/licensing/ -!! -!! This file is part of the QtGui module of the Qt Toolkit. -!! -!! $QT_BEGIN_LICENSE:LGPL21$ -!! Commercial License Usage -!! Licensees holding valid commercial Qt licenses may use this file in -!! accordance with the commercial license agreement provided with the -!! Software or, alternatively, in accordance with the terms contained in -!! a written agreement between you and The Qt Company. For licensing terms -!! and conditions see http://www.qt.io/terms-conditions. For further -!! information use the contact form at http://www.qt.io/contact-us. -!! -!! GNU Lesser General Public License Usage -!! Alternatively, this file may be used under the terms of the GNU Lesser -!! General Public License version 2.1 or version 3 as published by the Free -!! Software Foundation and appearing in the file LICENSE.LGPLv21 and -!! LICENSE.LGPLv3 included in the packaging of this file. Please review the -!! following information to ensure the GNU Lesser General Public License -!! requirements will be met: https://www.gnu.org/licenses/lgpl.html and -!! http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -!! -!! As a special exception, The Qt Company gives you certain additional -!! rights. These rights are described in The Qt Company LGPL Exception -!! version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -!! -!! $QT_END_LICENSE$ -!! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - .section ".text" - - .align 4 - .type q_atomic_trylock_int,#function - .global q_atomic_trylock_int -q_atomic_trylock_int: - sethi %hi(-2147483648),%o2 - swap [%o0],%o2 - retl - mov %o2,%o0 - .size q_atomic_trylock_int,.-q_atomic_trylock_int - - - - - .align 4 - .type q_atomic_trylock_ptr,#function - .global q_atomic_trylock_ptr -q_atomic_trylock_ptr: - mov -1, %o2 - swap [%o0], %o2 - retl - mov %o2, %o0 - .size q_atomic_trylock_ptr,.-q_atomic_trylock_ptr - - - - - .align 4 - .type q_atomic_unlock,#function - .global q_atomic_unlock -q_atomic_unlock: - stbar - retl - st %o1,[%o0] - .size q_atomic_unlock,.-q_atomic_unlock - - - - - .align 4 - .type q_atomic_set_int,#function - .global q_atomic_set_int -q_atomic_set_int: - swap [%o0],%o1 - stbar - retl - mov %o1,%o0 - .size q_atomic_set_int,.-q_atomic_set_int - - - - - .align 4 - .type q_atomic_set_ptr,#function - .global q_atomic_set_ptr -q_atomic_set_ptr: - swap [%o0],%o1 - stbar - retl - mov %o1,%o0 - .size q_atomic_set_ptr,.-q_atomic_set_ptr - diff --git a/src/corelib/arch/sparc/qatomic64.s b/src/corelib/arch/sparc/qatomic64.s deleted file mode 100644 index 440167b7db..0000000000 --- a/src/corelib/arch/sparc/qatomic64.s +++ /dev/null @@ -1,319 +0,0 @@ -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! -!! Copyright (C) 2015 The Qt Company Ltd. -!! Contact: http://www.qt.io/licensing/ -!! -!! This file is part of the QtGui module of the Qt Toolkit. -!! -!! $QT_BEGIN_LICENSE:LGPL21$ -!! Commercial License Usage -!! Licensees holding valid commercial Qt licenses may use this file in -!! accordance with the commercial license agreement provided with the -!! Software or, alternatively, in accordance with the terms contained in -!! a written agreement between you and The Qt Company. For licensing terms -!! and conditions see http://www.qt.io/terms-conditions. For further -!! information use the contact form at http://www.qt.io/contact-us. -!! -!! GNU Lesser General Public License Usage -!! Alternatively, this file may be used under the terms of the GNU Lesser -!! General Public License version 2.1 or version 3 as published by the Free -!! Software Foundation and appearing in the file LICENSE.LGPLv21 and -!! LICENSE.LGPLv3 included in the packaging of this file. Please review the -!! following information to ensure the GNU Lesser General Public License -!! requirements will be met: https://www.gnu.org/licenses/lgpl.html and -!! http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -!! -!! As a special exception, The Qt Company gives you certain additional -!! rights. These rights are described in The Qt Company LGPL Exception -!! version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -!! -!! $QT_END_LICENSE$ -!! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - .section ".text" - - .align 4 - .type q_atomic_test_and_set_int,#function - .global q_atomic_test_and_set_int -q_atomic_test_and_set_int: - cas [%o0],%o1,%o2 - cmp %o1,%o2 - clr %o0 - retl - move %icc,1,%o0 - .size q_atomic_test_and_set_int,.-q_atomic_test_and_set_int - - .align 4 - .type q_atomic_test_and_set_acquire_int,#function - .global q_atomic_test_and_set_acquire_int -q_atomic_test_and_set_acquire_int: - cas [%o0],%o1,%o2 - cmp %o1,%o2 - clr %o0 - membar #LoadLoad | #LoadStore - retl - move %icc,1,%o0 - .size q_atomic_test_and_set_acquire_int,.-q_atomic_test_and_set_acquire_int - - .align 4 - .type q_atomic_test_and_set_release_int,#function - .global q_atomic_test_and_set_release_int -q_atomic_test_and_set_release_int: - membar #LoadStore | #StoreStore - cas [%o0],%o1,%o2 - cmp %o1,%o2 - clr %o0 - retl - move %icc,1,%o0 - .size q_atomic_test_and_set_release_int,.-q_atomic_test_and_set_release_int - - .align 4 - .type q_atomic_test_and_set_ptr,#function - .global q_atomic_test_and_set_ptr -q_atomic_test_and_set_ptr: - casx [%o0],%o1,%o2 - cmp %o1,%o2 - clr %o0 - retl - move %icc,1,%o0 - .size q_atomic_test_and_set_ptr,.-q_atomic_test_and_set_ptr - - .align 4 - .type q_atomic_increment,#function - .global q_atomic_increment -q_atomic_increment: -q_atomic_increment_retry: - ld [%o0],%o3 - add %o3,1,%o4 - cas [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_increment_retry - nop - cmp %o4,-1 - clr %o0 - retl - movne %icc,1,%o0 - .size q_atomic_increment,.-q_atomic_increment - - .align 4 - .type q_atomic_decrement,#function - .global q_atomic_decrement -q_atomic_decrement: -q_atomic_decrement_retry: - ld [%o0],%o3 - add %o3,-1,%o4 - cas [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_decrement_retry - nop - cmp %o4,1 - clr %o0 - retl - movne %icc,1,%o0 - .size q_atomic_decrement,.-q_atomic_decrement - - .align 4 - .type q_atomic_set_int,#function - .global q_atomic_set_int -q_atomic_set_int: -q_atomic_set_int_retry: - ld [%o0],%o2 - cas [%o0],%o2,%o1 - cmp %o2,%o1 - bne q_atomic_set_int_retry - nop - retl - mov %o1,%o0 - .size q_atomic_set_int,.-q_atomic_set_int - - .align 4 - .type q_atomic_set_ptr,#function - .global q_atomic_set_ptr -q_atomic_set_ptr: -q_atomic_set_ptr_retry: - ldx [%o0],%o2 - casx [%o0],%o2,%o1 - cmp %o2,%o1 - bne q_atomic_set_ptr_retry - nop - retl - mov %o1,%o0 - .size q_atomic_set_ptr,.-q_atomic_set_ptr - - .align 4 - .type q_atomic_fetch_and_add_int,#function - .global q_atomic_fetch_and_add_int -q_atomic_fetch_and_add_int: -q_atomic_fetch_and_add_int_retry: - ld [%o0],%o3 - add %o3,%o1,%o4 - cas [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_fetch_and_add_int_retry - nop - retl - mov %o3,%o0 - .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int - - .align 4 - .type q_atomic_fetch_and_add_acquire_int,#function - .global q_atomic_fetch_and_add_acquire_int -q_atomic_fetch_and_add_acquire_int: -q_atomic_fetch_and_add_acquire_int_retry: - ld [%o0],%o3 - add %o3,%o1,%o4 - cas [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_fetch_and_add_acquire_int_retry - nop - membar #LoadLoad | #LoadStore - retl - mov %o3,%o0 - .size q_atomic_fetch_and_add_acquire_int,.-q_atomic_fetch_and_add_acquire_int - - .align 4 - .type q_atomic_fetch_and_add_release_int,#function - .global q_atomic_fetch_and_add_release_int -q_atomic_fetch_and_add_release_int: -q_atomic_fetch_and_add_release_int_retry: - membar #LoadStore | #StoreStore - ld [%o0],%o3 - add %o3,%o1,%o4 - cas [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_fetch_and_add_release_int_retry - nop - retl - mov %o3,%o0 - .size q_atomic_fetch_and_add_release_int,.-q_atomic_fetch_and_add_release_int - - .align 4 - .type q_atomic_fetch_and_store_acquire_int,#function - .global q_atomic_fetch_and_store_acquire_int -q_atomic_fetch_and_store_acquire_int: -q_atomic_fetch_and_store_acquire_int_retry: - ld [%o0],%o2 - cas [%o0],%o2,%o1 - cmp %o2,%o1 - bne q_atomic_fetch_and_store_acquire_int_retry - nop - membar #LoadLoad | #LoadStore - retl - mov %o1,%o0 - .size q_atomic_fetch_and_store_acquire_int,.-q_atomic_fetch_and_store_acquire_int - - .align 4 - .type q_atomic_fetch_and_store_release_int,#function - .global q_atomic_fetch_and_store_release_int -q_atomic_fetch_and_store_release_int: -q_atomic_fetch_and_store_release_int_retry: - membar #LoadStore | #StoreStore - ld [%o0],%o2 - cas [%o0],%o2,%o1 - cmp %o2,%o1 - bne q_atomic_fetch_and_store_release_int_retry - nop - retl - mov %o1,%o0 - .size q_atomic_fetch_and_store_release_int,.-q_atomic_fetch_and_store_release_int - - .align 4 - .type q_atomic_test_and_set_acquire_ptr,#function - .global q_atomic_test_and_set_acquire_ptr -q_atomic_test_and_set_acquire_ptr: - casx [%o0],%o1,%o2 - cmp %o1,%o2 - clr %o0 - membar #LoadLoad | #LoadStore - retl - move %icc,1,%o0 - .size q_atomic_test_and_set_acquire_ptr,.-q_atomic_test_and_set_acquire_ptr - - .align 4 - .type q_atomic_test_and_set_release_ptr,#function - .global q_atomic_test_and_set_release_ptr -q_atomic_test_and_set_release_ptr: - membar #LoadStore | #StoreStore - casx [%o0],%o1,%o2 - cmp %o1,%o2 - clr %o0 - retl - move %icc,1,%o0 - .size q_atomic_test_and_set_release_ptr,.-q_atomic_test_and_set_release_ptr - - .align 4 - .type q_atomic_fetch_and_store_acquire_ptr,#function - .global q_atomic_fetch_and_store_acquire_ptr -q_atomic_fetch_and_store_acquire_ptr: -q_atomic_fetch_and_store_acquire_ptr_retry: - ldx [%o0],%o2 - casx [%o0],%o2,%o1 - cmp %o2,%o1 - bne q_atomic_fetch_and_store_acquire_ptr_retry - nop - membar #LoadLoad | #LoadStore - retl - mov %o1,%o0 - .size q_atomic_fetch_and_store_acquire_ptr,.-q_atomic_fetch_and_store_acquire_ptr - - .align 4 - .type q_atomic_fetch_and_store_release_ptr,#function - .global q_atomic_fetch_and_store_release_ptr -q_atomic_fetch_and_store_release_ptr: -q_atomic_fetch_and_store_release_ptr_retry: - membar #LoadStore | #StoreStore - ldx [%o0],%o2 - casx [%o0],%o2,%o1 - cmp %o2,%o1 - bne q_atomic_fetch_and_store_release_ptr_retry - nop - retl - mov %o1,%o0 - .size q_atomic_fetch_and_store_release_ptr,.-q_atomic_fetch_and_store_release_ptr - - .align 4 - .type q_atomic_fetch_and_add_ptr,#function - .global q_atomic_fetch_and_add_ptr -q_atomic_fetch_and_add_ptr: -q_atomic_fetch_and_add_ptr_retry: - ldx [%o0],%o3 - add %o3,%o1,%o4 - casx [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_fetch_and_add_ptr_retry - nop - retl - mov %o3,%o0 - .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr - - .align 4 - .type q_atomic_fetch_and_add_acquire_ptr,#function - .global q_atomic_fetch_and_add_acquire_ptr -q_atomic_fetch_and_add_acquire_ptr: -q_atomic_fetch_and_add_acquire_ptr_retry: - ldx [%o0],%o3 - add %o3,%o1,%o4 - casx [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_fetch_and_add_acquire_ptr_retry - nop - membar #LoadLoad | #LoadStore - retl - mov %o3,%o0 - .size q_atomic_fetch_and_add_acquire_ptr,.-q_atomic_fetch_and_add_acquire_ptr - - .align 4 - .type q_atomic_fetch_and_add_release_ptr,#function - .global q_atomic_fetch_and_add_release_ptr -q_atomic_fetch_and_add_release_ptr: -q_atomic_fetch_and_add_release_ptr_retry: - membar #LoadStore | #StoreStore - ldx [%o0],%o3 - add %o3,%o1,%o4 - casx [%o0],%o3,%o4 - cmp %o3,%o4 - bne q_atomic_fetch_and_add_release_ptr_retry - nop - retl - mov %o3,%o0 - .size q_atomic_fetch_and_add_release_ptr,.-q_atomic_fetch_and_add_release_ptr diff --git a/src/corelib/arch/sparc/qatomic_sparc.cpp b/src/corelib/arch/sparc/qatomic_sparc.cpp deleted file mode 100644 index eb16f8bb5f..0000000000 --- a/src/corelib/arch/sparc/qatomic_sparc.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qatomic.h> - -#include <limits.h> -#include <sched.h> - -extern "C" { - -int q_atomic_trylock_int(volatile int *addr); -int q_atomic_trylock_ptr(volatile void *addr); - -Q_CORE_EXPORT int q_atomic_lock_int(volatile int *addr) -{ - int returnValue = q_atomic_trylock_int(addr); - - if (returnValue == INT_MIN) { - do { - // spin until we think we can succeed - do { - sched_yield(); - returnValue = *addr; - } while (returnValue == INT_MIN); - - // try again - returnValue = q_atomic_trylock_int(addr); - } while (returnValue == INT_MIN); - } - - return returnValue; -} - -Q_CORE_EXPORT int q_atomic_lock_ptr(volatile void *addr) -{ - int returnValue = q_atomic_trylock_ptr(addr); - - if (returnValue == -1) { - do { - // spin until we think we can succeed - do { - sched_yield(); - returnValue = *reinterpret_cast<volatile int *>(addr); - } while (returnValue == -1); - - // try again - returnValue = q_atomic_trylock_ptr(addr); - } while (returnValue == -1); - } - - return returnValue; -} - -} // extern "C" |