1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtCore module of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 2.1 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 2.1 requirements
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25
** In addition, as a special exception, Digia gives you certain additional
26
** rights. These rights are described in the Digia Qt LGPL Exception
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29
** GNU General Public License Usage
30
** Alternatively, this file may be used under the terms of the GNU
31
** General Public License version 3.0 as published by the Free Software
32
** Foundation and appearing in the file LICENSE.GPL included in the
33
** packaging of this file. Please review the following information to
34
** ensure the GNU General Public License version 3.0 requirements will be
35
** met: http://www.gnu.org/copyleft/gpl.html.
40
****************************************************************************/
42
#ifndef QATOMIC_POWER_H
43
#define QATOMIC_POWER_H
45
#include <QtCore/qoldbasicatomic.h>
51
#define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
53
inline bool QBasicAtomicInt::isReferenceCountingNative()
55
inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
58
#define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
60
inline bool QBasicAtomicInt::isTestAndSetNative()
62
inline bool QBasicAtomicInt::isTestAndSetWaitFree()
65
#define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
67
inline bool QBasicAtomicInt::isFetchAndStoreNative()
69
inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
72
#define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
74
inline bool QBasicAtomicInt::isFetchAndAddNative()
76
inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
79
#define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
82
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
85
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
88
#define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
91
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
94
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
97
#define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
100
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
102
template <typename T>
103
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
106
#if defined(Q_CC_GNU)
108
#ifdef Q_PROCESSOR_POWER_32
109
# define _Q_VALUE "0, %[_q_value]"
110
# define _Q_VALUE_MEMORY_OPERAND "+m" (_q_value)
111
# define _Q_VALUE_REGISTER_OPERAND [_q_value] "r" (&_q_value),
112
#else // Q_PROCESSOR_POWER_64
113
# define _Q_VALUE "%y[_q_value]"
114
# define _Q_VALUE_MEMORY_OPERAND [_q_value] "+Z" (_q_value)
115
# define _Q_VALUE_REGISTER_OPERAND
118
inline bool QBasicAtomicInt::ref()
120
register int originalValue;
121
register int newValue;
122
asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
123
"addi %[newValue], %[originalValue], %[one]\n"
124
"stwcx. %[newValue]," _Q_VALUE "\n"
126
: [originalValue] "=&b" (originalValue),
127
[newValue] "=&r" (newValue),
128
_Q_VALUE_MEMORY_OPERAND
129
: _Q_VALUE_REGISTER_OPERAND
132
return newValue != 0;
135
inline bool QBasicAtomicInt::deref()
137
register int originalValue;
138
register int newValue;
139
asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
140
"addi %[newValue], %[originalValue], %[minusOne]\n"
141
"stwcx. %[newValue]," _Q_VALUE "\n"
143
: [originalValue] "=&b" (originalValue),
144
[newValue] "=&r" (newValue),
145
_Q_VALUE_MEMORY_OPERAND
146
: _Q_VALUE_REGISTER_OPERAND
149
return newValue != 0;
152
inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
155
asm volatile("lwarx %[result]," _Q_VALUE "\n"
156
"xor. %[result], %[result], %[expectedValue]\n"
158
"stwcx. %[newValue]," _Q_VALUE "\n"
160
: [result] "=&r" (result),
161
_Q_VALUE_MEMORY_OPERAND
162
: _Q_VALUE_REGISTER_OPERAND
163
[expectedValue] "r" (expectedValue),
164
[newValue] "r" (newValue)
169
inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
172
asm volatile("lwarx %[result]," _Q_VALUE "\n"
173
"xor. %[result], %[result], %[expectedValue]\n"
175
"stwcx. %[newValue]," _Q_VALUE "\n"
178
: [result] "=&r" (result),
179
_Q_VALUE_MEMORY_OPERAND
180
: _Q_VALUE_REGISTER_OPERAND
181
[expectedValue] "r" (expectedValue),
182
[newValue] "r" (newValue)
187
inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
190
asm volatile("eieio\n"
191
"lwarx %[result]," _Q_VALUE "\n"
192
"xor. %[result], %[result], %[expectedValue]\n"
194
"stwcx. %[newValue]," _Q_VALUE "\n"
196
: [result] "=&r" (result),
197
_Q_VALUE_MEMORY_OPERAND
198
: _Q_VALUE_REGISTER_OPERAND
199
[expectedValue] "r" (expectedValue),
200
[newValue] "r" (newValue)
205
inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
207
register int originalValue;
208
asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
209
"stwcx. %[newValue]," _Q_VALUE "\n"
211
: [originalValue] "=&r" (originalValue),
212
_Q_VALUE_MEMORY_OPERAND
213
: _Q_VALUE_REGISTER_OPERAND
214
[newValue] "r" (newValue)
216
return originalValue;
219
inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
221
register int originalValue;
222
asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
223
"stwcx. %[newValue]," _Q_VALUE "\n"
226
: [originalValue] "=&r" (originalValue),
227
_Q_VALUE_MEMORY_OPERAND
228
: _Q_VALUE_REGISTER_OPERAND
229
[newValue] "r" (newValue)
231
return originalValue;
234
inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
236
register int originalValue;
237
asm volatile("eieio\n"
238
"lwarx %[originalValue]," _Q_VALUE "\n"
239
"stwcx. %[newValue]," _Q_VALUE "\n"
241
: [originalValue] "=&r" (originalValue),
242
_Q_VALUE_MEMORY_OPERAND
243
: _Q_VALUE_REGISTER_OPERAND
244
[newValue] "r" (newValue)
246
return originalValue;
249
inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
251
register int originalValue;
252
register int newValue;
253
asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
254
"add %[newValue], %[originalValue], %[valueToAdd]\n"
255
"stwcx. %[newValue]," _Q_VALUE "\n"
257
: [originalValue] "=&r" (originalValue),
258
[newValue] "=&r" (newValue),
259
_Q_VALUE_MEMORY_OPERAND
260
: _Q_VALUE_REGISTER_OPERAND
261
[valueToAdd] "r" (valueToAdd)
263
return originalValue;
266
inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
268
register int originalValue;
269
register int newValue;
270
asm volatile("lwarx %[originalValue]," _Q_VALUE "\n"
271
"add %[newValue], %[originalValue], %[valueToAdd]\n"
272
"stwcx. %[newValue]," _Q_VALUE "\n"
275
: [originalValue] "=&r" (originalValue),
276
[newValue] "=&r" (newValue),
277
_Q_VALUE_MEMORY_OPERAND
278
: _Q_VALUE_REGISTER_OPERAND
279
[valueToAdd] "r" (valueToAdd)
281
return originalValue;
284
inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
286
register int originalValue;
287
register int newValue;
288
asm volatile("eieio\n"
289
"lwarx %[originalValue]," _Q_VALUE "\n"
290
"add %[newValue], %[originalValue], %[valueToAdd]\n"
291
"stwcx. %[newValue]," _Q_VALUE "\n"
293
: [originalValue] "=&r" (originalValue),
294
[newValue] "=&r" (newValue),
295
_Q_VALUE_MEMORY_OPERAND
296
: _Q_VALUE_REGISTER_OPERAND
297
[valueToAdd] "r" (valueToAdd)
299
return originalValue;
302
#ifdef Q_PROCESSOR_POWER_64
303
# define LPARX "ldarx"
304
# define STPCX "stdcx."
306
# define LPARX "lwarx"
307
# define STPCX "stwcx."
310
template <typename T>
311
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
313
register void *result;
314
asm volatile(LPARX" %[result]," _Q_VALUE "\n"
315
"xor. %[result], %[result], %[expectedValue]\n"
317
STPCX" %[newValue]," _Q_VALUE "\n"
319
: [result] "=&r" (result),
320
_Q_VALUE_MEMORY_OPERAND
321
: _Q_VALUE_REGISTER_OPERAND
322
[expectedValue] "r" (expectedValue),
323
[newValue] "r" (newValue)
328
template <typename T>
329
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
331
register void *result;
332
asm volatile(LPARX" %[result]," _Q_VALUE "\n"
333
"xor. %[result], %[result], %[expectedValue]\n"
335
STPCX" %[newValue]," _Q_VALUE "\n"
338
: [result] "=&r" (result),
339
_Q_VALUE_MEMORY_OPERAND
340
: _Q_VALUE_REGISTER_OPERAND
341
[expectedValue] "r" (expectedValue),
342
[newValue] "r" (newValue)
347
template <typename T>
348
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
350
register void *result;
351
asm volatile("eieio\n"
352
LPARX" %[result]," _Q_VALUE "\n"
353
"xor. %[result], %[result], %[expectedValue]\n"
355
STPCX" %[newValue]," _Q_VALUE "\n"
357
: [result] "=&r" (result),
358
_Q_VALUE_MEMORY_OPERAND
359
: _Q_VALUE_REGISTER_OPERAND
360
[expectedValue] "r" (expectedValue),
361
[newValue] "r" (newValue)
366
template <typename T>
367
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
369
register T *originalValue;
370
asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
371
STPCX" %[newValue]," _Q_VALUE "\n"
373
: [originalValue] "=&r" (originalValue),
374
_Q_VALUE_MEMORY_OPERAND
375
: _Q_VALUE_REGISTER_OPERAND
376
[newValue] "r" (newValue)
378
return originalValue;
381
template <typename T>
382
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
384
register T *originalValue;
385
asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
386
STPCX" %[newValue]," _Q_VALUE "\n"
389
: [originalValue] "=&r" (originalValue),
390
_Q_VALUE_MEMORY_OPERAND
391
: _Q_VALUE_REGISTER_OPERAND
392
[newValue] "r" (newValue)
394
return originalValue;
397
template <typename T>
398
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
400
register T *originalValue;
401
asm volatile("eieio\n"
402
LPARX" %[originalValue]," _Q_VALUE "\n"
403
STPCX" %[newValue]," _Q_VALUE "\n"
405
: [originalValue] "=&r" (originalValue),
406
_Q_VALUE_MEMORY_OPERAND
407
: _Q_VALUE_REGISTER_OPERAND
408
[newValue] "r" (newValue)
410
return originalValue;
413
template <typename T>
414
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
416
register T *originalValue;
417
register T *newValue;
418
asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
419
"add %[newValue], %[originalValue], %[valueToAdd]\n"
420
STPCX" %[newValue]," _Q_VALUE "\n"
422
: [originalValue] "=&r" (originalValue),
423
[newValue] "=&r" (newValue),
424
_Q_VALUE_MEMORY_OPERAND
425
: _Q_VALUE_REGISTER_OPERAND
426
[valueToAdd] "r" (valueToAdd * sizeof(T))
428
return originalValue;
431
template <typename T>
432
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
434
register T *originalValue;
435
register T *newValue;
436
asm volatile(LPARX" %[originalValue]," _Q_VALUE "\n"
437
"add %[newValue], %[originalValue], %[valueToAdd]\n"
438
STPCX" %[newValue]," _Q_VALUE "\n"
441
: [originalValue] "=&r" (originalValue),
442
[newValue] "=&r" (newValue),
443
_Q_VALUE_MEMORY_OPERAND
444
: _Q_VALUE_REGISTER_OPERAND
445
[valueToAdd] "r" (valueToAdd * sizeof(T))
447
return originalValue;
450
template <typename T>
451
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
453
register T *originalValue;
454
register T *newValue;
455
asm volatile("eieio\n"
456
LPARX" %[originalValue]," _Q_VALUE "\n"
457
"add %[newValue], %[originalValue], %[valueToAdd]\n"
458
STPCX" %[newValue]," _Q_VALUE "\n"
460
: [originalValue] "=&r" (originalValue),
461
[newValue] "=&r" (newValue),
462
_Q_VALUE_MEMORY_OPERAND
463
: _Q_VALUE_REGISTER_OPERAND
464
[valueToAdd] "r" (valueToAdd * sizeof(T))
466
return originalValue;
472
#undef _Q_VALUE_MEMORY_OPERAND
473
#undef _Q_VALUE_REGISTER_OPERAND
476
# error "This compiler for Power/PowerPC is not supported"
479
inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
481
return testAndSetAcquire(expectedValue, newValue);
484
inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
486
return fetchAndStoreAcquire(newValue);
489
inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
491
return fetchAndAddAcquire(valueToAdd);
494
template <typename T>
495
Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
497
return testAndSetAcquire(expectedValue, newValue);
500
template <typename T>
501
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
503
return fetchAndStoreAcquire(newValue);
506
template <typename T>
507
Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
509
return fetchAndAddAcquire(valueToAdd);
516
#endif // QATOMIC_POWER_H