1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QATOMIC_ALPHA_H
43 #define QATOMIC_ALPHA_H
44 
45 QT_BEGIN_HEADER
46 
47 QT_BEGIN_NAMESPACE
48 
49 #define Q_ATOMIC_INT_REFERENCE_COUNTING_IS_ALWAYS_NATIVE
50 
isReferenceCountingNative()51 inline bool QBasicAtomicInt::isReferenceCountingNative()
52 { return true; }
isReferenceCountingWaitFree()53 inline bool QBasicAtomicInt::isReferenceCountingWaitFree()
54 { return false; }
55 
56 #define Q_ATOMIC_INT_TEST_AND_SET_IS_ALWAYS_NATIVE
57 
isTestAndSetNative()58 inline bool QBasicAtomicInt::isTestAndSetNative()
59 { return true; }
isTestAndSetWaitFree()60 inline bool QBasicAtomicInt::isTestAndSetWaitFree()
61 { return false; }
62 
63 #define Q_ATOMIC_INT_FETCH_AND_STORE_IS_ALWAYS_NATIVE
64 
isFetchAndStoreNative()65 inline bool QBasicAtomicInt::isFetchAndStoreNative()
66 { return true; }
isFetchAndStoreWaitFree()67 inline bool QBasicAtomicInt::isFetchAndStoreWaitFree()
68 { return false; }
69 
70 #define Q_ATOMIC_INT_FETCH_AND_ADD_IS_ALWAYS_NATIVE
71 
isFetchAndAddNative()72 inline bool QBasicAtomicInt::isFetchAndAddNative()
73 { return true; }
isFetchAndAddWaitFree()74 inline bool QBasicAtomicInt::isFetchAndAddWaitFree()
75 { return false; }
76 
77 #define Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE
78 
79 template <typename T>
isTestAndSetNative()80 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetNative()
81 { return true; }
82 template <typename T>
isTestAndSetWaitFree()83 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isTestAndSetWaitFree()
84 { return false; }
85 
86 #define Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE
87 
88 template <typename T>
isFetchAndStoreNative()89 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreNative()
90 { return true; }
91 template <typename T>
isFetchAndStoreWaitFree()92 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndStoreWaitFree()
93 { return false; }
94 
95 #define Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE
96 
97 template <typename T>
isFetchAndAddNative()98 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddNative()
99 { return true; }
100 template <typename T>
isFetchAndAddWaitFree()101 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree()
102 { return false; }
103 
104 #if defined(Q_CC_GNU)
105 
ref()106 inline bool QBasicAtomicInt::ref()
107 {
108     int old, tmp;
109     asm volatile("1:\n"
110                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
111                  "addl  %0,1,%1\n" /* tmp=old+1;                              */
112                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
113                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
114                  "br    3f\n"      /* goto 3;                                 */
115                  "2: br 1b\n"      /* goto 1;                                 */
116                  "3:\n"
117                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
118                  :
119                  : "memory");
120     return old != -1;
121 }
122 
deref()123 inline bool QBasicAtomicInt::deref()
124 {
125     int old, tmp;
126     asm volatile("1:\n"
127                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
128                  "subl  %0,1,%1\n" /* tmp=old-1;                              */
129                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
130                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
131                  "br    3f\n"      /* goto 3;                                 */
132                  "2: br 1b\n"      /* goto 1;                                 */
133                  "3:\n"
134                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
135                  :
136                  : "memory");
137     return old != 1;
138 }
139 
testAndSetRelaxed(int expectedValue,int newValue)140 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
141 {
142     int ret;
143     asm volatile("1:\n"
144                  "ldl_l %0,%1\n"   /* ret=*ptr;                               */
145                  "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1;   */
146                  "beq   %0,3f\n"   /* if (ret==0) goto 3;                     */
147                  "mov   %3,%0\n"   /* ret=newval;                             */
148                  "stl_c %0,%1\n"   /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */
149                  "beq   %0,2f\n"   /* if (ret==0) goto 2;                     */
150                  "br    3f\n"      /* goto 3;                                 */
151                  "2: br 1b\n"      /* goto 1;                                 */
152                  "3:\n"
153                  : "=&r" (ret), "+m" (_q_value)
154                  : "r" (expectedValue), "r" (newValue)
155                  : "memory");
156     return ret != 0;
157 }
158 
testAndSetAcquire(int expectedValue,int newValue)159 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
160 {
161     int ret;
162     asm volatile("1:\n"
163                  "ldl_l %0,%1\n"   /* ret=*ptr;                               */
164                  "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1;   */
165                  "beq   %0,3f\n"   /* if (ret==0) goto 3;                     */
166                  "mov   %3,%0\n"   /* ret=newval;                             */
167                  "stl_c %0,%1\n"   /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */
168                  "beq   %0,2f\n"   /* if (ret==0) goto 2;                     */
169                  "br    3f\n"      /* goto 3;                                 */
170                  "2: br 1b\n"      /* goto 1;                                 */
171                  "3:\n"
172                  "mb\n"
173                  : "=&r" (ret), "+m" (_q_value)
174                  : "r" (expectedValue), "r" (newValue)
175                  : "memory");
176     return ret != 0;
177 }
178 
testAndSetRelease(int expectedValue,int newValue)179 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
180 {
181     int ret;
182     asm volatile("mb\n"
183                  "1:\n"
184                  "ldl_l %0,%1\n"   /* ret=*ptr;                               */
185                  "cmpeq %0,%2,%0\n"/* if (ret==expected) ret=0; else ret=1;   */
186                  "beq   %0,3f\n"   /* if (ret==0) goto 3;                     */
187                  "mov   %3,%0\n"   /* ret=newval;                             */
188                  "stl_c %0,%1\n"   /* if ((*ptr=ret)!=ret) ret=0; else ret=1; */
189                  "beq   %0,2f\n"   /* if (ret==0) goto 2;                     */
190                  "br    3f\n"      /* goto 3;                                 */
191                  "2: br 1b\n"      /* goto 1;                                 */
192                  "3:\n"
193                  : "=&r" (ret), "+m" (_q_value)
194                  : "r" (expectedValue), "r" (newValue)
195                  : "memory");
196     return ret != 0;
197 }
198 
fetchAndStoreRelaxed(int newValue)199 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
200 {
201     int old, tmp;
202     asm volatile("1:\n"
203                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
204                  "mov   %3,%1\n"   /* tmp=newval;                             */
205                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
206                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
207                  "br    3f\n"      /* goto 3;                                 */
208                  "2: br 1b\n"      /* goto 1;                                 */
209                  "3:\n"
210                  : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
211                  : "r" (newValue)
212                  : "memory");
213     return old;
214 }
215 
fetchAndStoreAcquire(int newValue)216 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
217 {
218     int old, tmp;
219     asm volatile("1:\n"
220                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
221                  "mov   %3,%1\n"   /* tmp=newval;                             */
222                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
223                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
224                  "br    3f\n"      /* goto 3;                                 */
225                  "2: br 1b\n"      /* goto 1;                                 */
226                  "3:\n"
227                  "mb\n"
228                  : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
229                  : "r" (newValue)
230                  : "memory");
231     return old;
232 }
233 
fetchAndStoreRelease(int newValue)234 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
235 {
236     int old, tmp;
237     asm volatile("mb\n"
238                  "1:\n"
239                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
240                  "mov   %3,%1\n"   /* tmp=newval;                             */
241                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
242                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
243                  "br    3f\n"      /* goto 3;                                 */
244                  "2: br 1b\n"      /* goto 1;                                 */
245                  "3:\n"
246                  : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
247                  : "r" (newValue)
248                  : "memory");
249     return old;
250 }
251 
fetchAndAddRelaxed(int valueToAdd)252 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
253 {
254     int old, tmp;
255     asm volatile("1:\n"
256                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
257                  "addl  %0,%3,%1\n"/* tmp=old+value;                          */
258                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
259                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
260                  "br    3f\n"      /* goto 3;                                 */
261                  "2: br 1b\n"      /* goto 1;                                 */
262                  "3:\n"
263                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
264                  : "r" (valueToAdd)
265                  : "memory");
266     return old;
267 }
268 
fetchAndAddAcquire(int valueToAdd)269 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
270 {
271     int old, tmp;
272     asm volatile("1:\n"
273                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
274                  "addl  %0,%3,%1\n"/* tmp=old+value;                          */
275                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
276                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
277                  "br    3f\n"      /* goto 3;                                 */
278                  "2: br 1b\n"      /* goto 1;                                 */
279                  "3:\n"
280                  "mb\n"
281                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
282                  : "r" (valueToAdd)
283                  : "memory");
284     return old;
285 }
286 
fetchAndAddRelease(int valueToAdd)287 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
288 {
289     int old, tmp;
290     asm volatile("mb\n"
291                  "1:\n"
292                  "ldl_l %0,%2\n"   /* old=*ptr;                               */
293                  "addl  %0,%3,%1\n"/* tmp=old+value;                          */
294                  "stl_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
295                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
296                  "br    3f\n"      /* goto 3;                                 */
297                  "2: br 1b\n"      /* goto 1;                                 */
298                  "3:\n"
299                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
300                  : "r" (valueToAdd)
301                  : "memory");
302     return old;
303 }
304 
305 template <typename T>
testAndSetRelaxed(T * expectedValue,T * newValue)306 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
307 {
308     void *ret;
309     asm volatile("1:\n"
310                  "ldq_l %0,%1\n"   /* ret=*ptr;                               */
311                  "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1;   */
312                  "beq   %0,3f\n"   /* if (tmp==0) goto 3;                     */
313                  "mov   %3,%0\n"   /* tmp=newval;                             */
314                  "stq_c %0,%1\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
315                  "beq   %0,2f\n"   /* if (ret==0) goto 2;                     */
316                  "br    3f\n"      /* goto 3;                                 */
317                  "2: br 1b\n"      /* goto 1;                                 */
318                  "3:\n"
319                  : "=&r" (ret), "+m" (_q_value)
320                  : "r" (expectedValue), "r" (newValue)
321                  : "memory");
322     return ret != 0;
323 }
324 
325 template <typename T>
testAndSetAcquire(T * expectedValue,T * newValue)326 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
327 {
328     void *ret;
329     asm volatile("1:\n"
330                  "ldq_l %0,%1\n"   /* ret=*ptr;                               */
331                  "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1;   */
332                  "beq   %0,3f\n"   /* if (tmp==0) goto 3;                     */
333                  "mov   %3,%0\n"   /* tmp=newval;                             */
334                  "stq_c %0,%1\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
335                  "beq   %0,2f\n"   /* if (ret==0) goto 2;                     */
336                  "br    3f\n"      /* goto 3;                                 */
337                  "2: br 1b\n"      /* goto 1;                                 */
338                  "3:\n"
339                  "mb\n"
340                  : "=&r" (ret), "+m" (_q_value)
341                  : "r" (expectedValue), "r" (newValue)
342                  : "memory");
343     return ret != 0;
344 }
345 
346 template <typename T>
testAndSetRelease(T * expectedValue,T * newValue)347 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
348 {
349     void *ret;
350     asm volatile("mb\n"
351                  "1:\n"
352                  "ldq_l %0,%1\n"   /* ret=*ptr;                               */
353                  "cmpeq %0,%2,%0\n"/* if (ret==expected) tmp=0; else tmp=1;   */
354                  "beq   %0,3f\n"   /* if (tmp==0) goto 3;                     */
355                  "mov   %3,%0\n"   /* tmp=newval;                             */
356                  "stq_c %0,%1\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
357                  "beq   %0,2f\n"   /* if (ret==0) goto 2;                     */
358                  "br    3f\n"      /* goto 3;                                 */
359                  "2: br 1b\n"      /* goto 1;                                 */
360                  "3:\n"
361                  : "=&r" (ret), "+m" (_q_value)
362                  : "r" (expectedValue), "r" (newValue)
363                  : "memory");
364     return ret != 0;
365 }
366 
367 template <typename T>
fetchAndStoreRelaxed(T * newValue)368 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
369 {
370     T *old, *tmp;
371     asm volatile("1:\n"
372                  "ldq_l %0,%2\n"   /* old=*ptr;                               */
373                  "mov   %3,%1\n"   /* tmp=newval;                             */
374                  "stq_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
375                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
376                  "br    3f\n"      /* goto 3;                                 */
377                  "2: br 1b\n"      /* goto 1;                                 */
378                  "3:\n"
379                  : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
380                  : "r" (newValue)
381                  : "memory");
382     return old;
383 }
384 
385 template <typename T>
fetchAndStoreAcquire(T * newValue)386 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
387 {
388     T *old, *tmp;
389     asm volatile("1:\n"
390                  "ldq_l %0,%2\n"   /* old=*ptr;                               */
391                  "mov   %3,%1\n"   /* tmp=newval;                             */
392                  "stq_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
393                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
394                  "br    3f\n"      /* goto 3;                                 */
395                  "2: br 1b\n"      /* goto 1;                                 */
396                  "3:\n"
397                  "mb\n"
398                  : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
399                  : "r" (newValue)
400                  : "memory");
401     return old;
402 }
403 
404 template <typename T>
fetchAndStoreRelease(T * newValue)405 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
406 {
407     T *old, *tmp;
408     asm volatile("mb\n"
409                  "1:\n"
410                  "ldq_l %0,%2\n"   /* old=*ptr;                               */
411                  "mov   %3,%1\n"   /* tmp=newval;                             */
412                  "stq_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
413                  "beq   %1,2f\n"   /* if (tmp==0) goto 2;                     */
414                  "br    3f\n"      /* goto 3;                                 */
415                  "2: br 1b\n"      /* goto 1;                                 */
416                  "3:\n"
417                  : "=&r" (old), "=&r" (tmp), "+m" (_q_value)
418                  : "r" (newValue)
419                  : "memory");
420     return old;
421 }
422 
423 template <typename T>
fetchAndAddRelaxed(qptrdiff valueToAdd)424 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
425 {
426     T *old, *tmp;
427     asm volatile("1:\n"
428                  "ldq_l %0,%2\n"   /* old=*ptr;                               */
429                  "addq  %0,%3,%1\n"/* tmp=old+value;                          */
430                  "stq_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
431                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
432                  "br    3f\n"      /* goto 3;                                 */
433                  "2: br 1b\n"      /* goto 1;                                 */
434                  "3:\n"
435                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
436                  : "r" (valueToAdd)
437                  : "memory");
438     return reinterpret_cast<T *>(old);
439 }
440 
441 template <typename T>
fetchAndAddAcquire(qptrdiff valueToAdd)442 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
443 {
444     T *old, *tmp;
445     asm volatile("1:\n"
446                  "ldq_l %0,%2\n"   /* old=*ptr;                               */
447                  "addq  %0,%3,%1\n"/* tmp=old+value;                          */
448                  "stq_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
449                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
450                  "br    3f\n"      /* goto 3;                                 */
451                  "2: br 1b\n"      /* goto 1;                                 */
452                  "3:\n"
453                  "mb\n"
454                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
455                  : "r" (valueToAdd)
456                  : "memory");
457     return reinterpret_cast<T *>(old);
458 }
459 
460 template <typename T>
fetchAndAddRelease(qptrdiff valueToAdd)461 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
462 {
463     T *old, *tmp;
464     asm volatile("mb\n"
465                  "1:\n"
466                  "ldq_l %0,%2\n"   /* old=*ptr;                               */
467                  "addq  %0,%3,%1\n"/* tmp=old+value;                          */
468                  "stq_c %1,%2\n"   /* if ((*ptr=tmp)!=tmp) tmp=0; else tmp=1; */
469                  "beq   %1,2f\n"   /* if (tmp == 0) goto 2;                   */
470                  "br    3f\n"      /* goto 3;                                 */
471                  "2: br 1b\n"      /* goto 1;                                 */
472                  "3:\n"
473                  : "=&r" (old), "=&r" (tmp), "+m"(_q_value)
474                  : "r" (valueToAdd)
475                  : "memory");
476     return reinterpret_cast<T *>(old);
477 }
478 
479 #else // !Q_CC_GNU
480 
481 extern "C" {
482     Q_CORE_EXPORT int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
483     Q_CORE_EXPORT int q_atomic_test_and_set_acquire_int(volatile int *ptr, int expected, int newval);
484     Q_CORE_EXPORT int q_atomic_test_and_set_release_int(volatile int *ptr, int expected, int newval);
485     Q_CORE_EXPORT int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
486     Q_CORE_EXPORT int q_atomic_increment(volatile int *ptr);
487     Q_CORE_EXPORT int q_atomic_decrement(volatile int *ptr);
488     Q_CORE_EXPORT int q_atomic_set_int(volatile int *ptr, int newval);
489     Q_CORE_EXPORT void *q_atomic_set_ptr(volatile void *ptr, void *newval);
490     Q_CORE_EXPORT int q_atomic_fetch_and_add_int(volatile int *ptr, int value);
491     Q_CORE_EXPORT int q_atomic_fetch_and_add_acquire_int(volatile int *ptr, int value);
492     Q_CORE_EXPORT int q_atomic_fetch_and_add_release_int(volatile int *ptr, int value);
493 } // extern "C"
494 
ref()495 inline bool QBasicAtomicInt::ref()
496 {
497     return q_atomic_increment(&_q_value) != 0;
498 }
499 
deref()500 inline bool QBasicAtomicInt::deref()
501 {
502     return q_atomic_decrement(&_q_value) != 0;
503 }
504 
testAndSetRelaxed(int expectedValue,int newValue)505 inline bool QBasicAtomicInt::testAndSetRelaxed(int expectedValue, int newValue)
506 {
507     return q_atomic_test_and_set_int(&_q_value, expectedValue, newValue) != 0;
508 }
509 
testAndSetAcquire(int expectedValue,int newValue)510 inline bool QBasicAtomicInt::testAndSetAcquire(int expectedValue, int newValue)
511 {
512     return q_atomic_test_and_set_acquire_int(&_q_value, expectedValue, newValue) != 0;
513 }
514 
testAndSetRelease(int expectedValue,int newValue)515 inline bool QBasicAtomicInt::testAndSetRelease(int expectedValue, int newValue)
516 {
517     return q_atomic_test_and_set_release_int(&_q_value, expectedValue, newValue) != 0;
518 }
519 
fetchAndStoreRelaxed(int newValue)520 inline int QBasicAtomicInt::fetchAndStoreRelaxed(int newValue)
521 {
522     return q_atomic_set_int(&_q_value, newValue);
523 }
524 
fetchAndStoreAcquire(int newValue)525 inline int QBasicAtomicInt::fetchAndStoreAcquire(int newValue)
526 {
527     return q_atomic_fetch_and_store_acquire_int(&_q_value, newValue);
528 }
529 
fetchAndStoreRelease(int newValue)530 inline int QBasicAtomicInt::fetchAndStoreRelease(int newValue)
531 {
532     return q_atomic_fetch_and_store_release_int(&_q_value, newValue);
533 }
534 
fetchAndAddRelaxed(int valueToAdd)535 inline int QBasicAtomicInt::fetchAndAddRelaxed(int valueToAdd)
536 {
537     return q_atomic_fetch_and_add_int(&_q_value, valueToAdd);
538 }
539 
fetchAndAddAcquire(int valueToAdd)540 inline int QBasicAtomicInt::fetchAndAddAcquire(int valueToAdd)
541 {
542     return q_atomic_fetch_and_add_acquire_int(&_q_value, valueToAdd);
543 }
544 
fetchAndAddRelease(int valueToAdd)545 inline int QBasicAtomicInt::fetchAndAddRelease(int valueToAdd)
546 {
547     return q_atomic_fetch_and_add_release_int(&_q_value, valueToAdd);
548 }
549 
550 template <typename T>
testAndSetRelaxed(T * expectedValue,T * newValue)551 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelaxed(T *expectedValue, T *newValue)
552 {
553     return q_atomic_test_and_set_ptr(&_q_value, expectedValue, newValue) != 0;
554 }
555 
556 template <typename T>
testAndSetAcquire(T * expectedValue,T * newValue)557 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetAcquire(T *expectedValue, T *newValue)
558 {
559     return q_atomic_test_and_set_acquire_ptr(&_q_value, expectedValue, newValue) != 0;
560 }
561 
562 template <typename T>
testAndSetRelease(T * expectedValue,T * newValue)563 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetRelease(T *expectedValue, T *newValue)
564 {
565     return q_atomic_test_and_set_release_ptr(&_q_value, expectedValue, newValue) != 0;
566 }
567 
568 template <typename T>
fetchAndStoreRelaxed(T * newValue)569 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelaxed(T *newValue)
570 {
571     return reinterpret_cast<T *>(q_atomic_set_ptr(&_q_value, newValue));
572 }
573 
574 template <typename T>
fetchAndStoreAcquire(T * newValue)575 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreAcquire(T *newValue)
576 {
577     return reinterpret_cast<T *>(q_atomic_fetch_and_store_acquire_ptr(&_q_value, newValue));
578 }
579 
580 template <typename T>
fetchAndStoreRelease(T * newValue)581 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreRelease(T *newValue)
582 {
583     return reinterpret_cast<T *>(q_atomic_fetch_and_store_release_ptr(&_q_value, newValue));
584 }
585 
586 template <typename T>
fetchAndAddRelaxed(qptrdiff valueToAdd)587 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelaxed(qptrdiff valueToAdd)
588 {
589     return reinterpret_cast<T *>(q_atomic_fetch_and_add_ptr(&_q_value, newValue));
590 }
591 template <typename T>
fetchAndAddAcquire(qptrdiff valueToAdd)592 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddAcquire(qptrdiff valueToAdd)
593 {
594     return reinterpret_cast<T *>(q_atomic_fetch_and_add_acquire_ptr(&_q_value, newValue));
595 }
596 
597 template <typename T>
fetchAndAddRelease(qptrdiff valueToAdd)598 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddRelease(qptrdiff valueToAdd)
599 {
600     return reinterpret_cast<T *>(q_atomic_fetch_and_add_release_ptr(&_q_value, newValue));
601 }
602 
603 #endif // Q_CC_GNU
604 
testAndSetOrdered(int expectedValue,int newValue)605 inline bool QBasicAtomicInt::testAndSetOrdered(int expectedValue, int newValue)
606 {
607     return testAndSetAcquire(expectedValue, newValue);
608 }
609 
fetchAndStoreOrdered(int newValue)610 inline int QBasicAtomicInt::fetchAndStoreOrdered(int newValue)
611 {
612     return fetchAndStoreAcquire(newValue);
613 }
614 
fetchAndAddOrdered(int valueToAdd)615 inline int QBasicAtomicInt::fetchAndAddOrdered(int valueToAdd)
616 {
617     return fetchAndAddAcquire(valueToAdd);
618 }
619 
620 template <typename T>
testAndSetOrdered(T * expectedValue,T * newValue)621 Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::testAndSetOrdered(T *expectedValue, T *newValue)
622 {
623     return testAndSetAcquire(expectedValue, newValue);
624 }
625 
626 template <typename T>
fetchAndStoreOrdered(T * newValue)627 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndStoreOrdered(T *newValue)
628 {
629     return fetchAndStoreAcquire(newValue);
630 }
631 
632 template <typename T>
fetchAndAddOrdered(qptrdiff valueToAdd)633 Q_INLINE_TEMPLATE T *QBasicAtomicPointer<T>::fetchAndAddOrdered(qptrdiff valueToAdd)
634 {
635     return fetchAndAddAcquire(valueToAdd);
636 }
637 
638 QT_END_NAMESPACE
639 
640 QT_END_HEADER
641 
642 #endif // QATOMIC_ALPHA_H
643