diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/corelib/arch | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'src/corelib/arch')
58 files changed, 11090 insertions, 0 deletions
diff --git a/src/corelib/arch/alpha/arch.pri b/src/corelib/arch/alpha/arch.pri new file mode 100644 index 0000000..448a531 --- /dev/null +++ b/src/corelib/arch/alpha/arch.pri @@ -0,0 +1,4 @@ +# +# Alpha architecture +# +!*-g++*:SOURCES += $$QT_ARCH_CPP/qatomic_alpha.s diff --git a/src/corelib/arch/alpha/qatomic_alpha.s b/src/corelib/arch/alpha/qatomic_alpha.s new file mode 100644 index 0000000..9363b35 --- /dev/null +++ b/src/corelib/arch/alpha/qatomic_alpha.s @@ -0,0 +1,199 @@ + .set noreorder + .set volatile + .set noat + .arch ev4 + .text + .align 2 + .align 4 + .globl q_atomic_test_and_set_int + .ent q_atomic_test_and_set_int +q_atomic_test_and_set_int: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + cmpeq $0,$17,$0 + beq $0,3f + mov $18,$0 + stl_c $0,0($16) + beq $0,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_test_and_set_int + .align 2 + .align 4 + .globl q_atomic_test_and_set_acquire_int + .ent q_atomic_test_and_set_acquire_int +q_atomic_test_and_set_acquire_int: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + cmpeq $0,$17,$0 + beq $0,3f + mov $18,$0 + stl_c $0,0($16) + beq $0,2f + br 3f +2: br 1b +3: mb + addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_test_and_set_acquire_int + .align 2 + .align 4 + .globl q_atomic_test_and_set_release_int + .ent q_atomic_test_and_set_release_int +q_atomic_test_and_set_release_int: + .frame $30,0,$26,0 + .prologue 0 + mb +1: ldl_l $0,0($16) + cmpeq $0,$17,$0 + beq $0,3f + mov $18,$0 + stl_c $0,0($16) + beq $0,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_test_and_set_release_int + .align 2 + .align 4 + .globl q_atomic_test_and_set_ptr + .ent q_atomic_test_and_set_ptr +q_atomic_test_and_set_ptr: + .frame $30,0,$26,0 + .prologue 0 +1: ldq_l $0,0($16) + cmpeq $0,$17,$0 + beq $0,3f + mov $18,$0 + stq_c $0,0($16) + beq $0,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_test_and_set_ptr + .align 2 + .align 4 + .globl q_atomic_increment + .ent q_atomic_increment +q_atomic_increment: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + addl $0,1,$1 + stl_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + cmpeq $0,$1,$0 + xor $0,1,$0 + ret $31,($26),1 + .end q_atomic_increment + .align 2 + .align 4 + .globl q_atomic_decrement + .ent q_atomic_decrement +q_atomic_decrement: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + subl $0,1,$1 + stl_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + cmpeq $0,1,$0 + xor $0,1,$0 + ret $31,($26),1 + .end q_atomic_decrement + .align 2 + .align 4 + .globl q_atomic_set_int + .ent q_atomic_set_int +q_atomic_set_int: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + mov $17,$1 + stl_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_set_int + .align 2 + .align 4 + .globl q_atomic_set_ptr + .ent q_atomic_set_ptr +q_atomic_set_ptr: + .frame $30,0,$26,0 + .prologue 0 +1: ldq_l $0,0($16) + mov $17,$1 + stq_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: ret $31,($26),1 + .end q_atomic_set_ptr + + .align 2 + .align 4 + .globl q_atomic_fetch_and_add_int + .ent q_atomic_fetch_and_add_int +q_atomic_fetch_and_add_int: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + addl $0,$17,$1 + stl_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_fetch_and_add_int + + .align 2 + .align 4 + .globl q_atomic_fetch_and_add_acquire_int + .ent q_atomic_fetch_and_add_acquire_int +q_atomic_fetch_and_add_acquire_int: + .frame $30,0,$26,0 + .prologue 0 +1: ldl_l $0,0($16) + addl $0,$17,$1 + stl_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: mb + addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_fetch_and_add_acquire_int + + .align 2 + .align 4 + .globl q_atomic_fetch_and_add_release_int + .ent q_atomic_fetch_and_add_release_int +q_atomic_fetch_and_add_release_int: + .frame $30,0,$26,0 + .prologue 0 + mb +1: ldl_l $0,0($16) + addl $0,$17,$1 + stl_c $1,0($16) + beq $1,2f + br 3f +2: br 1b +3: addl $31,$0,$0 + ret $31,($26),1 + .end q_atomic_fetch_and_add_release_int diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri new file mode 100644 index 0000000..20b9227 --- /dev/null +++ b/src/corelib/arch/arch.pri @@ -0,0 +1,26 @@ +win32:HEADERS += arch/qatomic_windows.h \ + arch/qatomic_generic.h + +mac:HEADERS += arch/qatomic_macosx.h \ + arch/qatomic_generic.h + +!wince*:!win32:!mac:HEADERS += arch/qatomic_alpha.h \ + arch/qatomic_avr32.h \ + arch/qatomic_ia64.h \ + arch/qatomic_parisc.h \ + arch/qatomic_sparc.h \ + arch/qatomic_arch.h \ + arch/qatomic_generic.h \ + arch/qatomic_powerpc.h \ + arch/qatomic_arm.h \ + arch/qatomic_armv6.h \ + arch/qatomic_i386.h \ + arch/qatomic_mips.h \ + arch/qatomic_s390.h \ + arch/qatomic_x86_64.h \ + arch/qatomic_sh.h \ + arch/qatomic_sh4a.h + +QT_ARCH_CPP = $$QT_SOURCE_TREE/src/corelib/arch/$$QT_ARCH +DEPENDPATH += $$QT_ARCH_CPP +include($$QT_ARCH_CPP/arch.pri) diff --git a/src/corelib/arch/arm/arch.pri b/src/corelib/arch/arm/arch.pri new file mode 100644 index 0000000..79e4bfc --- /dev/null +++ b/src/corelib/arch/arm/arch.pri @@ -0,0 +1,4 @@ +# +# ARM architecture +# +SOURCES += $$QT_ARCH_CPP/qatomic_arm.cpp diff --git a/src/corelib/arch/arm/qatomic_arm.cpp b/src/corelib/arch/arm/qatomic_arm.cpp new file mode 100644 index 0000000..901c181 --- /dev/null +++ b/src/corelib/arch/arm/qatomic_arm.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qglobal.h> + +#include <unistd.h> +#ifdef _POSIX_PRIORITY_SCHEDULING +# include <sched.h> +#endif +#include <time.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +Q_CORE_EXPORT char q_atomic_lock = 0; + +Q_CORE_EXPORT void qt_atomic_yield(int *count) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING + if((*count)++ < 50) { + sched_yield(); + } else +#endif + { + struct timespec tm; + tm.tv_sec = 0; + tm.tv_nsec = 2000001; + nanosleep(&tm, NULL); + *count = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/corelib/arch/armv6/arch.pri b/src/corelib/arch/armv6/arch.pri new file mode 100644 index 0000000..fd0cce1 --- /dev/null +++ b/src/corelib/arch/armv6/arch.pri @@ -0,0 +1,3 @@ +# +# ARMv6 +# diff --git a/src/corelib/arch/avr32/arch.pri b/src/corelib/arch/avr32/arch.pri new file mode 100644 index 0000000..37f231e --- /dev/null +++ b/src/corelib/arch/avr32/arch.pri @@ -0,0 +1,3 @@ +# +# AVR32 architecture +# diff --git a/src/corelib/arch/bfin/arch.pri b/src/corelib/arch/bfin/arch.pri new file mode 100644 index 0000000..fa198ae --- /dev/null +++ b/src/corelib/arch/bfin/arch.pri @@ -0,0 +1,3 @@ +# +# Blackfin architecture +# diff --git a/src/corelib/arch/generic/arch.pri b/src/corelib/arch/generic/arch.pri new file mode 100644 index 0000000..8fee63f --- /dev/null +++ b/src/corelib/arch/generic/arch.pri @@ -0,0 +1,6 @@ +# +# 'generic' architecture +# + +unix:SOURCES += qatomic_generic_unix.cpp +win32:SOURCES += qatomic_generic_windows.cpp diff --git a/src/corelib/arch/generic/qatomic_generic_unix.cpp b/src/corelib/arch/generic/qatomic_generic_unix.cpp new file mode 100644 index 0000000..15918be --- /dev/null +++ b/src/corelib/arch/generic/qatomic_generic_unix.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" + +#include <QtCore/qatomic.h> + +static pthread_mutex_t qAtomicMutex = PTHREAD_MUTEX_INITIALIZER; + +Q_CORE_EXPORT +bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue) +{ + 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 +int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue) +{ + int returnValue; + pthread_mutex_lock(&qAtomicMutex); + returnValue = *_q_value; + *_q_value = newValue; + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} + +Q_CORE_EXPORT +int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd) +{ + int returnValue; + pthread_mutex_lock(&qAtomicMutex); + returnValue = *_q_value; + *_q_value += valueToAdd; + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} + +Q_CORE_EXPORT +bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value, + void *expectedValue, + void *newValue) +{ + 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 +void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue) +{ + void *returnValue; + pthread_mutex_lock(&qAtomicMutex); + returnValue = *_q_value; + *_q_value = newValue; + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} + +Q_CORE_EXPORT +void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd) +{ + void *returnValue; + pthread_mutex_lock(&qAtomicMutex); + returnValue = *_q_value; + *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd; + pthread_mutex_unlock(&qAtomicMutex); + return returnValue; +} diff --git a/src/corelib/arch/generic/qatomic_generic_windows.cpp b/src/corelib/arch/generic/qatomic_generic_windows.cpp new file mode 100644 index 0000000..13ef767 --- /dev/null +++ b/src/corelib/arch/generic/qatomic_generic_windows.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" + +#include <QtCore/qatomic.h> + + +class QCriticalSection +{ +public: + QCriticalSection() { InitializeCriticalSection(§ion); } + ~QCriticalSection() { DeleteCriticalSection(§ion); } + void lock() { EnterCriticalSection(§ion); } + void unlock() { LeaveCriticalSection(§ion); } + +private: + CRITICAL_SECTION section; +}; + +static QCriticalSection qAtomicCriticalSection; + +Q_CORE_EXPORT +bool QBasicAtomicInt_testAndSetOrdered(volatile int *_q_value, int expectedValue, int newValue) +{ + bool returnValue = false; + qAtomicCriticalSection.lock(); + if (*_q_value == expectedValue) { + *_q_value = newValue; + returnValue = true; + } + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *_q_value, int newValue) +{ + int returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value = newValue; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +int QBasicAtomicInt_fetchAndAddOrdered(volatile int *_q_value, int valueToAdd) +{ + int returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value += valueToAdd; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *_q_value, + void *expectedValue, + void *newValue) +{ + bool returnValue = false; + qAtomicCriticalSection.lock(); + if (*_q_value == expectedValue) { + *_q_value = newValue; + returnValue = true; + } + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *_q_value, void *newValue) +{ + void *returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value = newValue; + qAtomicCriticalSection.unlock(); + return returnValue; +} + +Q_CORE_EXPORT +void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *_q_value, qptrdiff valueToAdd) +{ + void *returnValue; + qAtomicCriticalSection.lock(); + returnValue = *_q_value; + *_q_value = reinterpret_cast<char *>(returnValue) + valueToAdd; + qAtomicCriticalSection.unlock(); + return returnValue; +} diff --git a/src/corelib/arch/i386/arch.pri b/src/corelib/arch/i386/arch.pri new file mode 100644 index 0000000..3101dae --- /dev/null +++ b/src/corelib/arch/i386/arch.pri @@ -0,0 +1,4 @@ +# +# i386 architecture +# +!*-g++*:!*-icc*:SOURCES += $$QT_ARCH_CPP/qatomic_i386.s diff --git a/src/corelib/arch/i386/qatomic_i386.s b/src/corelib/arch/i386/qatomic_i386.s new file mode 100644 index 0000000..08158f9 --- /dev/null +++ b/src/corelib/arch/i386/qatomic_i386.s @@ -0,0 +1,103 @@ + .text + + .align 4,0x90 + .globl q_atomic_test_and_set_int +q_atomic_test_and_set_int: + movl 4(%esp),%ecx + movl 8(%esp),%eax + movl 12(%esp),%edx + lock + cmpxchgl %edx,(%ecx) + mov $0,%eax + sete %al + ret + .align 4,0x90 + .type q_atomic_test_and_set_int,@function + .size q_atomic_test_and_set_int,.-q_atomic_test_and_set_int + + .align 4,0x90 + .globl q_atomic_test_and_set_ptr +q_atomic_test_and_set_ptr: + movl 4(%esp),%ecx + movl 8(%esp),%eax + movl 12(%esp),%edx + lock + cmpxchgl %edx,(%ecx) + mov $0,%eax + sete %al + ret + .align 4,0x90 + .type q_atomic_test_and_set_ptr,@function + .size q_atomic_test_and_set_ptr,.-q_atomic_test_and_set_ptr + + .align 4,0x90 + .globl q_atomic_increment +q_atomic_increment: + movl 4(%esp), %ecx + lock + incl (%ecx) + mov $0,%eax + setne %al + ret + .align 4,0x90 + .type q_atomic_increment,@function + .size q_atomic_increment,.-q_atomic_increment + + .align 4,0x90 + .globl q_atomic_decrement +q_atomic_decrement: + movl 4(%esp), %ecx + lock + decl (%ecx) + mov $0,%eax + setne %al + ret + .align 4,0x90 + .type q_atomic_decrement,@function + .size q_atomic_decrement,.-q_atomic_decrement + + .align 4,0x90 + .globl q_atomic_set_int +q_atomic_set_int: + mov 4(%esp),%ecx + mov 8(%esp),%eax + xchgl %eax,(%ecx) + ret + .align 4,0x90 + .type q_atomic_set_int,@function + .size q_atomic_set_int,.-q_atomic_set_int + + .align 4,0x90 + .globl q_atomic_set_ptr +q_atomic_set_ptr: + mov 4(%esp),%ecx + mov 8(%esp),%eax + xchgl %eax,(%ecx) + ret + .align 4,0x90 + .type q_atomic_set_ptr,@function + .size q_atomic_set_ptr,.-q_atomic_set_ptr + + .align 4,0x90 + .globl q_atomic_fetch_and_add_int +q_atomic_fetch_and_add_int: + mov 4(%esp),%ecx + mov 8(%esp),%eax + lock + xadd %eax,(%ecx) + ret + .align 4,0x90 + .type q_atomic_fetch_and_add_int,@function + .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int + + .align 4,0x90 + .globl q_atomic_fetch_and_add_ptr +q_atomic_fetch_and_add_ptr: + mov 4(%esp),%ecx + mov 8(%esp),%eax + lock + xadd %eax,(%ecx) + ret + .align 4,0x90 + .type q_atomic_fetch_and_add_ptr,@function + .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr diff --git a/src/corelib/arch/ia64/arch.pri b/src/corelib/arch/ia64/arch.pri new file mode 100644 index 0000000..63afa96 --- /dev/null +++ b/src/corelib/arch/ia64/arch.pri @@ -0,0 +1,4 @@ +# +# Intel Itanium architecture +# +!*-g++:!*-icc:!hpuxi-acc-*:SOURCES += $$QT_ARCH_CPP/qatomic_ia64.s diff --git a/src/corelib/arch/ia64/qatomic_ia64.s b/src/corelib/arch/ia64/qatomic_ia64.s new file mode 100644 index 0000000..6b8a204 --- /dev/null +++ b/src/corelib/arch/ia64/qatomic_ia64.s @@ -0,0 +1,34 @@ + .pred.safe_across_calls p1-p5,p16-p63 +.text + .align 16 + .global q_atomic_test_and_set_int# + .proc q_atomic_test_and_set_int# +q_atomic_test_and_set_int: + .prologue + .body + mov ar.ccv=r33 + ;; + cmpxchg4.acq r34=[r32],r34,ar.ccv + ;; + cmp4.eq p6, p7 = r33, r34 + ;; + (p6) addl r8 = 1, r0 + (p7) mov r8 = r0 + br.ret.sptk.many b0 + .endp q_atomic_test_and_set_int# + .align 16 + .global q_atomic_test_and_set_ptr# + .proc q_atomic_test_and_set_ptr# +q_atomic_test_and_set_ptr: + .prologue + .body + mov ar.ccv=r33 + ;; + cmpxchg8.acq r34=[r32],r34,ar.ccv + ;; + cmp.eq p6, p7 = r33, r34 + ;; + (p6) addl r8 = 1, r0 + (p7) mov r8 = r0 + br.ret.sptk.many b0 + .endp q_atomic_test_and_set_ptr# diff --git a/src/corelib/arch/macosx/arch.pri b/src/corelib/arch/macosx/arch.pri new file mode 100644 index 0000000..e42a962 --- /dev/null +++ b/src/corelib/arch/macosx/arch.pri @@ -0,0 +1,7 @@ +# +# Mac OS X architecture +# +!*-icc*:!*-g++* { + contains($$list($$system(uname -m)), .*86):SOURCES += $$QT_ARCH_CPP/../i386/qatomic.s + else:SOURCES += $$QT_ARCH_CPP/../powerpc/qatomic32.s +} diff --git a/src/corelib/arch/macosx/qatomic32_ppc.s b/src/corelib/arch/macosx/qatomic32_ppc.s new file mode 100644 index 0000000..13fff67 --- /dev/null +++ b/src/corelib/arch/macosx/qatomic32_ppc.s @@ -0,0 +1,129 @@ + .section __TEXT,__text,regular,pure_instructions + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .section __TEXT,__text,regular,pure_instructions + .align 2 + .align 2 + .globl _q_atomic_test_and_set_int + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_test_and_set_int: + lwarx r6,0,r3 + cmpw r6,r4 + bne- $+20 + stwcx. r5,0,r3 + bne- $-16 + addi r3,0,1 + blr + addi r3,0,0 + blr + + .align 2 + .globl _q_atomic_test_and_set_acquire_int + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_test_and_set_acquire_int: + lwarx r6,0,r3 + cmpw r6,r4 + bne- $+20 + stwcx. r5,0,r3 + bne- $-16 + addi r3,0,1 + b $+8 + addi r3,0,0 + eieio + blr + + .align 2 + .globl _q_atomic_test_and_set_release_int + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_test_and_set_release_int: + eieio + lwarx r6,0,r3 + cmpw r6,r4 + bne- $+20 + stwcx. r5,0,r3 + bne- $-16 + addi r3,0,1 + blr + addi r3,0,0 + blr + + .align 2 + .globl _q_atomic_test_and_set_ptr + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_test_and_set_ptr: + lwarx r6,0,r3 + cmpw r6,r4 + bne- $+20 + stwcx. r5,0,r3 + bne- $-16 + addi r3,0,1 + blr + addi r3,0,0 + blr + + .align 2 + .globl _q_atomic_increment + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_increment: + lwarx r4,0,r3 + addi r4,r4,1 + stwcx. r4,0,r3 + bne- $-12 + mr r3,r4 + blr + + .align 2 + .globl _q_atomic_decrement + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_decrement: + lwarx r4,0,r3 + subi r4,r4,1 + stwcx. r4,0,r3 + bne- $-12 + mr r3,r4 + blr + + .align 2 + .globl _q_atomic_set_int + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_set_int: + lwarx r5,0,r3 + stwcx. r4,0,r3 + bne- $-8 + mr r3,r5 + blr + + .align 2 + .globl _q_atomic_set_ptr + .section __TEXT,__text,regular,pure_instructions + .align 2 +_q_atomic_set_ptr: + lwarx r5,0,r3 + stwcx. r4,0,r3 + bne- $-8 + mr r3,r5 + blr + +.globl q_atomic_test_and_set_int.eh + q_atomic_test_and_set_int.eh = 0 +.globl q_atomic_test_and_set_ptr.eh + q_atomic_test_and_set_ptr.eh = 0 +.globl q_atomic_increment.eh + q_atomic_increment.eh = 0 +.globl q_atomic_decrement.eh + q_atomic_decrement.eh = 0 +.globl q_atomic_set_int.eh + q_atomic_set_int.eh = 0 +.globl q_atomic_set_ptr.eh + q_atomic_set_ptr.eh = 0 +.data +.constructor +.data +.destructor +.align 1 diff --git a/src/corelib/arch/mips/arch.pri b/src/corelib/arch/mips/arch.pri new file mode 100644 index 0000000..296c845 --- /dev/null +++ b/src/corelib/arch/mips/arch.pri @@ -0,0 +1,8 @@ +# +# MIPS 3/4 architecture +# + +# note: even though we use inline assembler with gcc, we always +# include the compiled version to keep binary compatibility +*-64:SOURCES += $$QT_ARCH_CPP/qatomic_mips64.s +else:SOURCES += $$QT_ARCH_CPP/qatomic_mips32.s diff --git a/src/corelib/arch/mips/qatomic_mips32.s b/src/corelib/arch/mips/qatomic_mips32.s new file mode 100644 index 0000000..e7a449b --- /dev/null +++ b/src/corelib/arch/mips/qatomic_mips32.s @@ -0,0 +1,110 @@ + .set nobopt + .set noreorder + .option pic2 + .text + + .globl q_atomic_test_and_set_int + .ent q_atomic_test_and_set_int + .set mips2 +q_atomic_test_and_set_int: +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .set mips0 + .end q_atomic_test_and_set_int + + .globl q_atomic_test_and_set_acquire_int + .ent q_atomic_test_and_set_acquire_int + .set mips2 +q_atomic_test_and_set_acquire_int: +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: sync + jr $31 + move $2,$0 + .set mips0 + .end q_atomic_test_and_set_acquire_int + + .globl q_atomic_test_and_set_release_int + .ent q_atomic_test_and_set_release_int + .set mips2 +q_atomic_test_and_set_release_int: + sync +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .set mips0 + .end q_atomic_test_and_set_release_int + + .globl q_atomic_test_and_set_ptr + .ent q_atomic_test_and_set_ptr + .set mips2 +q_atomic_test_and_set_ptr: +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .set mips0 + .end q_atomic_test_and_set_ptr + + .globl q_atomic_test_and_set_acquire_ptr + .ent q_atomic_test_and_set_acquire_ptr + .set mips2 +q_atomic_test_and_set_acquire_ptr: +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: sync + jr $31 + move $2,$0 + .set mips0 + .end q_atomic_test_and_set_acquire_ptr + + .globl q_atomic_test_and_set_release_ptr + .ent q_atomic_test_and_set_release_ptr + .set mips2 +q_atomic_test_and_set_release_ptr: + sync +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .set mips0 + .end q_atomic_test_and_set_release_ptr diff --git a/src/corelib/arch/mips/qatomic_mips64.s b/src/corelib/arch/mips/qatomic_mips64.s new file mode 100644 index 0000000..d2bd8fe --- /dev/null +++ b/src/corelib/arch/mips/qatomic_mips64.s @@ -0,0 +1,98 @@ + .set nobopt + .set noreorder + .option pic2 + .text + + .globl q_atomic_test_and_set_int + .ent q_atomic_test_and_set_int +q_atomic_test_and_set_int: +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .end q_atomic_test_and_set_int + + .globl q_atomic_test_and_set_acquire_int + .ent q_atomic_test_and_set_acquire_int +q_atomic_test_and_set_acquire_int: +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: sync + jr $31 + move $2,$0 + .end q_atomic_test_and_set_acquire_int + + .globl q_atomic_test_and_set_release_int + .ent q_atomic_test_and_set_release_int +q_atomic_test_and_set_release_int: + sync +1: ll $8,0($4) + bne $8,$5,2f + move $2,$6 + sc $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .end q_atomic_test_and_set_release_int + + .globl q_atomic_test_and_set_ptr + .ent q_atomic_test_and_set_ptr +q_atomic_test_and_set_ptr: +1: lld $8,0($4) + bne $8,$5,2f + move $2,$6 + scd $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .end q_atomic_test_and_set_ptr + + .globl q_atomic_test_and_set_acquire_ptr + .ent q_atomic_test_and_set_acquire_ptr +q_atomic_test_and_set_acquire_ptr: +1: lld $8,0($4) + bne $8,$5,2f + move $2,$6 + scd $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: sync + jr $31 + move $2,$0 + .end q_atomic_test_and_set_acquire_ptr + + .globl q_atomic_test_and_set_release_ptr + .ent q_atomic_test_and_set_release_ptr +q_atomic_test_and_set_release_ptr: + sync +1: lld $8,0($4) + bne $8,$5,2f + move $2,$6 + scd $2,0($4) + beqz $2,1b + nop + jr $31 + nop +2: jr $31 + move $2,$0 + .end q_atomic_test_and_set_release_ptr diff --git a/src/corelib/arch/parisc/arch.pri b/src/corelib/arch/parisc/arch.pri new file mode 100644 index 0000000..fab2897 --- /dev/null +++ b/src/corelib/arch/parisc/arch.pri @@ -0,0 +1,5 @@ +# +# HP PA-RISC architecture +# +SOURCES += $$QT_ARCH_CPP/q_ldcw.s \ + $$QT_ARCH_CPP/qatomic_parisc.cpp diff --git a/src/corelib/arch/parisc/q_ldcw.s b/src/corelib/arch/parisc/q_ldcw.s new file mode 100644 index 0000000..f901ad9 --- /dev/null +++ b/src/corelib/arch/parisc/q_ldcw.s @@ -0,0 +1,22 @@ + .SPACE $PRIVATE$ + .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 + .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82 + .SPACE $TEXT$ + .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 + .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY + .IMPORT $global$,DATA + .IMPORT $$dyncall,MILLICODE + .SPACE $TEXT$ + .SUBSPA $CODE$ + + .align 4 + .EXPORT q_ldcw,ENTRY,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR +q_ldcw + .PROC + .CALLINFO FRAME=0,CALLS,SAVE_RP + .ENTRY + ldcw 0(%r26),%r1 + bv %r0(%r2) + copy %r1,%r28 + .EXIT + .PROCEND diff --git a/src/corelib/arch/parisc/qatomic_parisc.cpp b/src/corelib/arch/parisc/qatomic_parisc.cpp new file mode 100644 index 0000000..580838e --- /dev/null +++ b/src/corelib/arch/parisc/qatomic_parisc.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qglobal.h> +#include <QtCore/qhash.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +#define UNLOCKED {-1,-1,-1,-1} +#define UNLOCKED2 UNLOCKED,UNLOCKED +#define UNLOCKED4 UNLOCKED2,UNLOCKED2 +#define UNLOCKED8 UNLOCKED4,UNLOCKED4 +#define UNLOCKED16 UNLOCKED8,UNLOCKED8 +#define UNLOCKED32 UNLOCKED16,UNLOCKED16 +#define UNLOCKED64 UNLOCKED32,UNLOCKED32 +#define UNLOCKED128 UNLOCKED64,UNLOCKED64 +#define UNLOCKED256 UNLOCKED128,UNLOCKED128 + +// use a 4k page for locks +static int locks[256][4] = { UNLOCKED256 }; + +int *getLock(volatile void *addr) +{ return locks[qHash(const_cast<void *>(addr)) % 256]; } + +static int *align16(int *lock) +{ + ulong off = (((ulong) lock) % 16); + return off ? (int *)(ulong(lock) + 16 - off) : lock; +} + +extern "C" { + + int q_ldcw(volatile int *addr); + + void q_atomic_lock(int *lock) + { + // ldcw requires a 16-byte aligned address + volatile int *x = align16(lock); + while (q_ldcw(x) == 0) + ; + } + + void q_atomic_unlock(int *lock) + { lock[0] = lock[1] = lock[2] = lock[3] = -1; } +} + + +QT_END_NAMESPACE diff --git a/src/corelib/arch/powerpc/arch.pri b/src/corelib/arch/powerpc/arch.pri new file mode 100644 index 0000000..1989ac7 --- /dev/null +++ b/src/corelib/arch/powerpc/arch.pri @@ -0,0 +1,10 @@ +# +# PowerPC architecture +# +!*-g++* { + *-64 { + SOURCES += $$QT_ARCH_CPP/qatomic64.s + } else { + SOURCES += $$QT_ARCH_CPP/qatomic32.s + } +} diff --git a/src/corelib/arch/powerpc/qatomic32.s b/src/corelib/arch/powerpc/qatomic32.s new file mode 100644 index 0000000..811ba84 --- /dev/null +++ b/src/corelib/arch/powerpc/qatomic32.s @@ -0,0 +1,485 @@ + .machine "ppc" + .toc + .csect .text[PR] + + .align 2 + .globl q_atomic_test_and_set_int + .globl .q_atomic_test_and_set_int + .csect q_atomic_test_and_set_int[DS],3 +q_atomic_test_and_set_int: + .long .q_atomic_test_and_set_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int + .short 25 + .byte "q_atomic_test_and_set_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_int + .globl .q_atomic_test_and_set_acquire_int + .csect q_atomic_test_and_set_acquire_int[DS],3 +q_atomic_test_and_set_acquire_int: + .long .q_atomic_test_and_set_acquire_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_acquire_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int + .short 33 + .byte "q_atomic_test_and_set_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_int + .globl .q_atomic_test_and_set_release_int + .csect q_atomic_test_and_set_release_int[DS],3 +q_atomic_test_and_set_release_int: + .long .q_atomic_test_and_set_release_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_release_int: + eieio + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int + .short 33 + .byte "q_atomic_test_and_set_release_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_ptr + .globl .q_atomic_test_and_set_ptr + .csect q_atomic_test_and_set_ptr[DS],3 +q_atomic_test_and_set_ptr: + .long .q_atomic_test_and_set_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr + .short 25 + .byte "q_atomic_test_and_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_ptr + .globl .q_atomic_test_and_set_acquire_ptr + .csect q_atomic_test_and_set_acquire_ptr[DS],3 +q_atomic_test_and_set_acquire_ptr: + .long .q_atomic_test_and_set_acquire_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_acquire_ptr: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr + .short 25 + .byte "q_atomic_test_and_set_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_ptr + .globl .q_atomic_test_and_set_release_ptr + .csect q_atomic_test_and_set_release_ptr[DS],3 +q_atomic_test_and_set_release_ptr: + .long .q_atomic_test_and_set_release_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_release_ptr: + eieio + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr + .short 33 + .byte "q_atomic_test_and_set_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_increment + .globl .q_atomic_increment + .csect q_atomic_increment[DS],3 +q_atomic_increment: + .long .q_atomic_increment,TOC[tc0],0 + .csect .text[PR] +.q_atomic_increment: + lwarx 4,0,3 + addi 4,4,1 + stwcx. 4,0,3 + bne- $-12 + mr 3,4 + blr +LT..q_atomic_increment: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_increment-.q_atomic_increment + .short 18 + .byte "q_atomic_increment" + .align 2 + + .align 2 + .globl q_atomic_decrement + .globl .q_atomic_decrement + .csect q_atomic_decrement[DS],3 +q_atomic_decrement: + .long .q_atomic_decrement,TOC[tc0],0 + .csect .text[PR] +.q_atomic_decrement: + lwarx 4,0,3 + subi 4,4,1 + stwcx. 4,0,3 + bne- $-12 + mr 3,4 + blr +LT..q_atomic_decrement: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_decrement-.q_atomic_decrement + .short 18 + .byte "q_atomic_decrement" + .align 2 + + .align 2 + .globl q_atomic_set_int + .globl .q_atomic_set_int + .csect q_atomic_set_int[DS],3 +q_atomic_set_int: + .long .q_atomic_set_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_set_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_int-.q_atomic_set_int + .short 16 + .byte "q_atomic_set_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_int + .globl .q_atomic_fetch_and_store_acquire_int + .csect q_atomic_fetch_and_store_acquire_int[DS],3 +q_atomic_fetch_and_store_acquire_int: + .long .q_atomic_fetch_and_store_acquire_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_acquire_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int + .short 16 + .byte "q_atomic_fetch_and_store_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_int + .globl .q_atomic_fetch_and_store_release_int + .csect q_atomic_fetch_and_store_release_int[DS],3 +q_atomic_fetch_and_store_release_int: + .long .q_atomic_fetch_and_store_release_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_release_int: + eieio + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int + .short 16 + .byte "q_atomic_fetch_and_store_release_int" + .align 2 + + .align 2 + .globl q_atomic_set_ptr + .globl .q_atomic_set_ptr + .csect q_atomic_set_ptr[DS],3 +q_atomic_set_ptr: + .long .q_atomic_set_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_set_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_ptr-.q_atomic_set_ptr + .short 16 + .byte "q_atomic_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_ptr + .globl .q_atomic_fetch_and_store_acquire_ptr + .csect q_atomic_fetch_and_store_acquire_ptr[DS],3 +q_atomic_fetch_and_store_acquire_ptr: + .long .q_atomic_fetch_and_store_acquire_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_acquire_ptr: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr + .short 16 + .byte "q_atomic_fetch_and_store_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_ptr + .globl .q_atomic_fetch_and_store_release_ptr + .csect q_atomic_fetch_and_store_release_ptr[DS],3 +q_atomic_fetch_and_store_release_ptr: + .long .q_atomic_fetch_and_store_release_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_release_ptr: + eieio + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr + .short 16 + .byte "q_atomic_fetch_and_store_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_int + .globl .q_atomic_fetch_and_add_int + .csect q_atomic_fetch_and_add_int[DS],3 +q_atomic_fetch_and_add_int: + .long .q_atomic_fetch_and_add_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int + .short 18 + .byte "q_atomic_fetch_and_add_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_int + .globl .q_atomic_fetch_and_add_acquire_int + .csect q_atomic_fetch_and_add_acquire_int[DS],3 +q_atomic_fetch_and_add_acquire_int: + .long .q_atomic_fetch_and_add_acquire_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_acquire_int: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int + .short 18 + .byte "q_atomic_fetch_and_add_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_int + .globl .q_atomic_fetch_and_add_release_int + .csect q_atomic_fetch_and_add_release_int[DS],3 +q_atomic_fetch_and_add_release_int: + .long .q_atomic_fetch_and_add_release_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_release_int: + eieio + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int + .short 34 + .byte "q_atomic_fetch_and_add_release_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_ptr + .globl .q_atomic_fetch_and_add_ptr + .csect q_atomic_fetch_and_add_ptr[DS],3 +q_atomic_fetch_and_add_ptr: + .long .q_atomic_fetch_and_add_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr + .short 26 + .byte "q_atomic_fetch_and_add_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_ptr + .globl .q_atomic_fetch_and_add_acquire_ptr + .csect q_atomic_fetch_and_add_acquire_ptr[DS],3 +q_atomic_fetch_and_add_acquire_ptr: + .long .q_atomic_fetch_and_add_acquire_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_acquire_ptr: + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr + .short 34 + .byte "q_atomic_fetch_and_add_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_ptr + .globl .q_atomic_fetch_and_add_release_ptr + .csect q_atomic_fetch_and_add_release_ptr[DS],3 +q_atomic_fetch_and_add_release_ptr: + .long .q_atomic_fetch_and_add_release_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_release_ptr: + eieio + lwarx 5,0,3 + add 6,4,5 + stwcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr + .short 34 + .byte "q_atomic_fetch_and_add_release_ptr" + .align 2 + +_section_.text: + .csect .data[RW],3 + .long _section_.text diff --git a/src/corelib/arch/powerpc/qatomic64.s b/src/corelib/arch/powerpc/qatomic64.s new file mode 100644 index 0000000..88c2bbd --- /dev/null +++ b/src/corelib/arch/powerpc/qatomic64.s @@ -0,0 +1,493 @@ + .machine "ppc64" + .toc + .csect .text[PR] + + .align 2 + .globl q_atomic_test_and_set_int + .globl .q_atomic_test_and_set_int + .csect q_atomic_test_and_set_int[DS],3 +q_atomic_test_and_set_int: + .llong .q_atomic_test_and_set_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + extsw 3,3 + blr +LT..q_atomic_test_and_set_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_int-.q_atomic_test_and_set_int + .short 25 + .byte "q_atomic_test_and_set_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_int + .globl .q_atomic_test_and_set_acquire_int + .csect q_atomic_test_and_set_acquire_int[DS],3 +q_atomic_test_and_set_acquire_int: + .llong .q_atomic_test_and_set_acquire_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_acquire_int: + lwarx 6,0,3 + xor. 6,6,4 + bne $+16 + stwcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + extsw 3,3 + blr +LT..q_atomic_test_and_set_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_int-.q_atomic_test_and_set_acquire_int + .short 33 + .byte "q_atomic_test_and_set_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_int + .globl .q_atomic_test_and_set_release_int + .csect q_atomic_test_and_set_release_int[DS],3 +q_atomic_test_and_set_release_int: + .llong .q_atomic_test_and_set_release_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_release_int: + eieio + lwarx 6,0,3 + xor. 6,6,4 + bne $+12 + stwcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + extsw 3,3 + blr +LT..q_atomic_test_and_set_release_int: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_int-.q_atomic_test_and_set_release_int + .short 33 + .byte "q_atomic_test_and_set_release_int" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_ptr + .globl .q_atomic_test_and_set_ptr + .csect q_atomic_test_and_set_ptr[DS],3 +q_atomic_test_and_set_ptr: + .llong .q_atomic_test_and_set_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_ptr: + ldarx 6,0,3 + xor. 6,6,4 + bne $+12 + stdcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_ptr-.q_atomic_test_and_set_ptr + .short 25 + .byte "q_atomic_test_and_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_acquire_ptr + .globl .q_atomic_test_and_set_acquire_ptr + .csect q_atomic_test_and_set_acquire_ptr[DS],3 +q_atomic_test_and_set_acquire_ptr: + .llong .q_atomic_test_and_set_acquire_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_acquire_ptr: + ldarx 6,0,3 + xor. 6,6,4 + bne $+16 + stdcx. 5,0,3 + bne- $-16 + isync + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_acquire_ptr-.q_atomic_test_and_set_acquire_ptr + .short 33 + .byte "q_atomic_test_and_set_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_test_and_set_release_ptr + .globl .q_atomic_test_and_set_release_ptr + .csect q_atomic_test_and_set_release_ptr[DS],3 +q_atomic_test_and_set_release_ptr: + .llong .q_atomic_test_and_set_release_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_test_and_set_release_ptr: + eieio + ldarx 6,0,3 + xor. 6,6,4 + bne $+12 + stdcx. 5,0,3 + bne- $-16 + subfic 3,6,0 + adde 3,3,6 + blr +LT..q_atomic_test_and_set_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,3,0 + .long 0 + .long LT..q_atomic_test_and_set_release_ptr-.q_atomic_test_and_set_release_ptr + .short 33 + .byte "q_atomic_test_and_set_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_increment + .globl .q_atomic_increment + .csect q_atomic_increment[DS],3 +q_atomic_increment: + .llong .q_atomic_increment,TOC[tc0],0 + .csect .text[PR] +.q_atomic_increment: + lwarx 4,0,3 + addi 5,4,1 + extsw 4,5 + stwcx. 4,0,3 + bne- $-16 + mr 3,4 + blr +LT..q_atomic_increment: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_increment-.q_atomic_increment + .short 18 + .byte "q_atomic_increment" + .align 2 + + .align 2 + .globl q_atomic_decrement + .globl .q_atomic_decrement + .csect q_atomic_decrement[DS],3 +q_atomic_decrement: + .llong .q_atomic_decrement,TOC[tc0],0 + .csect .text[PR] +.q_atomic_decrement: + lwarx 4,0,3 + subi 5,4,1 + extsw 4,5 + stwcx. 4,0,3 + bne- $-16 + mr 3,4 + blr +LT..q_atomic_decrement: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_decrement-.q_atomic_decrement + .short 18 + .byte "q_atomic_decrement" + .align 2 + + .align 2 + .globl q_atomic_set_int + .globl .q_atomic_set_int + .csect q_atomic_set_int[DS],3 +q_atomic_set_int: + .llong .q_atomic_set_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_set_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + extsw 3,5 + blr +LT..q_atomic_set_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_int-.q_atomic_set_int + .short 16 + .byte "q_atomic_set_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_int + .globl .q_atomic_fetch_and_store_acquire_int + .csect q_atomic_fetch_and_store_acquire_int[DS],3 +q_atomic_fetch_and_store_acquire_int: + .llong .q_atomic_fetch_and_store_acquire_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_acquire_int: + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + isync + extsw 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_int-.q_atomic_fetch_and_store_acquire_int + .short 36 + .byte "q_atomic_fetch_and_store_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_int + .globl .q_atomic_fetch_and_store_release_int + .csect q_atomic_fetch_and_store_release_int[DS],3 +q_atomic_fetch_and_store_release_int: + .llong .q_atomic_fetch_and_store_release_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_release_int: + eieio + lwarx 5,0,3 + stwcx. 4,0,3 + bne- $-8 + extsw 3,5 + blr +LT..q_atomic_fetch_and_store_release_int: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_int-.q_atomic_fetch_and_store_release_int + .short 36 + .byte "q_atomic_fetch_and_store_release_int" + .align 2 + + .align 2 + .globl q_atomic_set_ptr + .globl .q_atomic_set_ptr + .csect q_atomic_set_ptr[DS],3 +q_atomic_set_ptr: + .llong .q_atomic_set_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_set_ptr: + ldarx 5,0,3 + stdcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_set_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_set_ptr-.q_atomic_set_ptr + .short 16 + .byte "q_atomic_set_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_acquire_ptr + .globl .q_atomic_fetch_and_store_acquire_ptr + .csect q_atomic_fetch_and_store_acquire_ptr[DS],3 +q_atomic_fetch_and_store_acquire_ptr: + .llong .q_atomic_fetch_and_store_acquire_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_acquire_ptr: + ldarx 5,0,3 + stdcx. 4,0,3 + bne- $-8 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_store_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_acquire_ptr-.q_atomic_fetch_and_store_acquire_ptr + .short 36 + .byte "q_atomic_fetch_and_store_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_store_release_ptr + .globl .q_atomic_fetch_and_store_release_ptr + .csect q_atomic_fetch_and_store_release_ptr[DS],3 +q_atomic_fetch_and_store_release_ptr: + .llong .q_atomic_fetch_and_store_release_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_store_release_ptr: + eieio + ldarx 5,0,3 + stdcx. 4,0,3 + bne- $-8 + mr 3,5 + blr +LT..q_atomic_fetch_and_store_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,2,0 + .long 0 + .long LT..q_atomic_fetch_and_store_release_ptr-.q_atomic_fetch_and_store_release_ptr + .short 36 + .byte "q_atomic_fetch_and_store_release_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_int + .globl .q_atomic_fetch_and_add_int + .csect q_atomic_fetch_and_add_int[DS],3 +q_atomic_fetch_and_add_int: + .llong .q_atomic_fetch_and_add_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_int: + lwarx 5,0,3 + add 6,4,5 + extsw 7,6 + stwcx. 7,0,3 + bne- $-16 + extsw 3,5 + blr +LT..q_atomic_fetch_and_add_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_int-.q_atomic_fetch_and_add_int + .short 26 + .byte "q_atomic_fetch_and_add_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_int + .globl .q_atomic_fetch_and_add_acquire_int + .csect q_atomic_fetch_and_add_acquire_int[DS],3 +q_atomic_fetch_and_add_acquire_int: + .llong .q_atomic_fetch_and_add_acquire_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_acquire_int: + lwarx 5,0,3 + add 6,4,5 + extsw 7,6 + stwcx. 7,0,3 + bne- $-16 + isync + extsw 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_int-.q_atomic_fetch_and_add_acquire_int + .short 34 + .byte "q_atomic_fetch_and_add_acquire_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_int + .globl .q_atomic_fetch_and_add_release_int + .csect q_atomic_fetch_and_add_release_int[DS],3 +q_atomic_fetch_and_add_release_int: + .llong .q_atomic_fetch_and_add_release_int,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_release_int: + eieio + lwarx 5,0,3 + add 6,4,5 + extsw 7,6 + stwcx. 7,0,3 + bne- $-16 + extsw 3,5 + blr +LT..q_atomic_fetch_and_add_release_int: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_int-.q_atomic_fetch_and_add_release_int + .short 34 + .byte "q_atomic_fetch_and_add_release_int" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_ptr + .globl .q_atomic_fetch_and_add_ptr + .csect q_atomic_fetch_and_add_ptr[DS],3 +q_atomic_fetch_and_add_ptr: + .llong .q_atomic_fetch_and_add_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_ptr: + ldarx 5,0,3 + add 6,4,5 + stdcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_ptr-.q_atomic_fetch_and_add_ptr + .short 26 + .byte "q_atomic_fetch_and_add_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_acquire_ptr + .globl .q_atomic_fetch_and_add_acquire_ptr + .csect q_atomic_fetch_and_add_acquire_ptr[DS],3 +q_atomic_fetch_and_add_acquire_ptr: + .llong .q_atomic_fetch_and_add_acquire_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_acquire_ptr: + ldarx 5,0,3 + add 6,4,5 + stdcx. 6,0,3 + bne- $-12 + isync + mr 3,5 + blr +LT..q_atomic_fetch_and_add_acquire_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_acquire_ptr-.q_atomic_fetch_and_add_acquire_ptr + .short 34 + .byte "q_atomic_fetch_and_add_acquire_ptr" + .align 2 + + .align 2 + .globl q_atomic_fetch_and_add_release_ptr + .globl .q_atomic_fetch_and_add_release_ptr + .csect q_atomic_fetch_and_add_release_ptr[DS],3 +q_atomic_fetch_and_add_release_ptr: + .llong .q_atomic_fetch_and_add_release_ptr,TOC[tc0],0 + .csect .text[PR] +.q_atomic_fetch_and_add_release_ptr: + eieio + ldarx 5,0,3 + add 6,4,5 + stdcx. 6,0,3 + bne- $-12 + mr 3,5 + blr +LT..q_atomic_fetch_and_add_release_ptr: + .long 0 + .byte 0,9,32,64,0,0,1,0 + .long 0 + .long LT..q_atomic_fetch_and_add_release_ptr-.q_atomic_fetch_and_add_release_ptr + .short 34 + .byte "q_atomic_fetch_and_add_release_ptr" + .align 2 + +_section_.text: + .csect .data[RW],3 + .llong _section_.text diff --git a/src/corelib/arch/qatomic_alpha.h b/src/corelib/arch/qatomic_alpha.h new file mode 100644 index 0000000..0387baf --- /dev/null +++ b/src/corelib/arch/qatomic_alpha.h @@ -0,0 +1,642 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_ALPHA_H +#define QATOMIC_ALPHA_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#if defined(Q_CC_GNU) + +inline bool QBasicAtomicInt::ref() +{ + register int old, tmp; + asm volatile("1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "addl %0,1,%1\n" /* tmp=old+1; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : + : "memory"); + return old != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + register int old, tmp; + asm volatile("1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "subl %0,1,%1\n" /* tmp=old-1; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : + : "memory"); + return old != 1; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + register int ret; + asm volatile("1:\n" + "ldl_l %0,%1\n" /* ret=*ptr; */ + "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */ + "beq %0,3f\n" /* if (ret==0) goto 3; */ + "mov %3,%0\n" /* ret=newval; */ + "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */ + "beq %0,2f\n" /* if (ret==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + register int ret; + asm volatile("1:\n" + "ldl_l %0,%1\n" /* ret=*ptr; */ + "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */ + "beq %0,3f\n" /* if (ret==0) goto 3; */ + "mov %3,%0\n" /* ret=newval; */ + "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */ + "beq %0,2f\n" /* if (ret==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + "mb\n" + : "=&r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + register int ret; + asm volatile("mb\n" + "1:\n" + "ldl_l %0,%1\n" /* ret=*ptr; */ + "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1; */ + "beq %0,3f\n" /* if (ret==0) goto 3; */ + "mov %3,%0\n" /* ret=newval; */ + "stl_c %0,%1\n" /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */ + "beq %0,2f\n" /* if (ret==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + register int old, tmp; + asm volatile("1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "mov %3,%1\n" /* tmp=newval; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return old; +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + register int old, tmp; + asm volatile("1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "mov %3,%1\n" /* tmp=newval; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + "mb\n" + : "=&r" (old), "=&r" (tmp), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return old; +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + register int old, tmp; + asm volatile("mb\n" + "1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "mov %3,%1\n" /* tmp=newval; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return old; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + register int old, tmp; + asm volatile("1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "addl %0,%3,%1\n"/* tmp=old+value; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : "r" (valueToAdd) + : "memory"); + return old; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + register int old, tmp; + asm volatile("1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "addl %0,%3,%1\n"/* tmp=old+value; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + "mb\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : "r" (valueToAdd) + : "memory"); + return old; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + register int old, tmp; + asm volatile("mb\n" + "1:\n" + "ldl_l %0,%2\n" /* old=*ptr; */ + "addl %0,%3,%1\n"/* tmp=old+value; */ + "stl_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : "r" (valueToAdd) + : "memory"); + return old; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + register void *ret; + asm volatile("1:\n" + "ldq_l %0,%1\n" /* ret=*ptr; */ + "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */ + "beq %0,3f\n" /* if (tmp==0) goto 3; */ + "mov %3,%0\n" /* tmp=newval; */ + "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %0,2f\n" /* if (ret==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + register void *ret; + asm volatile("1:\n" + "ldq_l %0,%1\n" /* ret=*ptr; */ + "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */ + "beq %0,3f\n" /* if (tmp==0) goto 3; */ + "mov %3,%0\n" /* tmp=newval; */ + "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %0,2f\n" /* if (ret==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + "mb\n" + : "=&r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + register void *ret; + asm volatile("mb\n" + "1:\n" + "ldq_l %0,%1\n" /* ret=*ptr; */ + "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1; */ + "beq %0,3f\n" /* if (tmp==0) goto 3; */ + "mov %3,%0\n" /* tmp=newval; */ + "stq_c %0,%1\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %0,2f\n" /* if (ret==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + register void *old, *tmp; + asm volatile("1:\n" + "ldq_l %0,%2\n" /* old=*ptr; */ + "mov %3,%1\n" /* tmp=newval; */ + "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return old; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + register void *old, *tmp; + asm volatile("1:\n" + "ldq_l %0,%2\n" /* old=*ptr; */ + "mov %3,%1\n" /* tmp=newval; */ + "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + "mb\n" + : "=&r" (old), "=&r" (tmp), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return old; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + register void *old, *tmp; + asm volatile("mb\n" + "1:\n" + "ldq_l %0,%2\n" /* old=*ptr; */ + "mov %3,%1\n" /* tmp=newval; */ + "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp==0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return old; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + register void *old, *tmp; + asm volatile("1:\n" + "ldq_l %0,%2\n" /* old=*ptr; */ + "addq %0,%3,%1\n"/* tmp=old+value; */ + "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : "r" (valueToAdd) + : "memory"); + return reinterpret_cast<T *>(old); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + register void *old, *tmp; + asm volatile("1:\n" + "ldq_l %0,%2\n" /* old=*ptr; */ + "addq %0,%3,%1\n"/* tmp=old+value; */ + "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + "mb\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : "r" (valueToAdd) + : "memory"); + return reinterpret_cast<T *>(old); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + register void *old, *tmp; + asm volatile("mb\n" + "1:\n" + "ldq_l %0,%2\n" /* old=*ptr; */ + "addq %0,%3,%1\n"/* tmp=old+value; */ + "stq_c %1,%2\n" /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */ + "beq %1,2f\n" /* if (tmp == 0) goto 2; */ + "br 3f\n" /* goto 3; */ + "2: br 1b\n" /* goto 1; */ + "3:\n" + : "=&r" (old), "=&r" (tmp), "+m"(_q_value) + : "r" (valueToAdd) + : "memory"); + return reinterpret_cast<T *>(old); +} + +#else // !Q_CC_GNU + +extern "C" { + Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval); + Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); + Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval); + Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value); + Q_CORE_EXPORT int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int value); + Q_CORE_EXPORT int q_atomic_fetch_and_add_release_int(volatile int *ptr, int value); +} // extern "C" + +inline bool QBasicAtomicInt::ref() +{ + return q_atomic_increment(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return q_atomic_decrement(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return q_atomic_set_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return q_atomic_fetch_and_store_release_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return q_atomic_fetch_and_add_int(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return q_atomic_fetch_and_add_acquire_int(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return q_atomic_fetch_and_add_release_int(&_q_value, valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, newValue)); +} +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, newValue)); +} + +#endif // Q_CC_GNU + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_ALPHA_H diff --git a/src/corelib/arch/qatomic_arch.h b/src/corelib/arch/qatomic_arch.h new file mode 100644 index 0000000..33641fc --- /dev/null +++ b/src/corelib/arch/qatomic_arch.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARCH_H +#define QATOMIC_ARCH_H + +QT_BEGIN_HEADER + +#include "QtCore/qglobal.h" + +#if defined(QT_ARCH_ALPHA) +# include "QtCore/qatomic_alpha.h" +#elif defined(QT_ARCH_ARM) +# include "QtCore/qatomic_arm.h" +#elif defined(QT_ARCH_ARMV6) +# include "QtCore/qatomic_armv6.h" +#elif defined(QT_ARCH_AVR32) +# include "QtCore/qatomic_avr32.h" +#elif defined(QT_ARCH_BFIN) +# include "QtCore/qatomic_bfin.h" +#elif defined(QT_ARCH_GENERIC) +# include "QtCore/qatomic_generic.h" +#elif defined(QT_ARCH_I386) +# include "QtCore/qatomic_i386.h" +#elif defined(QT_ARCH_IA64) +# include "QtCore/qatomic_ia64.h" +#elif defined(QT_ARCH_MACOSX) +# include "QtCore/qatomic_macosx.h" +#elif defined(QT_ARCH_MIPS) +# include "QtCore/qatomic_mips.h" +#elif defined(QT_ARCH_PARISC) +# include "QtCore/qatomic_parisc.h" +#elif defined(QT_ARCH_POWERPC) +# include "QtCore/qatomic_powerpc.h" +#elif defined(QT_ARCH_S390) +# include "QtCore/qatomic_s390.h" +#elif defined(QT_ARCH_SPARC) +# include "QtCore/qatomic_sparc.h" +#elif defined(QT_ARCH_WINDOWS) +# include "QtCore/qatomic_windows.h" +#elif defined(QT_ARCH_WINDOWSCE) +# include "QtCore/qatomic_windowsce.h" +#elif defined(QT_ARCH_X86_64) +# include "QtCore/qatomic_x86_64.h" +#elif defined(QT_ARCH_SH) +# include "QtCore/qatomic_sh.h" +#elif defined(QT_ARCH_SH4A) +# include "QtCore/qatomic_sh4a.h" +#else +# error "Qt has not been ported to this architecture" +#endif + +QT_END_HEADER + +#endif // QATOMIC_ARCH_H diff --git a/src/corelib/arch/qatomic_arm.h b/src/corelib/arch/qatomic_arm.h new file mode 100644 index 0000000..07ad70c --- /dev/null +++ b/src/corelib/arch/qatomic_arm.h @@ -0,0 +1,401 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARM_H +#define QATOMIC_ARM_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#ifndef QT_NO_ARM_EABI + +// kernel places a restartable cmpxchg implementation at a fixed address +extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); +extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(void *oldval, void *newval, volatile void *ptr); +#define qt_atomic_eabi_cmpxchg_int (*(qt_atomic_eabi_cmpxchg_int_t *)0xffff0fc0) +#define qt_atomic_eabi_cmpxchg_ptr (*(qt_atomic_eabi_cmpxchg_ptr_t *)0xffff0fc0) + +#else + +extern Q_CORE_EXPORT char q_atomic_lock; +Q_CORE_EXPORT void qt_atomic_yield(int *); + +inline char q_atomic_swp(volatile char *ptr, char newval) +{ + register char ret; + asm volatile("swpb %0,%2,[%3]" + : "=&r"(ret), "=m" (*ptr) + : "r"(newval), "r"(ptr) + : "cc", "memory"); + return ret; +} + +#endif + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue + 1; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return newValue != 0; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value++; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue != -1; +#endif +} + +inline bool QBasicAtomicInt::deref() +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue - 1; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return newValue != 0; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value--; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue != 1; +#endif +} + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (qt_atomic_eabi_cmpxchg_int(expectedValue, newValue, &_q_value) != 0); + return true; +#else + bool returnValue = false; + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + q_atomic_swp(&q_atomic_lock, 0); + return returnValue; +#endif +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + int originalValue; + asm volatile("swp %0,%2,[%3]" + : "=&r"(originalValue), "=m" (_q_value) + : "r"(newValue), "r"(&_q_value) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ +#ifndef QT_NO_ARM_EABI + register int originalValue; + register int newValue; + do { + originalValue = _q_value; + newValue = originalValue + valueToAdd; + } while (qt_atomic_eabi_cmpxchg_int(originalValue, newValue, &_q_value) != 0); + return originalValue; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + int originalValue = _q_value; + _q_value += valueToAdd; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue; +#endif +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ +#ifndef QT_NO_ARM_EABI + register T *originalValue; + do { + originalValue = _q_value; + if (originalValue != expectedValue) + return false; + } while (qt_atomic_eabi_cmpxchg_ptr(expectedValue, newValue, &_q_value) != 0); + return true; +#else + bool returnValue = false; + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + q_atomic_swp(&q_atomic_lock, 0); + return returnValue; +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + T *originalValue; + asm volatile("swp %0,%2,[%3]" + : "=&r"(originalValue), "=m" (_q_value) + : "r"(newValue), "r"(&_q_value) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ +#ifndef QT_NO_ARM_EABI + register T *originalValue; + register T *newValue; + do { + originalValue = _q_value; + newValue = originalValue + valueToAdd; + } while (qt_atomic_eabi_cmpxchg_ptr(originalValue, newValue, &_q_value) != 0); + return originalValue; +#else + int count = 0; + while (q_atomic_swp(&q_atomic_lock, ~0) != 0) + qt_atomic_yield(&count); + T *originalValue = (_q_value); + _q_value += valueToAdd; + q_atomic_swp(&q_atomic_lock, 0); + return originalValue; +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_ARM_H diff --git a/src/corelib/arch/qatomic_armv6.h b/src/corelib/arch/qatomic_armv6.h new file mode 100644 index 0000000..2dd38fd --- /dev/null +++ b/src/corelib/arch/qatomic_armv6.h @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_ARMV6_H +#define QATOMIC_ARMV6_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +inline bool QBasicAtomicInt::ref() +{ + register int newValue; + register 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; +} + +inline bool QBasicAtomicInt::deref() +{ + register int newValue; + register 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; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + register int result; + asm volatile("0:\n" + "ldrex %[result], [%[_q_value]]\n" + "eors %[result], %[result], %[expectedValue]\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", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + register int originalValue; + register 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", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + register int originalValue; + register int newValue; + register 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), + [_q_value] "r" (&_q_value) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + register T *result; + asm volatile("0:\n" + "ldrex %[result], [%[_q_value]]\n" + "eors %[result], %[result], %[expectedValue]\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", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + register T *originalValue; + register 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", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + register 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 * sizeof(T)), + [_q_value] "r" (&_q_value) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_ARMV6_H diff --git a/src/corelib/arch/qatomic_avr32.h b/src/corelib/arch/qatomic_avr32.h new file mode 100644 index 0000000..7efbb39 --- /dev/null +++ b/src/corelib/arch/qatomic_avr32.h @@ -0,0 +1,252 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_AVR32_H +#define QATOMIC_AVR32_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +inline bool QBasicAtomicInt::ref() +{ + return __sync_add_and_fetch(&_q_value, 1); +} + +inline bool QBasicAtomicInt::deref() +{ + return __sync_sub_and_fetch(&_q_value, 1); +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return __sync_lock_test_and_set(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return __sync_fetch_and_add(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return __sync_bool_compare_and_swap(&_q_value, expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return __sync_lock_test_and_set(&_q_value, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return __sync_fetch_and_add(&_q_value, valueToAdd * sizeof(T)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_AVR32_H diff --git a/src/corelib/arch/qatomic_bfin.h b/src/corelib/arch/qatomic_bfin.h new file mode 100644 index 0000000..d1d4c91 --- /dev/null +++ b/src/corelib/arch/qatomic_bfin.h @@ -0,0 +1,343 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_BFIN_H +#define QATOMIC_BFIN_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) + +QT_BEGIN_INCLUDE_NAMESPACE +#include <asm/fixed_code.h> +QT_END_INCLUDE_NAMESPACE + +inline bool QBasicAtomicInt::ref() +{ + int ret; + asm volatile("R0 = 1;\n\t" + "P0 = %3;\n\t" + "CALL (%2);\n\t" + "%0 = R0;" + : "=da" (ret), "=m" (_q_value) + : "a" (ATOMIC_ADD32), "da" (&_q_value), "m" (_q_value) + : "R0", "R1", "P0", "RETS", "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + int ret; + asm volatile("R0 = 1;\n\t" + "P0 = %3;\n\t" + "CALL (%2);\n\t" + "%0 = R0;" + : "=da" (ret), "=m" (_q_value) + : "a" (ATOMIC_SUB32), "da" (&_q_value), "m" (_q_value) + : "R0", "R1", "P0", "RETS", "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + long int readval; + asm volatile ("P0 = %2;\n\t" + "R1 = %3;\n\t" + "R2 = %4;\n\t" + "CALL (%5);\n\t" + "%0 = R0;\n\t" + : "=da" (readval), "=m" (_q_value) + : "da" (&_q_value), + "da" (expectedValue), + "da" (newValue), + "a" (ATOMIC_CAS32), + "m" (_q_value) + : "P0", "R0", "R1", "R2", "RETS", "memory", "cc"); + return readval == expectedValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + asm volatile("R1 = %2;\n\t" + "P0 = %4;\n\t" + "CALL (%3);\n\t" + "%0 = R0;" + : "=da" (newValue), "=m" (_q_value) + : "da" (newValue), "a" (ATOMIC_XCHG32), "da" (&_q_value), "m" (_q_value) + : "R0", "R1", "P0", "RETS", "memory"); + return newValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + int ret; + asm volatile("R0 = %[val];\n\t" + "P0 = %[qvalp];\n\t" + "CALL (%[addr]);\n\t" + "%[ret] = R1;" + : [ret] "=da" (ret), "=m" (_q_value) + : [addr] "a" (ATOMIC_ADD32), [qvalp] "da" (&_q_value), "m" (_q_value), [val] "da" (valueToAdd) + : "R0", "R1", "P0", "RETS", "memory"); + return ret; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + T *readval; + asm volatile ("P0 = %2;\n\t" + "R1 = %3;\n\t" + "R2 = %4;\n\t" + "CALL (%5);\n\t" + "%0 = R0;\n\t" + : "=da" (readval), "=m" (_q_value) + : "da" (&_q_value), + "da" (expectedValue), + "da" (newValue), + "a" (ATOMIC_CAS32), + "m" (_q_value) + : "P0", "R0", "R1", "R2", "RETS", "memory", "cc"); + return readval == expectedValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + asm volatile("R1 = %2;\n\t" + "P0 = %4;\n\t" + "CALL (%3);\n\t" + "%0 = R0;" + : "=da" (newValue), "=m" (_q_value) + : "da" (newValue), "a" (ATOMIC_XCHG32), "da" (&_q_value), "m" (_q_value) + : "R0", "R1", "P0", "RETS", "memory"); + return newValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + T* ret; + asm volatile("R0 = %[val];\n\t" + "P0 = %[qvalp];\n\t" + "CALL (%[addr]);\n\t" + "%[ret] = R1;" + : [ret] "=da" (ret), "=m" (_q_value) + : [addr] "a" (ATOMIC_ADD32), [qvalp] "da" (&_q_value), "m" (_q_value), [val] "da" (valueToAdd * sizeof(T)) + : "R0", "R1", "P0", "RETS", "memory"); + return ret; +} + + +#endif // Q_OS_LINUX && Q_CC_GNU + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for integers + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for integers + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_BFIN_H diff --git a/src/corelib/arch/qatomic_bootstrap.h b/src/corelib/arch/qatomic_bootstrap.h new file mode 100644 index 0000000..7584b84 --- /dev/null +++ b/src/corelib/arch/qatomic_bootstrap.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_BOOTSTRAP_H +#define QATOMIC_BOOTSTRAP_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +inline bool QBasicAtomicInt::ref() +{ + return ++_q_value != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return --_q_value != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + if (_q_value == expectedValue) { + _q_value = newValue; + return true; + } + return false; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + int returnValue = _q_value; + _q_value += valueToAdd; + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + if (_q_value == expectedValue) { + _q_value = newValue; + return true; + } + return false; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_BOOTSTRAP_H diff --git a/src/corelib/arch/qatomic_generic.h b/src/corelib/arch/qatomic_generic.h new file mode 100644 index 0000000..f6e6a28 --- /dev/null +++ b/src/corelib/arch/qatomic_generic.h @@ -0,0 +1,282 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_GENERIC_H +#define QATOMIC_GENERIC_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +Q_CORE_EXPORT bool QBasicAtomicInt_testAndSetOrdered(volatile int *, int, int); +Q_CORE_EXPORT int QBasicAtomicInt_fetchAndStoreOrdered(volatile int *, int); +Q_CORE_EXPORT int QBasicAtomicInt_fetchAndAddOrdered(volatile int *, int); + +Q_CORE_EXPORT bool QBasicAtomicPointer_testAndSetOrdered(void * volatile *, void *, void *); +Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndStoreOrdered(void * volatile *, void *); +Q_CORE_EXPORT void *QBasicAtomicPointer_fetchAndAddOrdered(void * volatile *, qptrdiff); + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ + return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, 1) != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, -1) != 1; +} + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return QBasicAtomicInt_testAndSetOrdered(&_q_value, expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return QBasicAtomicInt_fetchAndStoreOrdered(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return QBasicAtomicInt_fetchAndAddOrdered(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + union { T * volatile * typed; void * volatile * voidp; } pointer; + pointer.typed = &_q_value; + return QBasicAtomicPointer_testAndSetOrdered(pointer.voidp, expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + union { T * volatile * typed; void * volatile * voidp; } pointer; + union { T *typed; void *voidp; } returnValue; + pointer.typed = &_q_value; + returnValue.voidp = QBasicAtomicPointer_fetchAndStoreOrdered(pointer.voidp, newValue); + return returnValue.typed; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + union { T * volatile *typed; void * volatile *voidp; } pointer; + union { T *typed; void *voidp; } returnValue; + pointer.typed = &_q_value; + returnValue.voidp = QBasicAtomicPointer_fetchAndAddOrdered(pointer.voidp, valueToAdd * sizeof(T)); + return returnValue.typed; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_GENERIC_H diff --git a/src/corelib/arch/qatomic_i386.h b/src/corelib/arch/qatomic_i386.h new file mode 100644 index 0000000..f8d3708 --- /dev/null +++ b/src/corelib/arch/qatomic_i386.h @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_I386_H +#define QATOMIC_I386_H + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return true; } + +#if defined(Q_CC_GNU) || defined(Q_CC_INTEL) + +inline bool QBasicAtomicInt::ref() +{ + unsigned char ret; + asm volatile("lock\n" + "incl %0\n" + "setne %1" + : "=m" (_q_value), "=qm" (ret) + : "m" (_q_value) + : "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + unsigned char ret; + asm volatile("lock\n" + "decl %0\n" + "setne %1" + : "=m" (_q_value), "=qm" (ret) + : "m" (_q_value) + : "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + unsigned char ret; + asm volatile("lock\n" + "cmpxchgl %3,%2\n" + "sete %1\n" + : "=a" (newValue), "=qm" (ret), "+m" (_q_value) + : "r" (newValue), "0" (expectedValue) + : "memory"); + return ret != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + asm volatile("xchgl %0,%1" + : "=r" (newValue), "+m" (_q_value) + : "0" (newValue) + : "memory"); + return newValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + asm volatile("lock\n" + "xaddl %0,%1" + : "=r" (valueToAdd), "+m" (_q_value) + : "0" (valueToAdd) + : "memory"); + return valueToAdd; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + unsigned char ret; + asm volatile("lock\n" + "cmpxchgl %3,%2\n" + "sete %1\n" + : "=a" (newValue), "=qm" (ret), "+m" (_q_value) + : "r" (newValue), "0" (expectedValue) + : "memory"); + return ret != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + asm volatile("xchgl %0,%1" + : "=r" (newValue), "+m" (_q_value) + : "0" (newValue) + : "memory"); + return newValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + asm volatile("lock\n" + "xaddl %0,%1" + : "=r" (valueToAdd), "+m" (_q_value) + : "0" (valueToAdd * sizeof(T)) + : "memory"); + return reinterpret_cast<T *>(valueToAdd); +} + +#else + +extern "C" { + Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval); + Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); + Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval); + Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value); + Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, int value); +} // extern "C" + +inline bool QBasicAtomicInt::ref() +{ + return q_atomic_increment(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return q_atomic_decrement(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return q_atomic_set_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return q_atomic_fetch_and_add_int(&_q_value, valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +#endif + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QATOMIC_I386_H diff --git a/src/corelib/arch/qatomic_ia64.h b/src/corelib/arch/qatomic_ia64.h new file mode 100644 index 0000000..1803c85 --- /dev/null +++ b/src/corelib/arch/qatomic_ia64.h @@ -0,0 +1,813 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_IA64_H +#define QATOMIC_IA64_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +inline bool _q_ia64_fetchadd_immediate(register int value) +{ + return value == 1 || value == -1 + || value == 4 || value == -4 + || value == 8 || value == -8 + || value == 16 || value == -16; +} + +#if defined(Q_CC_INTEL) + +// intrinsics provided by the Intel C++ Compiler +#include <ia64intrin.h> + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return static_cast<int>(_InterlockedExchange(&_q_value, newValue)); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + __memory_barrier(); + return static_cast<int>(_InterlockedExchange(&_q_value, newValue)); +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + register int expectedValueCopy = expectedValue; + return (static_cast<int>(_InterlockedCompareExchange(&_q_value, + newValue, + expectedValueCopy)) + == expectedValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + register int expectedValueCopy = expectedValue; + return (static_cast<int>(_InterlockedCompareExchange_acq(reinterpret_cast<volatile uint *>(&_q_value), + newValue, + expectedValueCopy)) + == expectedValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + register int expectedValueCopy = expectedValue; + return (static_cast<int>(_InterlockedCompareExchange_rel(reinterpret_cast<volatile uint *>(&_q_value), + newValue, + expectedValueCopy)) + == expectedValue); +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + __memory_barrier(); + return testAndSetAcquire(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + if (__builtin_constant_p(valueToAdd)) { + if (valueToAdd == 1) + return __fetchadd4_acq((unsigned int *)&_q_value, 1); + if (valueToAdd == -1) + return __fetchadd4_acq((unsigned int *)&_q_value, -1); + } + return _InterlockedExchangeAdd(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + if (__builtin_constant_p(valueToAdd)) { + if (valueToAdd == 1) + return __fetchadd4_rel((unsigned int *)&_q_value, 1); + if (valueToAdd == -1) + return __fetchadd4_rel((unsigned int *)&_q_value, -1); + } + __memory_barrier(); + return _InterlockedExchangeAdd(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + __memory_barrier(); + return fetchAndAddAcquire(valueToAdd); +} + +inline bool QBasicAtomicInt::ref() +{ + return _InterlockedIncrement(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return _InterlockedDecrement(&_q_value) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return (T *)_InterlockedExchangePointer(&_q_value, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + __memory_barrier(); + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + register T *expectedValueCopy = expectedValue; + return (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile*>(&_q_value), + newValue, + expectedValueCopy) + == expectedValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + union { + volatile void *x; + volatile unsigned long *p; + }; + x = &_q_value; + register T *expectedValueCopy = expectedValue; + return (_InterlockedCompareExchange64_acq(p, quintptr(newValue), quintptr(expectedValueCopy)) + == quintptr(expectedValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + union { + volatile void *x; + volatile unsigned long *p; + }; + x = &_q_value; + register T *expectedValueCopy = expectedValue; + return (_InterlockedCompareExchange64_rel(p, quintptr(newValue), quintptr(expectedValueCopy)) + == quintptr(expectedValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + __memory_barrier(); + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value, + valueToAdd * sizeof(T)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + __memory_barrier(); + return (T *)_InterlockedExchangeAdd64((volatile long *)&_q_value, + valueToAdd * sizeof(T)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + __memory_barrier(); + return fetchAndAddAcquire(valueToAdd); +} + +#else // !Q_CC_INTEL + +# if defined(Q_CC_GNU) + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + int ret; + asm volatile("xchg4 %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return ret; +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + int ret; + asm volatile("mf\n" + "xchg4 %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return ret; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + int ret; + asm volatile("mov ar.ccv=%2\n" + ";;\n" + "cmpxchg4.acq %0=%1,%3,ar.ccv\n" + : "=r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret == expectedValue; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + int ret; + asm volatile("mov ar.ccv=%2\n" + ";;\n" + "cmpxchg4.rel %0=%1,%3,ar.ccv\n" + : "=r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret == expectedValue; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + int ret; + +#if (__GNUC__ >= 4) + // We implement a fast fetch-and-add when we can + if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) { + asm volatile("fetchadd4.acq %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "i" (valueToAdd) + : "memory"); + return ret; + } +#endif + + // otherwise, use a loop around test-and-set + ret = _q_value; + asm volatile("0:\n" + " mov r9=%0\n" + " mov ar.ccv=%0\n" + " add %0=%0, %2\n" + " ;;\n" + " cmpxchg4.acq %0=%1,%0,ar.ccv\n" + " ;;\n" + " cmp.ne p6,p0 = %0, r9\n" + "(p6) br.dptk 0b\n" + "1:\n" + : "+r" (ret), "+m" (_q_value) + : "r" (valueToAdd) + : "r9", "p6", "memory"); + return ret; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + int ret; + +#if (__GNUC__ >= 4) + // We implement a fast fetch-and-add when we can + if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd)) { + asm volatile("fetchadd4.rel %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "i" (valueToAdd) + : "memory"); + return ret; + } +#endif + + // otherwise, use a loop around test-and-set + ret = _q_value; + asm volatile("0:\n" + " mov r9=%0\n" + " mov ar.ccv=%0\n" + " add %0=%0, %2\n" + " ;;\n" + " cmpxchg4.rel %0=%1,%0,ar.ccv\n" + " ;;\n" + " cmp.ne p6,p0 = %0, r9\n" + "(p6) br.dptk 0b\n" + "1:\n" + : "+r" (ret), "+m" (_q_value) + : "r" (valueToAdd) + : "r9", "p6", "memory"); + return ret; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + asm volatile("mf" ::: "memory"); + return fetchAndAddRelease(valueToAdd); +} + +inline bool QBasicAtomicInt::ref() +{ + int ret; + asm volatile("fetchadd4.acq %0=%1,1\n" + : "=r" (ret), "+m" (_q_value) + : + : "memory"); + return ret != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + int ret; + asm volatile("fetchadd4.rel %0=%1,-1\n" + : "=r" (ret), "+m" (_q_value) + : + : "memory"); + return ret != 1; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + T *ret; + asm volatile("xchg8 %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return ret; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + T *ret; + asm volatile("mf\n" + "xchg8 %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "r" (newValue) + : "memory"); + return ret; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + T *ret; + asm volatile("mov ar.ccv=%2\n" + ";;\n" + "cmpxchg8.acq %0=%1,%3,ar.ccv\n" + : "=r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret == expectedValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + T *ret; + asm volatile("mov ar.ccv=%2\n" + ";;\n" + "cmpxchg8.rel %0=%1,%3,ar.ccv\n" + : "=r" (ret), "+m" (_q_value) + : "r" (expectedValue), "r" (newValue) + : "memory"); + return ret == expectedValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + T *ret; + +#if (__GNUC__ >= 4) + // We implement a fast fetch-and-add when we can + if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd * sizeof(T))) { + asm volatile("fetchadd8.acq %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "i" (valueToAdd * sizeof(T)) + : "memory"); + return ret; + } +#endif + + // otherwise, use a loop around test-and-set + ret = _q_value; + asm volatile("0:\n" + " mov r9=%0\n" + " mov ar.ccv=%0\n" + " add %0=%0, %2\n" + " ;;\n" + " cmpxchg8.acq %0=%1,%0,ar.ccv\n" + " ;;\n" + " cmp.ne p6,p0 = %0, r9\n" + "(p6) br.dptk 0b\n" + "1:\n" + : "+r" (ret), "+m" (_q_value) + : "r" (valueToAdd * sizeof(T)) + : "r9", "p6", "memory"); + return ret; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + T *ret; + +#if (__GNUC__ >= 4) + // We implement a fast fetch-and-add when we can + if (__builtin_constant_p(valueToAdd) && _q_ia64_fetchadd_immediate(valueToAdd * sizeof(T))) { + asm volatile("fetchadd8.rel %0=%1,%2\n" + : "=r" (ret), "+m" (_q_value) + : "i" (valueToAdd * sizeof(T)) + : "memory"); + return ret; + } +#endif + + // otherwise, use a loop around test-and-set + ret = _q_value; + asm volatile("0:\n" + " mov r9=%0\n" + " mov ar.ccv=%0\n" + " add %0=%0, %2\n" + " ;;\n" + " cmpxchg8.rel %0=%1,%0,ar.ccv\n" + " ;;\n" + " cmp.ne p6,p0 = %0, r9\n" + "(p6) br.dptk 0b\n" + "1:\n" + : "+r" (ret), "+m" (_q_value) + : "r" (valueToAdd * sizeof(T)) + : "r9", "p6", "memory"); + return ret; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + asm volatile("mf" ::: "memory"); + return fetchAndAddRelease(valueToAdd); +} + +#elif defined Q_CC_HPACC + +QT_BEGIN_INCLUDE_NAMESPACE +#include <ia64/sys/inline.h> +QT_END_INCLUDE_NAMESPACE + +#define FENCE (_Asm_fence)(_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE) + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return _Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue, + (_Asm_ldhint)_LDHINT_NONE, FENCE); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + _Asm_mf(FENCE); + return _Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (unsigned)newValue, + (_Asm_ldhint)_LDHINT_NONE, FENCE); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE); + int ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, (unsigned)newValue, (_Asm_ldhint)_LDHINT_NONE); + return ret == expectedValue; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)expectedValue, FENCE); + int ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL, + &_q_value, newValue, (_Asm_ldhint)_LDHINT_NONE); + return ret == expectedValue; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + if (valueToAdd == 1) + return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE); + else if (valueToAdd == -1) + return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE); + + // implement the test-and-set loop + register int old, ret; + do { + old = _q_value; + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE); + ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); + } while (ret != old); + return old; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + if (valueToAdd == 1) + return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL, + &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE); + else if (valueToAdd == -1) + return _Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL, + &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE); + + // implement the test-and-set loop + register int old, ret; + do { + old = _q_value; + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (unsigned)old, FENCE); + ret = _Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL, + &_q_value, old + valueToAdd, (_Asm_ldhint)_LDHINT_NONE); + } while (ret != old); + return old; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + _Asm_mf(FENCE); + return fetchAndAddAcquire(valueToAdd); +} + +inline bool QBasicAtomicInt::ref() +{ + return (int)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, 1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + return (int)_Asm_fetchadd((_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_REL, + &_q_value, -1, (_Asm_ldhint)_LDHINT_NONE, FENCE) != 1; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ +#ifdef __LP64__ + return (T *)_Asm_xchg((_Asm_sz)_SZ_D, &_q_value, (quint64)newValue, + (_Asm_ldhint)_LDHINT_NONE, FENCE); +#else + return (T *)_Asm_xchg((_Asm_sz)_SZ_W, &_q_value, (quint32)newValue, + (_Asm_ldhint)_LDHINT_NONE, FENCE); +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + _Asm_mf(FENCE); + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ +#ifdef __LP64__ + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE); + T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ, + &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE); +#else + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)expectedValue, FENCE); + T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, (quint32)newValue, (_Asm_ldhint)_LDHINT_NONE); +#endif + return ret == expectedValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ +#ifdef __LP64__ + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)expectedValue, FENCE); + T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL, + &_q_value, (quint64)newValue, (_Asm_ldhint)_LDHINT_NONE); +#else + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)expectedValue, FENCE); + T *ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL, + &_q_value, (quint32)newValue, (_Asm_ldhint)_LDHINT_NONE); +#endif + return ret == expectedValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + // implement the test-and-set loop + register T *old, *ret; + do { + old = _q_value; +#ifdef __LP64__ + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE); + ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_ACQ, + &_q_value, (quint64)(old + valueToAdd), + (_Asm_ldhint)_LDHINT_NONE); +#else + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)old, FENCE); + ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_ACQ, + &_q_value, (quint32)(old + valueToAdd), + (_Asm_ldhint)_LDHINT_NONE); +#endif + } while (old != ret); + return old; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + // implement the test-and-set loop + register T *old, *ret; + do { + old = _q_value; +#ifdef __LP64__ + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint64)old, FENCE); + ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_D, (_Asm_sem)_SEM_REL, + &_q_value, (quint64)(old + valueToAdd), + (_Asm_ldhint)_LDHINT_NONE); +#else + _Asm_mov_to_ar((_Asm_app_reg)_AREG_CCV, (quint32)old, FENCE); + ret = (T *)_Asm_cmpxchg((_Asm_sz)_SZ_W, (_Asm_sem)_SEM_REL, + &_q_value, (quint32)(old + valueToAdd), + (_Asm_ldhint)_LDHINT_NONE); +#endif + } while (old != ret); + return old; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + _Asm_mf(FENCE); + return fetchAndAddAcquire(valueToAdd); +} + +#else + +extern "C" { + Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval); +} // extern "C" + +#endif + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +#endif // Q_CC_INTEL + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return fetchAndStoreRelease(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return fetchAndStoreRelaxed(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_IA64_H diff --git a/src/corelib/arch/qatomic_macosx.h b/src/corelib/arch/qatomic_macosx.h new file mode 100644 index 0000000..b343e41 --- /dev/null +++ b/src/corelib/arch/qatomic_macosx.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_MACOSX_H +#define QATOMIC_MACOSX_H + +QT_BEGIN_HEADER + +#if defined(__x86_64__) +# include <QtCore/qatomic_x86_64.h> +#elif defined(__i386__) +# include <QtCore/qatomic_i386.h> +#else // !__x86_64 && !__i386__ +# include <QtCore/qatomic_powerpc.h> +#endif // !__x86_64__ && !__i386__ + +QT_END_HEADER + +#endif // QATOMIC_MACOSX_H diff --git a/src/corelib/arch/qatomic_mips.h b/src/corelib/arch/qatomic_mips.h new file mode 100644 index 0000000..b263aab --- /dev/null +++ b/src/corelib/arch/qatomic_mips.h @@ -0,0 +1,826 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_MIPS_H +#define QATOMIC_MIPS_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#if defined(Q_CC_GNU) && !defined(Q_OS_IRIX) + +inline bool QBasicAtomicInt::ref() +{ + register int originalValue; + register int newValue; + asm volatile("0:\n" + "ll %[originalValue], %[_q_value]\n" + "addiu %[newValue], %[originalValue], %[one]\n" + "sc %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [one] "i" (1) + : "cc", "memory"); + return originalValue != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + register int originalValue; + register int newValue; + asm volatile("0:\n" + "ll %[originalValue], %[_q_value]\n" + "addiu %[newValue], %[originalValue], %[minusOne]\n" + "sc %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [minusOne] "i" (-1) + : "cc", "memory"); + return originalValue != 1; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + register int result; + register int tempValue; + asm volatile("0:\n" + "ll %[result], %[_q_value]\n" + "xor %[result], %[result], %[expectedValue]\n" + "bnez %[result], 0f\n" + "nop\n" + "move %[tempValue], %[newValue]\n" + "sc %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "0:\n" + : [result] "=&r" (result), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + register int result; + register int tempValue; + asm volatile("0:\n" + "ll %[result], %[_q_value]\n" + "xor %[result], %[result], %[expectedValue]\n" + "bnez %[result], 0f\n" + "nop\n" + "move %[tempValue], %[newValue]\n" + "sc %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "sync\n" + "0:\n" + : [result] "=&r" (result), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + register int result; + register int tempValue; + asm volatile("sync\n" + "0:\n" + "ll %[result], %[_q_value]\n" + "xor %[result], %[result], %[expectedValue]\n" + "bnez %[result], 0f\n" + "nop\n" + "move %[tempValue], %[newValue]\n" + "sc %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "0:\n" + : [result] "=&r" (result), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + register int originalValue; + register int tempValue; + asm volatile("0:\n" + "ll %[originalValue], %[_q_value]\n" + "move %[tempValue], %[newValue]\n" + "sc %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + register int originalValue; + register int tempValue; + asm volatile("0:\n" + "ll %[originalValue], %[_q_value]\n" + "move %[tempValue], %[newValue]\n" + "sc %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "sync\n" + : [originalValue] "=&r" (originalValue), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + register int originalValue; + register int tempValue; + asm volatile("sync\n" + "0:\n" + "ll %[originalValue], %[_q_value]\n" + "move %[tempValue], %[newValue]\n" + "sc %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + register int originalValue; + register int newValue; + asm volatile("0:\n" + "ll %[originalValue], %[_q_value]\n" + "addu %[newValue], %[originalValue], %[valueToAdd]\n" + "sc %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [valueToAdd] "r" (valueToAdd) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + register int originalValue; + register int newValue; + asm volatile("0:\n" + "ll %[originalValue], %[_q_value]\n" + "addu %[newValue], %[originalValue], %[valueToAdd]\n" + "sc %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + "sync\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [valueToAdd] "r" (valueToAdd) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + register int originalValue; + register int newValue; + asm volatile("sync\n" + "0:\n" + "ll %[originalValue], %[_q_value]\n" + "addu %[newValue], %[originalValue], %[valueToAdd]\n" + "sc %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [valueToAdd] "r" (valueToAdd) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +#if defined(__LP64__) +# define LLP "lld" +# define SCP "scd" +#else +# define LLP "ll" +# define SCP "sc" +#endif + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + register T *result; + register T *tempValue; + asm volatile("0:\n" + LLP" %[result], %[_q_value]\n" + "xor %[result], %[result], %[expectedValue]\n" + "bnez %[result], 0f\n" + "nop\n" + "move %[tempValue], %[newValue]\n" + SCP" %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "0:\n" + : [result] "=&r" (result), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + register T *result; + register T *tempValue; + asm volatile("0:\n" + LLP" %[result], %[_q_value]\n" + "xor %[result], %[result], %[expectedValue]\n" + "bnez %[result], 0f\n" + "nop\n" + "move %[tempValue], %[newValue]\n" + SCP" %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "sync\n" + "0:\n" + : [result] "=&r" (result), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + register T *result; + register T *tempValue; + asm volatile("sync\n" + "0:\n" + LLP" %[result], %[_q_value]\n" + "xor %[result], %[result], %[expectedValue]\n" + "bnez %[result], 0f\n" + "nop\n" + "move %[tempValue], %[newValue]\n" + SCP" %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "0:\n" + : [result] "=&r" (result), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + register T *originalValue; + register T *tempValue; + asm volatile("0:\n" + LLP" %[originalValue], %[_q_value]\n" + "move %[tempValue], %[newValue]\n" + SCP" %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + register T *originalValue; + register T *tempValue; + asm volatile("0:\n" + LLP" %[originalValue], %[_q_value]\n" + "move %[tempValue], %[newValue]\n" + SCP" %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + "sync\n" + : [originalValue] "=&r" (originalValue), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + register T *originalValue; + register T *tempValue; + asm volatile("sync\n" + "0:\n" + LLP" %[originalValue], %[_q_value]\n" + "move %[tempValue], %[newValue]\n" + SCP" %[tempValue], %[_q_value]\n" + "beqz %[tempValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [tempValue] "=&r" (tempValue), + [_q_value] "+m" (_q_value) + : [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + asm volatile("0:\n" + LLP" %[originalValue], %[_q_value]\n" + "addu %[newValue], %[originalValue], %[valueToAdd]\n" + SCP" %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + asm volatile("0:\n" + LLP" %[originalValue], %[_q_value]\n" + "addu %[newValue], %[originalValue], %[valueToAdd]\n" + SCP" %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + "sync\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + asm volatile("sync\n" + "0:\n" + LLP" %[originalValue], %[_q_value]\n" + "addu %[newValue], %[originalValue], %[valueToAdd]\n" + SCP" %[newValue], %[_q_value]\n" + "beqz %[newValue], 0b\n" + "nop\n" + : [originalValue] "=&r" (originalValue), + [_q_value] "+m" (_q_value), + [newValue] "=&r" (newValue) + : [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +#else // !Q_CC_GNU + +extern "C" { + Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval); + Q_CORE_EXPORT int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, void *expected, void *newval); + Q_CORE_EXPORT int q_atomic_test_and_set_release_ptr(volatile void *ptr, void *expected, void *newval); +} // extern "C" + +inline bool QBasicAtomicInt::ref() +{ + register int expected; + for (;;) { + expected = _q_value; + if (q_atomic_test_and_set_int(&_q_value, expected, expected + 1)) + break; + } + return expected != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + register int expected; + for (;;) { + expected = _q_value; + if (q_atomic_test_and_set_int(&_q_value, expected, expected - 1)) + break; + } + return expected != 1; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetRelaxed(returnValue, newValue)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetAcquire(returnValue, newValue)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetRelease(returnValue, newValue)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetOrdered(returnValue, newValue)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetRelaxed(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetAcquire(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetRelease(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + int returnValue; + for (;;) { + returnValue = _q_value; + if (testAndSetOrdered(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetRelaxed(returnValue, newValue)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetAcquire(returnValue, newValue)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetRelease(returnValue, newValue)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetOrdered(returnValue, newValue)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetRelaxed(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE +T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetAcquire(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetRelease(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + T *returnValue; + for (;;) { + returnValue = (_q_value); + if (testAndSetOrdered(returnValue, returnValue + valueToAdd)) + break; + } + return returnValue; +} + +#endif // Q_CC_GNU + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_MIPS_H diff --git a/src/corelib/arch/qatomic_parisc.h b/src/corelib/arch/qatomic_parisc.h new file mode 100644 index 0000000..134faf9 --- /dev/null +++ b/src/corelib/arch/qatomic_parisc.h @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_PARISC_H +#define QATOMIC_PARISC_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +extern "C" { + Q_CORE_EXPORT void q_atomic_lock(int *lock); + Q_CORE_EXPORT void q_atomic_unlock(int *lock); +} + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ + q_atomic_lock(_q_lock); + bool ret = (++_q_value != 0); + q_atomic_unlock(_q_lock); + return ret; +} + +inline bool QBasicAtomicInt::deref() +{ + q_atomic_lock(_q_lock); + bool ret = (--_q_value != 0); + q_atomic_unlock(_q_lock); + return ret; +} + +// Test-and-set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + q_atomic_lock(_q_lock); + if (_q_value == expectedValue) { + _q_value = newValue; + q_atomic_unlock(_q_lock); + return true; + } + q_atomic_unlock(_q_lock); + return false; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch-and-store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + q_atomic_lock(_q_lock); + int returnValue = _q_value; + _q_value = newValue; + q_atomic_unlock(_q_lock); + return returnValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch-and-add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + q_atomic_lock(_q_lock); + int originalValue = _q_value; + _q_value += valueToAdd; + q_atomic_unlock(_q_lock); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + q_atomic_lock(_q_lock); + if (_q_value == expectedValue) { + _q_value = newValue; + q_atomic_unlock(_q_lock); + return true; + } + q_atomic_unlock(_q_lock); + return false; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + q_atomic_lock(_q_lock); + T *returnValue = (_q_value); + _q_value = newValue; + q_atomic_unlock(_q_lock); + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + q_atomic_lock(_q_lock); + T *returnValue = (_q_value); + _q_value += valueToAdd; + q_atomic_unlock(_q_lock); + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_PARISC_H diff --git a/src/corelib/arch/qatomic_powerpc.h b/src/corelib/arch/qatomic_powerpc.h new file mode 100644 index 0000000..28a143e --- /dev/null +++ b/src/corelib/arch/qatomic_powerpc.h @@ -0,0 +1,650 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_POWERPC_H +#define QATOMIC_POWERPC_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +QT_BEGIN_NAMESPACE + +#if defined(Q_CC_GNU) + +#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) \ + || (!defined(__64BIT__) && !defined(__powerpc64__) && !defined(__ppc64__)) +# define _Q_VALUE "0, %[_q_value]" +# define _Q_VALUE_MEMORY_OPERAND "+m" (_q_value) +# define _Q_VALUE_REGISTER_OPERAND [_q_value] "r" (&_q_value), +#else +// On 64-bit with gcc >= 4.2 +# define _Q_VALUE "%y[_q_value]" +# define _Q_VALUE_MEMORY_OPERAND [_q_value] "+Z" (_q_value) +# define _Q_VALUE_REGISTER_OPERAND +#endif + +inline bool QBasicAtomicInt::ref() +{ + register int originalValue; + register int newValue; + asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" + "addi %[newValue], %[originalValue], %[one]\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + : [originalValue] "=&b" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [one] "i" (1) + : "cc", "memory"); + return newValue != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + register int originalValue; + register int newValue; + asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" + "addi %[newValue], %[originalValue], %[minusOne]\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + : [originalValue] "=&b" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [minusOne] "i" (-1) + : "cc", "memory"); + return newValue != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + register int result; + asm volatile("lwarx %[result]," _Q_VALUE "\n" + "xor. %[result], %[result], %[expectedValue]\n" + "bne $+12\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-16\n" + : [result] "=&r" (result), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + register int result; + asm volatile("lwarx %[result]," _Q_VALUE "\n" + "xor. %[result], %[result], %[expectedValue]\n" + "bne $+16\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-16\n" + "isync\n" + : [result] "=&r" (result), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + register int result; + asm volatile("eieio\n" + "lwarx %[result]," _Q_VALUE "\n" + "xor. %[result], %[result], %[expectedValue]\n" + "bne $+12\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-16\n" + : [result] "=&r" (result), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + register int originalValue; + asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-8\n" + : [originalValue] "=&r" (originalValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + register int originalValue; + asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-8\n" + "isync\n" + : [originalValue] "=&r" (originalValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + register int originalValue; + asm volatile("eieio\n" + "lwarx %[originalValue]," _Q_VALUE "\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-8\n" + : [originalValue] "=&r" (originalValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + register int originalValue; + register int newValue; + asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" + "add %[newValue], %[originalValue], %[valueToAdd]\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + : [originalValue] "=&r" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [valueToAdd] "r" (valueToAdd) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + register int originalValue; + register int newValue; + asm volatile("lwarx %[originalValue]," _Q_VALUE "\n" + "add %[newValue], %[originalValue], %[valueToAdd]\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + "isync\n" + : [originalValue] "=&r" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [valueToAdd] "r" (valueToAdd) + : "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + register int originalValue; + register int newValue; + asm volatile("eieio\n" + "lwarx %[originalValue]," _Q_VALUE "\n" + "add %[newValue], %[originalValue], %[valueToAdd]\n" + "stwcx. %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + : [originalValue] "=&r" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [valueToAdd] "r" (valueToAdd) + : "cc", "memory"); + return originalValue; +} + +#if defined(__64BIT__) || defined(__powerpc64__) || defined(__ppc64__) +# define LPARX "ldarx" +# define STPCX "stdcx." +#else +# define LPARX "lwarx" +# define STPCX "stwcx." +#endif + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + register void *result; + asm volatile(LPARX" %[result]," _Q_VALUE "\n" + "xor. %[result], %[result], %[expectedValue]\n" + "bne $+12\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-16\n" + : [result] "=&r" (result), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + register void *result; + asm volatile(LPARX" %[result]," _Q_VALUE "\n" + "xor. %[result], %[result], %[expectedValue]\n" + "bne $+16\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-16\n" + "isync\n" + : [result] "=&r" (result), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + register void *result; + asm volatile("eieio\n" + LPARX" %[result]," _Q_VALUE "\n" + "xor. %[result], %[result], %[expectedValue]\n" + "bne $+12\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-16\n" + : [result] "=&r" (result), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + register T *originalValue; + asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-8\n" + : [originalValue] "=&r" (originalValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + register T *originalValue; + asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-8\n" + "isync\n" + : [originalValue] "=&r" (originalValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + register T *originalValue; + asm volatile("eieio\n" + LPARX" %[originalValue]," _Q_VALUE "\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-8\n" + : [originalValue] "=&r" (originalValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [newValue] "r" (newValue) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" + "add %[newValue], %[originalValue], %[valueToAdd]\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + : [originalValue] "=&r" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n" + "add %[newValue], %[originalValue], %[valueToAdd]\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + "isync\n" + : [originalValue] "=&r" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + register T *originalValue; + register T *newValue; + asm volatile("eieio\n" + LPARX" %[originalValue]," _Q_VALUE "\n" + "add %[newValue], %[originalValue], %[valueToAdd]\n" + STPCX" %[newValue]," _Q_VALUE "\n" + "bne- $-12\n" + : [originalValue] "=&r" (originalValue), + [newValue] "=&r" (newValue), + _Q_VALUE_MEMORY_OPERAND + : _Q_VALUE_REGISTER_OPERAND + [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "cc", "memory"); + return originalValue; +} + +#undef LPARX +#undef STPCX +#undef _Q_VALUE +#undef _Q_VALUE_MEMORY_OPERAND +#undef _Q_VALUE_REGISTER_OPERAND + +#else + +extern "C" { + int q_atomic_test_and_set_int(volatile int *ptr, int expectedValue, int newValue); + int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expectedValue, int newValue); + int q_atomic_test_and_set_release_int(volatile int *ptr, int expectedValue, int newValue); + int q_atomic_test_and_set_ptr(volatile void *ptr, void *expectedValue, void *newValue); + int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, void *expectedValue, void *newValue); + int q_atomic_test_and_set_release_ptr(volatile void *ptr, void *expectedValue, void *newValue); + int q_atomic_increment(volatile int *); + int q_atomic_decrement(volatile int *); + int q_atomic_set_int(volatile int *, int); + int q_atomic_fetch_and_store_acquire_int(volatile int *ptr, int newValue); + int q_atomic_fetch_and_store_release_int(volatile int *ptr, int newValue); + void *q_atomic_set_ptr(volatile void *, void *); + int q_atomic_fetch_and_store_acquire_ptr(volatile void *ptr, void *newValue); + int q_atomic_fetch_and_store_release_ptr(volatile void *ptr, void *newValue); + int q_atomic_fetch_and_add_int(volatile int *ptr, int valueToAdd); + int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int valueToAdd); + int q_atomic_fetch_and_add_release_int(volatile int *ptr, int valueToAdd); + void *q_atomic_fetch_and_add_ptr(volatile void *ptr, qptrdiff valueToAdd); + void *q_atomic_fetch_and_add_acquire_ptr(volatile void *ptr, qptrdiff valueToAdd); + void *q_atomic_fetch_and_add_release_ptr(volatile void *ptr, qptrdiff valueToAdd); +} // extern "C" + + +inline bool QBasicAtomicInt::ref() +{ + return q_atomic_increment(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return q_atomic_decrement(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return q_atomic_set_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return q_atomic_fetch_and_store_release_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return q_atomic_fetch_and_add_int(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return q_atomic_fetch_and_add_acquire_int(&_q_value, valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return q_atomic_fetch_and_add_release_int(&_q_value, valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T))); +} +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +#endif + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_POWERPC_H diff --git a/src/corelib/arch/qatomic_s390.h b/src/corelib/arch/qatomic_s390.h new file mode 100644 index 0000000..434e12a --- /dev/null +++ b/src/corelib/arch/qatomic_s390.h @@ -0,0 +1,430 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_S390_H +#define QATOMIC_S390_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +#ifdef __GNUC__ +#define __GNU_EXTENSION __extension__ +#else +#define __GNU_EXTENSION +#endif + +#define __CS_LOOP(ptr, op_val, op_string, pre, post) __GNU_EXTENSION ({ \ + volatile int old_val, new_val; \ + __asm__ __volatile__(pre \ + " l %0,0(%3)\n" \ + "0: lr %1,%0\n" \ + op_string " %1,%4\n" \ + " cs %0,%1,0(%3)\n" \ + " jl 0b\n" \ + post \ + : "=&d" (old_val), "=&d" (new_val), \ + "=m" (*ptr) \ + : "a" (ptr), "d" (op_val), \ + "m" (*ptr) \ + : "cc", "memory" ); \ + new_val; \ +}) + +#define __CS_OLD_LOOP(ptr, op_val, op_string, pre, post ) __GNU_EXTENSION ({ \ + volatile int old_val, new_val; \ + __asm__ __volatile__(pre \ + " l %0,0(%3)\n" \ + "0: lr %1,%0\n" \ + op_string " %1,%4\n" \ + " cs %0,%1,0(%3)\n" \ + " jl 0b\n" \ + post \ + : "=&d" (old_val), "=&d" (new_val), \ + "=m" (*ptr) \ + : "a" (ptr), "d" (op_val), \ + "m" (*ptr) \ + : "cc", "memory" ); \ + old_val; \ +}) + +#ifdef __s390x__ +#define __CSG_OLD_LOOP(ptr, op_val, op_string, pre, post) __GNU_EXTENSION ({ \ + long old_val, new_val; \ + __asm__ __volatile__(pre \ + " lg %0,0(%3)\n" \ + "0: lgr %1,%0\n" \ + op_string " %1,%4\n" \ + " csg %0,%1,0(%3)\n" \ + " jl 0b\n" \ + post \ + : "=&d" (old_val), "=&d" (new_val), \ + "=m" (*ptr) \ + : "a" (ptr), "d" (op_val), \ + "m" (*ptr) \ + : "cc", "memory" ); \ + old_val; \ +}) +#endif + +inline bool QBasicAtomicInt::ref() +{ + return __CS_LOOP(&_q_value, 1, "ar", "", "") != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return __CS_LOOP(&_q_value, 1, "sr", "", "") != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + int retval; + __asm__ __volatile__( + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); + return retval == 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + int retval; + __asm__ __volatile__( + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:\n" + " bcr 15,0\n" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); + return retval == 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + int retval; + __asm__ __volatile__( + " bcr 15,0\n" + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); + return retval == 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return __CS_OLD_LOOP(&_q_value, newValue, "lr", "", ""); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return __CS_OLD_LOOP(&_q_value, newValue, "lr", "", "bcr 15,0\n"); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return __CS_OLD_LOOP(&_q_value, newValue, "lr", "bcr 15,0\n", ""); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return __CS_OLD_LOOP(&_q_value, valueToAdd, "ar", "", "bcr 15,0\n"); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + int retval; + +#ifndef __s390x__ + __asm__ __volatile__( + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); +#else + __asm__ __volatile__( + " lgr %0,%3\n" + " csg %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); +#endif + + return retval == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + int retval; + +#ifndef __s390x__ + __asm__ __volatile__( + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:\n" + " bcr 15,0\n" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); +#else + __asm__ __volatile__( + " lgr %0,%3\n" + " csg %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:\n" + " bcr 15,0\n" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); +#endif + + return retval == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + int retval; + +#ifndef __s390x__ + __asm__ __volatile__( + " bcr 15,0\n" + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); +#else + __asm__ __volatile__( + " bcr 15,0\n" + " lgr %0,%3\n" + " csg %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (_q_value) + : "a" (&_q_value), "d" (expectedValue) , "d" (newValue), + "m" (_q_value) : "cc", "memory" ); +#endif + + return retval == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ +#ifndef __s390x__ + return (T*)__CS_OLD_LOOP(reinterpret_cast<volatile long*>(_q_value), (int)newValue, "lr", + "", "bcr 15,0\n"); +#else + return (T*)__CSG_OLD_LOOP(reinterpret_cast<volatile long*>(_q_value), (long)newValue, "lgr", + "", "bcr 15,0\n"); +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ +#ifndef __s390x__ + return (T*)__CS_OLD_LOOP(reinterpret_cast<volatile long*>(_q_value), (int)newValue, "lr", "", ""); +#else + return (T*)__CSG_OLD_LOOP(reinterpret_cast<volatile long*>(_q_value), (long)newValue, "lgr", "", ""); +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ +#ifndef __s390x__ + return (T*)__CS_OLD_LOOP(reinterpret_cast<volatile long*>(_q_value), (int)newValue, "lr", + "bcr 15,0 \n", ""); +#else + return (T*)__CSG_OLD_LOOP(reinterpret_cast<volatile long*>(_q_value), (long)newValue, "lgr", + "bcr 15,0\n", ""); +#endif +} + +template <typename T> +Q_INLINE_TEMPLATE T* QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return fetchAndStoreAcquire(newValue); +} + + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +#undef __GNU_EXTENSION + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_S390_H diff --git a/src/corelib/arch/qatomic_sh.h b/src/corelib/arch/qatomic_sh.h new file mode 100644 index 0000000..b78ad45 --- /dev/null +++ b/src/corelib/arch/qatomic_sh.h @@ -0,0 +1,330 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_SH_H +#define QATOMIC_SH_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +extern Q_CORE_EXPORT volatile char qt_atomic_lock; +Q_CORE_EXPORT void qt_atomic_yield(int *count); + +inline int qt_atomic_tasb(volatile char *ptr) +{ + register int ret; + asm volatile("tas.b @%2\n" + "movt %0" + : "=&r"(ret), "=m"(*ptr) + : "r"(ptr) + : "cc", "memory"); + return ret; +} + +// Reference counting + +inline bool QBasicAtomicInt::ref() +{ + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + int originalValue = _q_value++; + qt_atomic_lock = 0; + return originalValue != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + int originalValue = _q_value--; + qt_atomic_lock = 0; + return originalValue != 1; +} + +// Test and set for integers + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + bool returnValue = false; + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + qt_atomic_lock = 0; + return returnValue; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for integers + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + int originalValue = _q_value; + _q_value = newValue; + qt_atomic_lock = 0; + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for integers + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + int originalValue = _q_value; + _q_value += valueToAdd; + qt_atomic_lock = 0; + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +// Test and set for pointers + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + bool returnValue = false; + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + if (_q_value == expectedValue) { + _q_value = newValue; + returnValue = true; + } + qt_atomic_lock = 0; + return returnValue; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +// Fetch and store for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + T *originalValue = _q_value; + _q_value = newValue; + qt_atomic_lock = 0; + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +// Fetch and add for pointers + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + int count = 0; + while (qt_atomic_tasb(&qt_atomic_lock) == 0) + qt_atomic_yield(&count); + T *originalValue = (_q_value); + _q_value += valueToAdd; + qt_atomic_lock = 0; + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_SH_H diff --git a/src/corelib/arch/qatomic_sh4a.h b/src/corelib/arch/qatomic_sh4a.h new file mode 100644 index 0000000..54371cd --- /dev/null +++ b/src/corelib/arch/qatomic_sh4a.h @@ -0,0 +1,537 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_SH4A_H +#define QATOMIC_SH4A_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + + +QT_END_NAMESPACE + +QT_END_HEADER + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +QT_BEGIN_NAMESPACE + +#if !defined(Q_CC_GNU) +# error "SH-4A support has not been added for this compiler" +#else + +inline bool QBasicAtomicInt::ref() +{ + register int newValue asm("r0"); + asm volatile("0:\n" + "movli.l @%[_q_value], %[newValue]\n" + "add #1,%[newValue]\n" + "movco.l %[newValue], @%[_q_value]\n" + "bf 0b\n" + : [newValue] "=&r" (newValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value) + : "cc", "memory"); + return newValue != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + register int newValue asm("r0"); + asm volatile("0:\n" + "movli.l @%[_q_value], %[newValue]\n" + "add #-1,%[newValue]\n" + "movco.l %[newValue], @%[_q_value]\n" + "bf 0b\n" + : [newValue] "=&r" (newValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value) + : "cc", "memory"); + return newValue != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + register int result; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "xor %[expectedValue], r0\n" + "cmp/eq #0, r0\n" + "bf/s 0f\n" + "mov r0, %[result]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "0:\n" + : [result] "=&r" (result), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + register int result; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "xor %[expectedValue], r0\n" + "cmp/eq #0, r0\n" + "bf/s 0f\n" + "mov r0, %[result]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "synco\n" + "0:\n" + : [result] "=&r" (result), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + register int result; + asm volatile("synco\n" + "0:\n" + "movli.l @%[_q_value], r0\n" + "xor %[expectedValue], r0\n" + "cmp/eq #0, r0\n" + "bf/s 0f\n" + "mov r0, %[result]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "0:\n" + : [result] "=&r" (result), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return result == 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + register int originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + register int originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "synco\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + register int originalValue; + asm volatile("synco\n" + "0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + register int originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "add %[valueToAdd], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [valueToAdd] "r" (valueToAdd) + : "r0", "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + register int originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "add %[valueToAdd], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "synco\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [valueToAdd] "r" (valueToAdd) + : "r0", "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + register int originalValue; + asm volatile("synco\n" + "0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "add %[valueToAdd], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [valueToAdd] "r" (valueToAdd) + : "r0", "cc", "memory"); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + register T *result; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "xor %[expectedValue], r0\n" + "cmp/eq #0, r0\n" + "bf/s 0f\n" + "mov r0, %[result]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "0:\n" + : [result] "=&r" (result), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + register T *result; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "xor %[expectedValue], r0\n" + "cmp/eq #0, r0\n" + "bf/s 0f\n" + "mov r0, %[result]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "synco\n" + "0:\n" + : [result] "=&r" (result), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + register T *result; + asm volatile("synco\n" + "0:\n" + "movli.l @%[_q_value], r0\n" + "xor %[expectedValue], r0\n" + "cmp/eq #0, r0\n" + "bf/s 0f\n" + "mov r0, %[result]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "0:\n" + : [result] "=&r" (result), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [expectedValue] "r" (expectedValue), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return result == 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return testAndSetAcquire(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + register T *originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + register T *originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "synco\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + register T *originalValue; + asm volatile("synco\n" + "0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "mov %[newValue], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [newValue] "r" (newValue) + : "r0", "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return fetchAndStoreAcquire(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + register T *originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "add %[valueToAdd], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "r0", "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + register T *originalValue; + asm volatile("0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "add %[valueToAdd], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + "synco\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "r0", "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + register T *originalValue; + asm volatile("synco\n" + "0:\n" + "movli.l @%[_q_value], r0\n" + "mov r0, %[originalValue]\n" + "add %[valueToAdd], r0\n" + "movco.l r0, @%[_q_value]\n" + "bf 0b\n" + : [originalValue] "=&r" (originalValue), + "+m" (_q_value) + : [_q_value] "r" (&_q_value), + [valueToAdd] "r" (valueToAdd * sizeof(T)) + : "r0", "cc", "memory"); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return fetchAndAddAcquire(valueToAdd); +} + +#endif // Q_CC_GNU + +#endif // QATOMIC_SH4A_H diff --git a/src/corelib/arch/qatomic_sparc.h b/src/corelib/arch/qatomic_sparc.h new file mode 100644 index 0000000..4129f14 --- /dev/null +++ b/src/corelib/arch/qatomic_sparc.h @@ -0,0 +1,525 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_SPARC_H +#define QATOMIC_SPARC_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#if defined(_LP64) + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +extern "C" { + Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr); + + Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, + int expected, + int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, + int expected, + int newval); + + Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); + Q_CORE_EXPORT int q_atomic_fetch_and_store_acquire_int(volatile int *ptr, int newval); + Q_CORE_EXPORT int q_atomic_fetch_and_store_release_int(volatile int *ptr, int newval); + + Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value); + Q_CORE_EXPORT int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int value); + Q_CORE_EXPORT int q_atomic_fetch_and_add_release_int(volatile int *ptr, int value); + + Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval); + Q_CORE_EXPORT int q_atomic_test_and_set_acquire_ptr(volatile void *ptr, + void *expected, + void *newval); + Q_CORE_EXPORT int q_atomic_test_and_set_release_ptr(volatile void *ptr, + void *expected, + void *newval); + + Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval); + Q_CORE_EXPORT void *q_atomic_fetch_and_store_acquire_ptr(volatile void *ptr, void *newval); + Q_CORE_EXPORT void *q_atomic_fetch_and_store_release_ptr(volatile void *ptr, void *newval); + + Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, int value); + Q_CORE_EXPORT void *q_atomic_fetch_and_add_acquire_ptr(volatile void *ptr, int value); + Q_CORE_EXPORT void *q_atomic_fetch_and_add_release_ptr(volatile void *ptr, int value); +} + +inline bool QBasicAtomicInt::ref() +{ + return fetchAndAddRelaxed(1) != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + return fetchAndAddRelaxed(-1) != 1; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return q_atomic_set_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return q_atomic_fetch_and_store_release_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int newValue) +{ + return q_atomic_fetch_and_add_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int newValue) +{ + return q_atomic_fetch_and_add_acquire_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int newValue) +{ + return q_atomic_fetch_and_add_release_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int newValue) +{ + return q_atomic_fetch_and_add_acquire_int(&_q_value, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +template <typename T> +Q_INLINE_TEMPLATE +T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +#else + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return false; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return false; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_NOT_NATIVE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return false; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return false; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return false; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return false; } + +extern "C" { + Q_CORE_EXPORT int q_atomic_lock_int(volatile int *addr); + Q_CORE_EXPORT int q_atomic_lock_ptr(volatile void *addr); + Q_CORE_EXPORT void q_atomic_unlock(volatile void *addr, int value); + Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); + Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval); +} // extern "C" + +inline bool QBasicAtomicInt::ref() +{ + const int val = q_atomic_lock_int(&_q_value); + q_atomic_unlock(&_q_value, val + 1); + return val != -1; +} + +inline bool QBasicAtomicInt::deref() +{ + const int val = q_atomic_lock_int(&_q_value); + q_atomic_unlock(&_q_value, val - 1); + return val != 1; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + int val = q_atomic_lock_int(&_q_value); + if (val == expectedValue) { + q_atomic_unlock(&_q_value, newValue); + return true; + } + q_atomic_unlock(&_q_value, val); + return false; +} + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return q_atomic_set_int(&_q_value, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + const int originalValue = q_atomic_lock_int(&_q_value); + q_atomic_unlock(&_q_value, originalValue + valueToAdd); + return originalValue; +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + T *val = reinterpret_cast<T *>(q_atomic_lock_ptr(&_q_value)); + if (val == expectedValue) { + q_atomic_unlock(&_q_value, reinterpret_cast<int>(newValue)); + return true; + } + q_atomic_unlock(&_q_value, reinterpret_cast<int>(val)); + return false; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + T *originalValue = reinterpret_cast<T *>(q_atomic_lock_ptr(&_q_value)); + q_atomic_unlock(&_q_value, int(originalValue + valueToAdd)); + return originalValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +#endif // _LP64 + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_SPARC_H diff --git a/src/corelib/arch/qatomic_windows.h b/src/corelib/arch/qatomic_windows.h new file mode 100644 index 0000000..ac26b4f --- /dev/null +++ b/src/corelib/arch/qatomic_windows.h @@ -0,0 +1,564 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_WINDOWS_H +#define QATOMIC_WINDOWS_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return true; } + +#if defined(Q_CC_MSVC) + +// MSVC++ 6.0 doesn't generate correct code when optimizations are turned on! +#if _MSC_VER < 1300 && defined (_M_IX86) + +inline bool QBasicAtomicInt::ref() +{ + volatile int *pointer = &_q_value; + unsigned char retVal; + __asm { + mov ECX,pointer + lock inc DWORD ptr[ECX] + setne retVal + } + return retVal != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + volatile int *pointer = &_q_value; + unsigned char retVal; + __asm { + mov ECX,pointer + lock dec DWORD ptr[ECX] + setne retVal + } + return retVal != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + volatile int *pointer = &_q_value; + __asm { + mov EDX,pointer + mov EAX,expectedValue + mov ECX,newValue + lock cmpxchg dword ptr[EDX],ECX + mov newValue,EAX + } + return newValue == expectedValue; +} + + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + volatile int *pointer = &_q_value; + __asm { + mov EDX,pointer + mov ECX,newValue + lock xchg dword ptr[EDX],ECX + mov newValue,ECX + } + return newValue; +} + + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + volatile int *pointer = &_q_value; + __asm { + mov EDX,pointer + mov ECX,valueToAdd + lock xadd dword ptr[EDX],ECX + mov valueToAdd,ECX + } + return valueToAdd; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + volatile void *pointer = &_q_value; + __asm { + mov EDX,pointer + mov EAX,expectedValue + mov ECX,newValue + lock cmpxchg dword ptr[EDX],ECX + mov newValue,EAX + } + return newValue == expectedValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + volatile void *pointer = &_q_value; + __asm { + mov EDX,pointer + mov ECX,newValue + lock xchg dword ptr[EDX],ECX + mov newValue,ECX + } + return reinterpret_cast<T *>(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + volatile void *pointer = &_q_value; + valueToAdd *= sizeof(T); + __asm { + mov EDX,pointer + mov ECX,valueToAdd + lock xadd dword ptr[EDX],ECX + mov pointer,ECX + } + return reinterpret_cast<T *>(const_cast<void *>(pointer)); +} + +#else + +#if !defined(Q_OS_WINCE) +// use compiler intrinsics for all atomic functions +extern "C" { + long __cdecl _InterlockedIncrement(volatile long *); + long __cdecl _InterlockedDecrement(volatile long *); + long __cdecl _InterlockedExchange(volatile long *, long); + long __cdecl _InterlockedCompareExchange(volatile long *, long, long); + long __cdecl _InterlockedExchangeAdd(volatile long *, long); +} +# pragma intrinsic (_InterlockedIncrement) +# pragma intrinsic (_InterlockedDecrement) +# pragma intrinsic (_InterlockedExchange) +# pragma intrinsic (_InterlockedCompareExchange) +# pragma intrinsic (_InterlockedExchangeAdd) + +# ifndef _M_IX86 +extern "C" { + void *_InterlockedCompareExchangePointer(void * volatile *, void *, void *); + void *_InterlockedExchangePointer(void * volatile *, void *); + __int64 _InterlockedExchangeAdd64(__int64 volatile * Addend, __int64 Value); +} +# pragma intrinsic (_InterlockedCompareExchangePointer) +# pragma intrinsic (_InterlockedExchangePointer) +# pragma intrinsic (_InterlockedExchangeAdd64) +# define _InterlockedExchangeAddPointer(a,b) \ + _InterlockedExchangeAdd64(reinterpret_cast<volatile __int64 *>(a), __int64(b)) +# else +# define _InterlockedCompareExchangePointer(a,b,c) \ + _InterlockedCompareExchange(reinterpret_cast<volatile long *>(a), long(b), long(c)) +# define _InterlockedExchangePointer(a, b) \ + _InterlockedExchange(reinterpret_cast<volatile long *>(a), long(b)) +# define _InterlockedExchangeAddPointer(a,b) \ + _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(a), long(b)) +# endif +inline bool QBasicAtomicInt::ref() +{ + return _InterlockedIncrement(reinterpret_cast<volatile long *>(&_q_value)) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return _InterlockedDecrement(reinterpret_cast<volatile long *>(&_q_value)) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return _InterlockedCompareExchange(reinterpret_cast<volatile long *>(&_q_value), newValue, expectedValue) == expectedValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return _InterlockedExchange(reinterpret_cast<volatile long *>(&_q_value), newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return _InterlockedExchangeAdd(reinterpret_cast<volatile long *>(&_q_value), valueToAdd); +} + +#if defined(Q_CC_MSVC) +#pragma warning( push ) +#pragma warning( disable : 4311 ) // ignoring the warning from /Wp64 +#endif + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return (_InterlockedCompareExchangePointer(reinterpret_cast<void * volatile *>(&_q_value), + newValue, expectedValue) == +#ifndef _M_IX86 + (void *) +#else + (long) +#endif + (expectedValue)); +} + +#if defined(Q_CC_MSVC) +#pragma warning( pop ) +#endif + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return reinterpret_cast<T *>(_InterlockedExchangePointer(reinterpret_cast<void * volatile *>(&_q_value), newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(_InterlockedExchangeAddPointer(reinterpret_cast<void * volatile *>(&_q_value), valueToAdd * sizeof(T))); +} + +#else // Q_OS_WINCE + +#if _WIN32_WCE < 0x600 && defined(_X86_) +// For X86 Windows CE build we need to include winbase.h to be able +// to catch the inline functions which overwrite the regular +// definitions inside of coredll.dll. Though one could use the +// original version of Increment/Decrement, the others are not +// exported at all. +#include <winbase.h> +#else + +#if _WIN32_WCE >= 0x600 +#define Q_ARGUMENT_TYPE volatile +# if defined(_X86_) +# define InterlockedIncrement _InterlockedIncrement +# define InterlockedDecrement _InterlockedDecrement +# define InterlockedExchange _InterlockedExchange +# define InterlockedCompareExchange _InterlockedCompareExchange +# define InterlockedExchangeAdd _InterlockedExchangeAdd +# endif +#else +#define Q_ARGUMENT_TYPE +#endif + +extern "C" { +long __cdecl InterlockedIncrement(long Q_ARGUMENT_TYPE * lpAddend); +long __cdecl InterlockedDecrement(long Q_ARGUMENT_TYPE * lpAddend); +long __cdecl InterlockedExchange(long Q_ARGUMENT_TYPE * Target, long Value); +long __cdecl InterlockedCompareExchange(long Q_ARGUMENT_TYPE * Destination, long Exchange, long Comperand); +long __cdecl InterlockedExchangeAdd(long Q_ARGUMENT_TYPE * Addend, long Value); +} + +#if _WIN32_WCE >= 0x600 && defined(_X86_) +# pragma intrinsic (_InterlockedIncrement) +# pragma intrinsic (_InterlockedDecrement) +# pragma intrinsic (_InterlockedExchange) +# pragma intrinsic (_InterlockedCompareExchange) +# pragma intrinsic (_InterlockedExchangeAdd) +#endif + +#endif + + +inline bool QBasicAtomicInt::ref() +{ + return InterlockedIncrement((long*)(&_q_value)) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return InterlockedDecrement((long*)(&_q_value)) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return InterlockedCompareExchange((long*)(&_q_value), newValue, expectedValue) == expectedValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + return InterlockedExchange((long*)(&_q_value), newValue); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return InterlockedExchangeAdd((long*)(&_q_value), valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return (InterlockedCompareExchange((long*)(&_q_value), + (long)newValue, (long)expectedValue) == + (long)(expectedValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return reinterpret_cast<T *>(InterlockedExchange((long*)(&_q_value), (long)newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(InterlockedExchangeAdd((long*)(&_q_value), valueToAdd * sizeof(T))); +} + +#endif //Q_OS_WINCE + +#endif // _MSC_VER ... + +#else + +// __INTERLOCKED_DECLARED is defined in MinGW's winbase.h. Simply, preferrably we use +// MinGW's definition, such that we pick up variations in the headers. +#ifndef __INTERLOCKED_DECLARED +#define __INTERLOCKED_DECLARED +extern "C" { + __declspec(dllimport) long __stdcall InterlockedCompareExchange(long *, long, long); + __declspec(dllimport) long __stdcall InterlockedIncrement(long *); + __declspec(dllimport) long __stdcall InterlockedDecrement(long *); + __declspec(dllimport) long __stdcall InterlockedExchange(long *, long); + __declspec(dllimport) long __stdcall InterlockedExchangeAdd(long *, long); +} +#endif + +inline bool QBasicAtomicInt::ref() +{ + return InterlockedIncrement(reinterpret_cast<long *>(const_cast<int *>(&_q_value))) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return InterlockedDecrement(reinterpret_cast<long *>(const_cast<int *>(&_q_value))) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + return InterlockedCompareExchange(reinterpret_cast<long *>(const_cast<int *>(&_q_value)), newValue, expectedValue) == expectedValue; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ return InterlockedExchange(reinterpret_cast<long *>(const_cast<int *>(&_q_value)), newValue); } + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + return InterlockedExchangeAdd(reinterpret_cast<long *>(const_cast<int *>(&_q_value)), valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T* newValue) +{ return InterlockedCompareExchange(reinterpret_cast<long *>(const_cast<T **>(&_q_value)), + reinterpret_cast<long>(newValue), + reinterpret_cast<long>(expectedValue)) == reinterpret_cast<long>(expectedValue); } + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T* newValue) +{ return reinterpret_cast<T *>(InterlockedExchange(reinterpret_cast<long *>(const_cast<T **>(&_q_value)), + reinterpret_cast<long>(newValue))); } + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ return reinterpret_cast<T *>(InterlockedExchangeAdd(reinterpret_cast<long *>(const_cast<T **>(&_q_value)), valueToAdd * sizeof(T))); } + +#endif // Q_CC_GNU + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_WINDOWS_H diff --git a/src/corelib/arch/qatomic_windowsce.h b/src/corelib/arch/qatomic_windowsce.h new file mode 100644 index 0000000..95ecba8 --- /dev/null +++ b/src/corelib/arch/qatomic_windowsce.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOWSCE_QATOMIC_H +#define WINDOWSCE_QATOMIC_H + +#include <QtCore/qglobal.h> +QT_BEGIN_HEADER + +#if defined(QT_ARCH_WINDOWSCE) +#include "QtCore/qatomic_windows.h" +#endif + +QT_END_HEADER + +#endif // QATOMIC_ARCH_H + + diff --git a/src/corelib/arch/qatomic_x86_64.h b/src/corelib/arch/qatomic_x86_64.h new file mode 100644 index 0000000..79d8a07 --- /dev/null +++ b/src/corelib/arch/qatomic_x86_64.h @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QATOMIC_X86_64_H +#define QATOMIC_X86_64_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isReferenceCountingNative() +{ return true; } +inline bool QBasicAtomicInt::isReferenceCountingWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_TEST_AND_SET_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isTestAndSetNative() +{ return true; } +inline bool QBasicAtomicInt::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndStoreNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_WAIT_FREE + +inline bool QBasicAtomicInt::isFetchAndAddNative() +{ return true; } +inline bool QBasicAtomicInt::isFetchAndAddWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree() +{ return true; } + +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative() +{ return true; } +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() +{ return true; } + +#if defined(Q_CC_GNU) || defined(Q_CC_INTEL) + +inline bool QBasicAtomicInt::ref() +{ + unsigned char ret; + asm volatile("lock\n" + "incl %0\n" + "setne %1" + : "=m" (_q_value), "=qm" (ret) + : "m" (_q_value) + : "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + unsigned char ret; + asm volatile("lock\n" + "decl %0\n" + "setne %1" + : "=m" (_q_value), "=qm" (ret) + : "m" (_q_value) + : "memory"); + return ret != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue) +{ + unsigned char ret; + asm volatile("lock\n" + "cmpxchgl %3,%2\n" + "sete %1\n" + : "=a" (newValue), "=qm" (ret), "+m" (_q_value) + : "r" (newValue), "0" (expectedValue) + : "memory"); + return ret != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue) +{ + asm volatile("xchgl %0,%1" + : "=r" (newValue), "+m" (_q_value) + : "0" (newValue) + : "memory"); + return newValue; +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd) +{ + asm volatile("lock\n" + "xaddl %0,%1" + : "=r" (valueToAdd), "+m" (_q_value) + : "0" (valueToAdd) + : "memory"); + return valueToAdd; +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + unsigned char ret; + asm volatile("lock\n" + "cmpxchgq %3,%2\n" + "sete %1\n" + : "=a" (newValue), "=qm" (ret), "+m" (_q_value) + : "r" (newValue), "0" (expectedValue) + : "memory"); + return ret != 0; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + asm volatile("xchgq %0,%1" + : "=r" (newValue), "+m" (_q_value) + : "0" (newValue) + : "memory"); + return newValue; +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + asm volatile("lock\n" + "xaddq %0,%1" + : "=r" (valueToAdd), "+m" (_q_value) + : "0" (valueToAdd * sizeof(T)) + : "memory"); + return reinterpret_cast<T *>(valueToAdd); +} + +#else // !Q_CC_INTEL && !Q_CC_GNU + +extern "C" { + Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval); + Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval); + Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr); + Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval); + Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval); + Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value); + Q_CORE_EXPORT void *q_atomic_fetch_and_add_ptr(volatile void *ptr, qptrdiff value); +} // extern "C" + +inline bool QBasicAtomicInt::ref() +{ + return q_atomic_increment(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::deref() +{ + return q_atomic_decrement(&_q_value) != 0; +} + +inline bool QBasicAtomicInt::testAndSetOrdered(int expected, int newval) +{ + return q_atomic_test_and_set_int(&_q_value, expected, newval) != 0; +} + +inline int QBasicAtomicInt::fetchAndStoreOrdered(int newval) +{ + return q_atomic_set_int(&_q_value, newval); +} + +inline int QBasicAtomicInt::fetchAndAddOrdered(int aValue) +{ + return q_atomic_fetch_and_add_int(&_q_value, aValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue) +{ + return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue) +{ + return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue)); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd) +{ + return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, valueToAdd * sizeof(T))); +} + +#endif // Q_CC_GNU || Q_CC_INTEL + +inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue) +{ + return testAndSetOrdered(expectedValue, newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue) +{ + return fetchAndStoreOrdered(newValue); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +template <typename T> +Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd) +{ + return fetchAndAddOrdered(valueToAdd); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QATOMIC_X86_64_H diff --git a/src/corelib/arch/s390/arch.pri b/src/corelib/arch/s390/arch.pri new file mode 100644 index 0000000..45cc578 --- /dev/null +++ b/src/corelib/arch/s390/arch.pri @@ -0,0 +1,3 @@ +# +# S390 architecture +# diff --git a/src/corelib/arch/sh/arch.pri b/src/corelib/arch/sh/arch.pri new file mode 100644 index 0000000..67fbb16 --- /dev/null +++ b/src/corelib/arch/sh/arch.pri @@ -0,0 +1,4 @@ +# +# SH (Renesas SuperH) architecture +# +SOURCES += $$QT_ARCH_CPP/qatomic_sh.cpp diff --git a/src/corelib/arch/sh/qatomic_sh.cpp b/src/corelib/arch/sh/qatomic_sh.cpp new file mode 100644 index 0000000..00a32ee --- /dev/null +++ b/src/corelib/arch/sh/qatomic_sh.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qglobal.h> + +#include <unistd.h> +#ifdef _POSIX_PRIORITY_SCHEDULING +# include <sched.h> +#endif +#include <time.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +Q_CORE_EXPORT volatile char qt_atomic_lock = 0; + +Q_CORE_EXPORT void qt_atomic_yield(int *count) +{ +#ifdef _POSIX_PRIORITY_SCHEDULING + if((*count)++ < 50) { + sched_yield(); + } else +#endif + { + struct timespec tm; + tm.tv_sec = 0; + tm.tv_nsec = 2000001; + nanosleep(&tm, NULL); + *count = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/corelib/arch/sh4a/arch.pri b/src/corelib/arch/sh4a/arch.pri new file mode 100644 index 0000000..19d5e04 --- /dev/null +++ b/src/corelib/arch/sh4a/arch.pri @@ -0,0 +1,3 @@ +# +# SH-4A (Renesas SuperH) architecture +# diff --git a/src/corelib/arch/sparc/arch.pri b/src/corelib/arch/sparc/arch.pri new file mode 100644 index 0000000..3113dd3 --- /dev/null +++ b/src/corelib/arch/sparc/arch.pri @@ -0,0 +1,10 @@ +# +# SPARC architecture +# +*-64 { + SOURCES += $$QT_ARCH_CPP/qatomic64.s +} +else { + SOURCES += $$QT_ARCH_CPP/qatomic32.s \ + $$QT_ARCH_CPP/qatomic_sparc.cpp +} diff --git a/src/corelib/arch/sparc/qatomic32.s b/src/corelib/arch/sparc/qatomic32.s new file mode 100644 index 0000000..f0ab0d1 --- /dev/null +++ b/src/corelib/arch/sparc/qatomic32.s @@ -0,0 +1,63 @@ + .section ".text" + + .align 4 + .type q_atomic_trylock_int,#function + .global q_atomic_trylock_int +q_atomic_trylock_int: + sethi %hi(-2147483648),%o2 + swap [%o0],%o2 + retl + mov %o2,%o0 + .size q_atomic_trylock_int,.-q_atomic_trylock_int + + + + + .align 4 + .type q_atomic_trylock_ptr,#function + .global q_atomic_trylock_ptr +q_atomic_trylock_ptr: + mov -1, %o2 + swap [%o0], %o2 + retl + mov %o2, %o0 + .size q_atomic_trylock_ptr,.-q_atomic_trylock_ptr + + + + + .align 4 + .type q_atomic_unlock,#function + .global q_atomic_unlock +q_atomic_unlock: + stbar + retl + st %o1,[%o0] + .size q_atomic_unlock,.-q_atomic_unlock + + + + + .align 4 + .type q_atomic_set_int,#function + .global q_atomic_set_int +q_atomic_set_int: + swap [%o0],%o1 + stbar + retl + mov %o1,%o0 + .size q_atomic_set_int,.-q_atomic_set_int + + + + + .align 4 + .type q_atomic_set_ptr,#function + .global q_atomic_set_ptr +q_atomic_set_ptr: + swap [%o0],%o1 + stbar + retl + mov %o1,%o0 + .size q_atomic_set_ptr,.-q_atomic_set_ptr + diff --git a/src/corelib/arch/sparc/qatomic64.s b/src/corelib/arch/sparc/qatomic64.s new file mode 100644 index 0000000..edd1716 --- /dev/null +++ b/src/corelib/arch/sparc/qatomic64.s @@ -0,0 +1,287 @@ + .section ".text" + + .align 4 + .type q_atomic_test_and_set_int,#function + .global q_atomic_test_and_set_int +q_atomic_test_and_set_int: + cas [%o0],%o1,%o2 + cmp %o1,%o2 + clr %o0 + retl + move %icc,1,%o0 + .size q_atomic_test_and_set_int,.-q_atomic_test_and_set_int + + .align 4 + .type q_atomic_test_and_set_acquire_int,#function + .global q_atomic_test_and_set_acquire_int +q_atomic_test_and_set_acquire_int: + cas [%o0],%o1,%o2 + cmp %o1,%o2 + clr %o0 + membar #LoadLoad | #LoadStore + retl + move %icc,1,%o0 + .size q_atomic_test_and_set_acquire_int,.-q_atomic_test_and_set_acquire_int + + .align 4 + .type q_atomic_test_and_set_release_int,#function + .global q_atomic_test_and_set_release_int +q_atomic_test_and_set_release_int: + membar #LoadStore | #StoreStore + cas [%o0],%o1,%o2 + cmp %o1,%o2 + clr %o0 + retl + move %icc,1,%o0 + .size q_atomic_test_and_set_release_int,.-q_atomic_test_and_set_release_int + + .align 4 + .type q_atomic_test_and_set_ptr,#function + .global q_atomic_test_and_set_ptr +q_atomic_test_and_set_ptr: + casx [%o0],%o1,%o2 + cmp %o1,%o2 + clr %o0 + retl + move %icc,1,%o0 + .size q_atomic_test_and_set_ptr,.-q_atomic_test_and_set_ptr + + .align 4 + .type q_atomic_increment,#function + .global q_atomic_increment +q_atomic_increment: +q_atomic_increment_retry: + ld [%o0],%o3 + add %o3,1,%o4 + cas [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_increment_retry + nop + cmp %o4,-1 + clr %o0 + retl + movne %icc,1,%o0 + .size q_atomic_increment,.-q_atomic_increment + + .align 4 + .type q_atomic_decrement,#function + .global q_atomic_decrement +q_atomic_decrement: +q_atomic_decrement_retry: + ld [%o0],%o3 + add %o3,-1,%o4 + cas [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_decrement_retry + nop + cmp %o4,1 + clr %o0 + retl + movne %icc,1,%o0 + .size q_atomic_decrement,.-q_atomic_decrement + + .align 4 + .type q_atomic_set_int,#function + .global q_atomic_set_int +q_atomic_set_int: +q_atomic_set_int_retry: + ld [%o0],%o2 + cas [%o0],%o2,%o1 + cmp %o2,%o1 + bne q_atomic_set_int_retry + nop + retl + mov %o1,%o0 + .size q_atomic_set_int,.-q_atomic_set_int + + .align 4 + .type q_atomic_set_ptr,#function + .global q_atomic_set_ptr +q_atomic_set_ptr: +q_atomic_set_ptr_retry: + ldx [%o0],%o2 + casx [%o0],%o2,%o1 + cmp %o2,%o1 + bne q_atomic_set_ptr_retry + nop + retl + mov %o1,%o0 + .size q_atomic_set_ptr,.-q_atomic_set_ptr + + .align 4 + .type q_atomic_fetch_and_add_int,#function + .global q_atomic_fetch_and_add_int +q_atomic_fetch_and_add_int: +q_atomic_fetch_and_add_int_retry: + ld [%o0],%o3 + add %o3,%o1,%o4 + cas [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_fetch_and_add_int_retry + nop + retl + mov %o3,%o0 + .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int + + .align 4 + .type q_atomic_fetch_and_add_acquire_int,#function + .global q_atomic_fetch_and_add_acquire_int +q_atomic_fetch_and_add_acquire_int: +q_atomic_fetch_and_add_acquire_int_retry: + ld [%o0],%o3 + add %o3,%o1,%o4 + cas [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_fetch_and_add_acquire_int_retry + nop + membar #LoadLoad | #LoadStore + retl + mov %o3,%o0 + .size q_atomic_fetch_and_add_acquire_int,.-q_atomic_fetch_and_add_acquire_int + + .align 4 + .type q_atomic_fetch_and_add_release_int,#function + .global q_atomic_fetch_and_add_release_int +q_atomic_fetch_and_add_release_int: +q_atomic_fetch_and_add_release_int_retry: + membar #LoadStore | #StoreStore + ld [%o0],%o3 + add %o3,%o1,%o4 + cas [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_fetch_and_add_release_int_retry + nop + retl + mov %o3,%o0 + .size q_atomic_fetch_and_add_release_int,.-q_atomic_fetch_and_add_release_int + + .align 4 + .type q_atomic_fetch_and_store_acquire_int,#function + .global q_atomic_fetch_and_store_acquire_int +q_atomic_fetch_and_store_acquire_int: +q_atomic_fetch_and_store_acquire_int_retry: + ld [%o0],%o2 + cas [%o0],%o2,%o1 + cmp %o2,%o1 + bne q_atomic_fetch_and_store_acquire_int_retry + nop + membar #LoadLoad | #LoadStore + retl + mov %o1,%o0 + .size q_atomic_fetch_and_store_acquire_int,.-q_atomic_fetch_and_store_acquire_int + + .align 4 + .type q_atomic_fetch_and_store_release_int,#function + .global q_atomic_fetch_and_store_release_int +q_atomic_fetch_and_store_release_int: +q_atomic_fetch_and_store_release_int_retry: + membar #LoadStore | #StoreStore + ld [%o0],%o2 + cas [%o0],%o2,%o1 + cmp %o2,%o1 + bne q_atomic_fetch_and_store_release_int_retry + nop + retl + mov %o1,%o0 + .size q_atomic_fetch_and_store_release_int,.-q_atomic_fetch_and_store_release_int + + .align 4 + .type q_atomic_test_and_set_acquire_ptr,#function + .global q_atomic_test_and_set_acquire_ptr +q_atomic_test_and_set_acquire_ptr: + casx [%o0],%o1,%o2 + cmp %o1,%o2 + clr %o0 + membar #LoadLoad | #LoadStore + retl + move %icc,1,%o0 + .size q_atomic_test_and_set_acquire_ptr,.-q_atomic_test_and_set_acquire_ptr + + .align 4 + .type q_atomic_test_and_set_release_ptr,#function + .global q_atomic_test_and_set_release_ptr +q_atomic_test_and_set_release_ptr: + membar #LoadStore | #StoreStore + casx [%o0],%o1,%o2 + cmp %o1,%o2 + clr %o0 + retl + move %icc,1,%o0 + .size q_atomic_test_and_set_release_ptr,.-q_atomic_test_and_set_release_ptr + + .align 4 + .type q_atomic_fetch_and_store_acquire_ptr,#function + .global q_atomic_fetch_and_store_acquire_ptr +q_atomic_fetch_and_store_acquire_ptr: +q_atomic_fetch_and_store_acquire_ptr_retry: + ldx [%o0],%o2 + casx [%o0],%o2,%o1 + cmp %o2,%o1 + bne q_atomic_fetch_and_store_acquire_ptr_retry + nop + membar #LoadLoad | #LoadStore + retl + mov %o1,%o0 + .size q_atomic_fetch_and_store_acquire_ptr,.-q_atomic_fetch_and_store_acquire_ptr + + .align 4 + .type q_atomic_fetch_and_store_release_ptr,#function + .global q_atomic_fetch_and_store_release_ptr +q_atomic_fetch_and_store_release_ptr: +q_atomic_fetch_and_store_release_ptr_retry: + membar #LoadStore | #StoreStore + ldx [%o0],%o2 + casx [%o0],%o2,%o1 + cmp %o2,%o1 + bne q_atomic_fetch_and_store_release_ptr_retry + nop + retl + mov %o1,%o0 + .size q_atomic_fetch_and_store_release_ptr,.-q_atomic_fetch_and_store_release_ptr + + .align 4 + .type q_atomic_fetch_and_add_ptr,#function + .global q_atomic_fetch_and_add_ptr +q_atomic_fetch_and_add_ptr: +q_atomic_fetch_and_add_ptr_retry: + ldx [%o0],%o3 + add %o3,%o1,%o4 + casx [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_fetch_and_add_ptr_retry + nop + retl + mov %o3,%o0 + .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr + + .align 4 + .type q_atomic_fetch_and_add_acquire_ptr,#function + .global q_atomic_fetch_and_add_acquire_ptr +q_atomic_fetch_and_add_acquire_ptr: +q_atomic_fetch_and_add_acquire_ptr_retry: + ldx [%o0],%o3 + add %o3,%o1,%o4 + casx [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_fetch_and_add_acquire_ptr_retry + nop + membar #LoadLoad | #LoadStore + retl + mov %o3,%o0 + .size q_atomic_fetch_and_add_acquire_ptr,.-q_atomic_fetch_and_add_acquire_ptr + + .align 4 + .type q_atomic_fetch_and_add_release_ptr,#function + .global q_atomic_fetch_and_add_release_ptr +q_atomic_fetch_and_add_release_ptr: +q_atomic_fetch_and_add_release_ptr_retry: + membar #LoadStore | #StoreStore + ldx [%o0],%o3 + add %o3,%o1,%o4 + casx [%o0],%o3,%o4 + cmp %o3,%o4 + bne q_atomic_fetch_and_add_release_ptr_retry + nop + retl + mov %o3,%o0 + .size q_atomic_fetch_and_add_release_ptr,.-q_atomic_fetch_and_add_release_ptr diff --git a/src/corelib/arch/sparc/qatomic_sparc.cpp b/src/corelib/arch/sparc/qatomic_sparc.cpp new file mode 100644 index 0000000..bb411cd --- /dev/null +++ b/src/corelib/arch/sparc/qatomic_sparc.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $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" diff --git a/src/corelib/arch/windows/arch.pri b/src/corelib/arch/windows/arch.pri new file mode 100644 index 0000000..d42374b --- /dev/null +++ b/src/corelib/arch/windows/arch.pri @@ -0,0 +1,3 @@ +# +# Windows architecture +# diff --git a/src/corelib/arch/x86_64/arch.pri b/src/corelib/arch/x86_64/arch.pri new file mode 100644 index 0000000..4145b7b --- /dev/null +++ b/src/corelib/arch/x86_64/arch.pri @@ -0,0 +1,4 @@ +# +# AMD64 architecture +# +solaris-cc*:SOURCES += $$QT_ARCH_CPP/qatomic_sun.s diff --git a/src/corelib/arch/x86_64/qatomic_sun.s b/src/corelib/arch/x86_64/qatomic_sun.s new file mode 100644 index 0000000..37969e6 --- /dev/null +++ b/src/corelib/arch/x86_64/qatomic_sun.s @@ -0,0 +1,91 @@ + .code64 + + .globl q_atomic_increment + .type q_atomic_increment,@function + .section .text, "ax" + .align 16 +q_atomic_increment: + lock + incl (%rdi) + setne %al + ret + .size q_atomic_increment,.-q_atomic_increment + + .globl q_atomic_decrement + .type q_atomic_decrement,@function + .section .text, "ax" + .align 16 +q_atomic_decrement: + lock + decl (%rdi) + setne %al + ret + .size q_atomic_decrement,.-q_atomic_decrement + + .globl q_atomic_test_and_set_int + .type q_atomic_test_and_set_int, @function + .section .text, "ax" + .align 16 +q_atomic_test_and_set_int: + movl %esi,%eax + lock + cmpxchgl %edx,(%rdi) + movl $0,%eax + sete %al + ret + .size q_atomic_test_and_set_int, . - q_atomic_test_and_set_int + + .globl q_atomic_set_int + .type q_atomic_set_int,@function + .section .text, "ax" + .align 16 +q_atomic_set_int: + xchgl %esi,(%rdi) + movl %esi,%eax + ret + .size q_atomic_set_int,.-q_atomic_set_int + + .globl q_atomic_fetch_and_add_int + .type q_atomic_fetch_and_add_int,@function + .section .text, "ax" + .align 16 +q_atomic_fetch_and_add_int: + lock + xaddl %esi,(%rdi) + movl %esi, %eax + ret + .size q_atomic_fetch_and_add_int,.-q_atomic_fetch_and_add_int + + .globl q_atomic_test_and_set_ptr + .type q_atomic_test_and_set_ptr, @function + .section .text, "ax" + .align 16 +q_atomic_test_and_set_ptr: + movq %rsi,%rax + lock + cmpxchgq %rdx,(%rdi) + movq $0, %rax + sete %al + ret + .size q_atomic_test_and_set_ptr, . - q_atomic_test_and_set_ptr + + .globl q_atomic_set_ptr + .type q_atomic_set_ptr,@function + .section .text, "ax" + .align 16 +q_atomic_set_ptr: + xchgq %rsi,(%rdi) + movq %rsi,%rax + ret + .size q_atomic_set_ptr,.-q_atomic_set_ptr + + .globl q_atomic_fetch_and_add_ptr + .type q_atomic_fetch_and_add_ptr,@function + .section .text, "ax" + .align 16 +q_atomic_fetch_and_add_ptr: + lock + xaddq %rsi,(%rdi) + movq %rsi,%rax + ret + .size q_atomic_fetch_and_add_ptr,.-q_atomic_fetch_and_add_ptr |