Remove all the atomic code besides MSVC and std::atomic
[ChangeLog][Important Behavior Changes] Starting with Qt 5.7, Qt requires a C++11 compiler with support for C++11 atomics. This affects user code too: Qt headers no longer compile with a C++98 compiler. The minimum compiler versions for this release are: * Clang 3.4 (found in XCode 5.1) * GCC 4.7 * Microsoft Visual Studio 2012 Change-Id: Ib056b47dde3341ef9a52ffff13ef1f496ea9363f Reviewed-by: Marc Mutz <marc.mutz@kdab.com> Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
This commit is contained in:
parent
57671bebbc
commit
7ffcafd1b5
@ -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
|
||||
}
|
||||
|
@ -1,210 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
@ -1,839 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
@ -1,63 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
@ -1,151 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
File diff suppressed because it is too large
Load Diff
@ -1,93 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
@ -1,150 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
@ -1,439 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2011 Thiago Macieira <thiago@kde.org>
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
@ -1,10 +0,0 @@
|
||||
#
|
||||
# SPARC architecture
|
||||
#
|
||||
*-64* {
|
||||
SOURCES += $$PWD/qatomic64.s
|
||||
}
|
||||
else {
|
||||
SOURCES += $$PWD/qatomic32.s \
|
||||
$$PWD/qatomic_sparc.cpp
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!
|
||||
!! Copyright (C) 2016 The Qt Company Ltd.
|
||||
!! Contact: https://www.qt.io/licensing/
|
||||
!!
|
||||
!! This file is part of the QtGui module of the Qt Toolkit.
|
||||
!!
|
||||
!! $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 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 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.
|
||||
!!
|
||||
!! 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$
|
||||
!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
.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
|
||||
|
@ -1,325 +0,0 @@
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!!
|
||||
!! Copyright (C) 2016 The Qt Company Ltd.
|
||||
!! Contact: https://www.qt.io/licensing/
|
||||
!!
|
||||
!! This file is part of the QtGui module of the Qt Toolkit.
|
||||
!!
|
||||
!! $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 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 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.
|
||||
!!
|
||||
!! 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$
|
||||
!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
.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
|
@ -1,90 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $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 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 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.
|
||||
**
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#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"
|
@ -46,42 +46,16 @@
|
||||
# include <QtCore/qatomic_bootstrap.h>
|
||||
|
||||
// If C++11 atomics are supported, use them!
|
||||
#elif defined(Q_COMPILER_ATOMICS) && defined(Q_COMPILER_CONSTEXPR) && !defined(QT_ATOMIC_FORCE_NO_CXX11)
|
||||
#elif defined(Q_COMPILER_ATOMICS) && defined(Q_COMPILER_CONSTEXPR)
|
||||
# include <QtCore/qatomic_cxx11.h>
|
||||
|
||||
// The following is used for testing only.
|
||||
// Note that we don't check the compiler support -- you had better
|
||||
// know what you're doing if you set it
|
||||
#elif defined(QT_ATOMIC_FORCE_GCC)
|
||||
# include <QtCore/qatomic_gcc.h>
|
||||
|
||||
// Compiler dependent implementation
|
||||
// We only support one fallback: MSVC, because even on version 2015, it lacks full constexpr support
|
||||
#elif defined(Q_CC_MSVC)
|
||||
# include <QtCore/qatomic_msvc.h>
|
||||
|
||||
// Processor dependent implementation
|
||||
#elif defined(Q_PROCESSOR_ARM_V7) && defined(Q_PROCESSOR_ARM_32)
|
||||
# include "QtCore/qatomic_armv7.h"
|
||||
#elif defined(Q_PROCESSOR_ARM_V6) && defined(Q_PROCESSOR_ARM_32)
|
||||
# include "QtCore/qatomic_armv6.h"
|
||||
#elif defined(Q_PROCESSOR_ARM_V5) && defined(Q_PROCESSOR_ARM_32)
|
||||
# include "QtCore/qatomic_armv5.h"
|
||||
#elif defined(Q_PROCESSOR_IA64)
|
||||
# include "QtCore/qatomic_ia64.h"
|
||||
#elif defined(Q_PROCESSOR_X86)
|
||||
# include <QtCore/qatomic_x86.h>
|
||||
|
||||
// Fallback compiler dependent implementation
|
||||
#elif defined(Q_CC_GNU)
|
||||
# include <QtCore/qatomic_gcc.h>
|
||||
|
||||
// Fallback operating system dependent implementation
|
||||
#elif defined(Q_OS_UNIX)
|
||||
# include <QtCore/qatomic_unix.h>
|
||||
|
||||
// No fallback
|
||||
#else
|
||||
# error "Qt has not been ported to this platform"
|
||||
# error "Qt requires C++11 support"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -1 +0,0 @@
|
||||
include(../../qatomicinteger.pri)
|
@ -2,16 +2,7 @@
|
||||
TYPE = $$basename(_PRO_FILE_PWD_)
|
||||
dn = $$dirname(_PRO_FILE_PWD_)
|
||||
FORCE = $$basename(dn)
|
||||
|
||||
equals(FORCE, no-cxx11) {
|
||||
suffix = NoCxx11_$$TYPE
|
||||
DEFINES += QT_ATOMIC_FORCE_NO_CXX11
|
||||
} else: equals(FORCE, gcc) {
|
||||
suffix = Gcc_$$TYPE
|
||||
DEFINES += QT_ATOMIC_FORCE_GCC
|
||||
} else {
|
||||
suffix = $$TYPE
|
||||
}
|
||||
suffix = $$TYPE
|
||||
|
||||
CONFIG += testcase
|
||||
QT = core testlib
|
||||
|
@ -16,43 +16,3 @@ SUBDIRS=\
|
||||
ulong \
|
||||
ushort \
|
||||
wchar_t \
|
||||
|
||||
|
||||
contains(QT_CONFIG, c++11)|msvc: SUBDIRS +=\
|
||||
no-cxx11/char \
|
||||
no-cxx11/char16_t \
|
||||
no-cxx11/char32_t \
|
||||
no-cxx11/int \
|
||||
no-cxx11/long \
|
||||
no-cxx11/qlonglong \
|
||||
no-cxx11/qptrdiff \
|
||||
no-cxx11/quintptr \
|
||||
no-cxx11/qulonglong \
|
||||
no-cxx11/schar \
|
||||
no-cxx11/short \
|
||||
no-cxx11/uchar \
|
||||
no-cxx11/uint \
|
||||
no-cxx11/ulong \
|
||||
no-cxx11/ushort \
|
||||
no-cxx11/wchar_t \
|
||||
|
||||
|
||||
# The GCC-style atomics only support 32-bit and pointer-sized but add
|
||||
# them all anyway so we ensure the macros are properly defined
|
||||
gcc: SUBDIRS +=\
|
||||
gcc/char \
|
||||
gcc/char16_t \
|
||||
gcc/char32_t \
|
||||
gcc/int \
|
||||
gcc/long \
|
||||
gcc/qlonglong \
|
||||
gcc/qptrdiff \
|
||||
gcc/quintptr \
|
||||
gcc/qulonglong \
|
||||
gcc/schar \
|
||||
gcc/short \
|
||||
gcc/uchar \
|
||||
gcc/uint \
|
||||
gcc/ulong \
|
||||
gcc/ushort \
|
||||
gcc/wchar_t \
|
||||
|
@ -708,8 +708,8 @@ void tst_Moc::oldStyleCasts()
|
||||
proc.closeWriteChannel();
|
||||
|
||||
QVERIFY(proc.waitForFinished());
|
||||
QCOMPARE(proc.exitCode(), 0);
|
||||
QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());
|
||||
QCOMPARE(proc.exitCode(), 0);
|
||||
#else
|
||||
QSKIP("Only tested on linux/gcc");
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user