ObjFW
atomic.h
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015
3  * Jonathan Schleifer <js@webkeks.org>
4  *
5  * All rights reserved.
6  *
7  * This file is part of ObjFW. It may be distributed under the terms of the
8  * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
9  * the packaging of this file.
10  *
11  * Alternatively, it may be distributed under the terms of the GNU General
12  * Public License, either version 2 or 3, which can be found in the file
13  * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
14  * file.
15  */
16 
17 #import "objfw-defs.h"
18 
19 #ifndef OF_HAVE_ATOMIC_OPS
20 # error No atomic operations available!
21 #endif
22 
23 #include <stdlib.h>
24 
25 #import "macros.h"
26 
27 #ifdef OF_HAVE_OSATOMIC
28 # include <libkern/OSAtomic.h>
29 #endif
30 
31 OF_ASSUME_NONNULL_BEGIN
32 
33 static OF_INLINE int
34 of_atomic_int_add(volatile int *OF_NONNULL p, int i)
35 {
36 #if !defined(OF_HAVE_THREADS)
37  return (*p += i);
38 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
39  return __sync_add_and_fetch(p, i);
40 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
41  if (sizeof(int) == 4)
42  __asm__ __volatile__ (
43  "lock\n\t"
44  "xaddl %0, %2\n\t"
45  "addl %1, %0"
46  : "+&r"(i)
47  : "r"(i), "m"(*p)
48  );
49 # ifdef OF_X86_64_ASM
50  else if (sizeof(int) == 8)
51  __asm__ __volatile__ (
52  "lock\n\t"
53  "xaddq %0, %2\n\t"
54  "addq %1, %0"
55  : "+&r"(i)
56  : "r"(i), "m"(*p)
57  );
58 # endif
59  else
60  abort();
61 
62  return i;
63 #elif defined(OF_PPC_ASM)
64  __asm__ __volatile__ (
65  "0:\n\t"
66  "lwarx %0, 0, %2\n\t"
67  "add %0, %0, %1\n\t"
68  "stwcx. %0, 0, %2\n\t"
69  "bne- 0b"
70  : "=&r"(i)
71  : "r"(i), "r"(p)
72  );
73 
74  return i;
75 #elif defined(OF_HAVE_OSATOMIC)
76  return OSAtomicAdd32Barrier(i, p);
77 #else
78 # error of_atomic_int_add not implemented!
79 #endif
80 }
81 
82 static OF_INLINE int32_t
83 of_atomic_int32_add(volatile int32_t *OF_NONNULL p, int32_t i)
84 {
85 #if !defined(OF_HAVE_THREADS)
86  return (*p += i);
87 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
88  return __sync_add_and_fetch(p, i);
89 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
90  __asm__ __volatile__ (
91  "lock\n\t"
92  "xaddl %0, %2\n\t"
93  "addl %1, %0"
94  : "+&r"(i)
95  : "r"(i), "m"(*p)
96  );
97 
98  return i;
99 #elif defined(OF_PPC_ASM)
100  __asm__ __volatile__ (
101  "0:\n\t"
102  "lwarx %0, 0, %2\n\t"
103  "add %0, %0, %1\n\t"
104  "stwcx. %0, 0, %2\n\t"
105  "bne- 0b"
106  : "=&r"(i)
107  : "r"(i), "r"(p)
108  );
109 
110  return i;
111 #elif defined(OF_HAVE_OSATOMIC)
112  return OSAtomicAdd32Barrier(i, p);
113 #else
114 # error of_atomic_int32_add not implemented!
115 #endif
116 }
117 
118 static OF_INLINE void*
119 of_atomic_ptr_add(void *volatile OF_NULLABLE *OF_NONNULL p, intptr_t i)
120 {
121 #if !defined(OF_HAVE_THREADS)
122  return (*(char* volatile*)p += i);
123 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
124  return __sync_add_and_fetch(p, (void*)i);
125 #elif defined(OF_X86_64_ASM)
126  __asm__ __volatile__ (
127  "lock\n\t"
128  "xaddq %0, %2\n\t"
129  "addq %1, %0"
130  : "+&r"(i)
131  : "r"(i), "m"(*p)
132  );
133 
134  return (void*)i;
135 #elif defined(OF_X86_ASM)
136  __asm__ __volatile__ (
137  "lock\n\t"
138  "xaddl %0, %2\n\t"
139  "addl %1, %0"
140  : "+&r"(i)
141  : "r"(i), "m"(*p)
142  );
143 
144  return (void*)i;
145 #elif defined(OF_PPC_ASM)
146  __asm__ __volatile__ (
147  "0:\n\t"
148  "lwarx %0, 0, %2\n\t"
149  "add %0, %0, %1\n\t"
150  "stwcx. %0, 0, %2\n\t"
151  "bne- 0b"
152  : "=&r"(i)
153  : "r"(i), "r"(p)
154  );
155 
156  return (void*)i;
157 #elif defined(OF_HAVE_OSATOMIC)
158 # ifdef __LP64__
159  return (void*)OSAtomicAdd64Barrier(i, (int64_t*)p);
160 # else
161  return (void*)OSAtomicAdd32Barrier(i, (int32_t*)p);
162 # endif
163 #else
164 # error of_atomic_ptr_add not implemented!
165 #endif
166 }
167 
168 static OF_INLINE int
169 of_atomic_int_sub(volatile int *OF_NONNULL p, int i)
170 {
171 #if !defined(OF_HAVE_THREADS)
172  return (*p -= i);
173 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
174  return __sync_sub_and_fetch(p, i);
175 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
176  if (sizeof(int) == 4)
177  __asm__ __volatile__ (
178  "negl %0\n\t"
179  "lock\n\t"
180  "xaddl %0, %2\n\t"
181  "subl %1, %0"
182  : "+&r"(i)
183  : "r"(i), "m"(*p)
184  );
185 # ifdef OF_X86_64_ASM
186  else if (sizeof(int) == 8)
187  __asm__ __volatile__ (
188  "negq %0\n\t"
189  "lock\n\t"
190  "xaddq %0, %2\n\t"
191  "subq %1, %0"
192  : "+&r"(i)
193  : "r"(i), "m"(*p)
194  );
195 # endif
196  else
197  abort();
198 
199  return i;
200 #elif defined(OF_PPC_ASM)
201  __asm__ __volatile__ (
202  "0:\n\t"
203  "lwarx %0, 0, %2\n\t"
204  "sub %0, %0, %1\n\t"
205  "stwcx. %0, 0, %2\n\t"
206  "bne- 0b"
207  : "=&r"(i)
208  : "r"(i), "r"(p)
209  );
210 
211  return i;
212 #elif defined(OF_HAVE_OSATOMIC)
213  return OSAtomicAdd32Barrier(-i, p);
214 #else
215 # error of_atomic_int_sub not implemented!
216 #endif
217 }
218 
219 static OF_INLINE int32_t
220 of_atomic_int32_sub(volatile int32_t *OF_NONNULL p, int32_t i)
221 {
222 #if !defined(OF_HAVE_THREADS)
223  return (*p -= i);
224 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
225  return __sync_sub_and_fetch(p, i);
226 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
227  __asm__ __volatile__ (
228  "negl %0\n\t"
229  "lock\n\t"
230  "xaddl %0, %2\n\t"
231  "subl %1, %0"
232  : "+&r"(i)
233  : "r"(i), "m"(*p)
234  );
235 
236  return i;
237 #elif defined(OF_PPC_ASM)
238  __asm__ __volatile__ (
239  "0:\n\t"
240  "lwarx %0, 0, %2\n\t"
241  "sub %0, %0, %1\n\t"
242  "stwcx. %0, 0, %2\n\t"
243  "bne- 0b"
244  : "=&r"(i)
245  : "r"(i), "r"(p)
246  );
247 
248  return i;
249 #elif defined(OF_HAVE_OSATOMIC)
250  return OSAtomicAdd32Barrier(-i, p);
251 #else
252 # error of_atomic_int32_sub not implemented!
253 #endif
254 }
255 
256 static OF_INLINE void*
257 of_atomic_ptr_sub(void *volatile OF_NULLABLE *OF_NONNULL p, intptr_t i)
258 {
259 #if !defined(OF_HAVE_THREADS)
260  return (*(char* volatile*)p -= i);
261 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
262  return __sync_sub_and_fetch(p, (void*)i);
263 #elif defined(OF_X86_64_ASM)
264  __asm__ __volatile__ (
265  "negq %0\n\t"
266  "lock\n\t"
267  "xaddq %0, %2\n\t"
268  "subq %1, %0"
269  : "+&r"(i)
270  : "r"(i), "m"(*p)
271  );
272 
273  return (void*)i;
274 #elif defined(OF_X86_ASM)
275  __asm__ __volatile__ (
276  "negl %0\n\t"
277  "lock\n\t"
278  "xaddl %0, %2\n\t"
279  "subl %1, %0"
280  : "+&r"(i)
281  : "r"(i), "m"(*p)
282  );
283 
284  return (void*)i;
285 #elif defined(OF_PPC_ASM)
286  __asm__ __volatile__ (
287  "0:\n\t"
288  "lwarx %0, 0, %2\n\t"
289  "sub %0, %0, %1\n\t"
290  "stwcx. %0, 0, %2\n\t"
291  "bne- 0b"
292  : "=&r"(i)
293  : "r"(i), "r"(p)
294  );
295 
296  return (void*)i;
297 #elif defined(OF_HAVE_OSATOMIC)
298 # ifdef __LP64__
299  return (void*)OSAtomicAdd64Barrier(-i, (int64_t*)p);
300 # else
301  return (void*)OSAtomicAdd32Barrier(-i, (int32_t*)p);
302 # endif
303 #else
304 # error of_atomic_ptr_sub not implemented!
305 #endif
306 }
307 
308 static OF_INLINE int
309 of_atomic_int_inc(volatile int *OF_NONNULL p)
310 {
311 #if !defined(OF_HAVE_THREADS)
312  return ++*p;
313 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
314  return __sync_add_and_fetch(p, 1);
315 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
316  int i;
317 
318  if (sizeof(int) == 4)
319  __asm__ __volatile__ (
320  "xorl %0, %0\n\t"
321  "incl %0\n\t"
322  "lock\n\t"
323  "xaddl %0, %1\n\t"
324  "incl %0"
325  : "=&r"(i)
326  : "m"(*p)
327  );
328 # ifdef OF_X86_64_ASM
329  else if (sizeof(int) == 8)
330  __asm__ __volatile__ (
331  "xorq %0, %0\n\t"
332  "incq %0\n\t"
333  "lock\n\t"
334  "xaddq %0, %1\n\t"
335  "incq %0"
336  : "=&r"(i)
337  : "m"(*p)
338  );
339 # endif
340  else
341  abort();
342 
343  return i;
344 #elif defined(OF_PPC_ASM)
345  int i;
346 
347  __asm__ __volatile__ (
348  "0:\n\t"
349  "lwarx %0, 0, %1\n\t"
350  "addi %0, %0, 1\n\t"
351  "stwcx. %0, 0, %1\n\t"
352  "bne- 0b"
353  : "=&r"(i)
354  : "r"(p)
355  );
356 
357  return i;
358 #elif defined(OF_HAVE_OSATOMIC)
359  return OSAtomicIncrement32Barrier(p);
360 #else
361 # error of_atomic_int_inc not implemented!
362 #endif
363 }
364 
365 static OF_INLINE int32_t
366 of_atomic_int32_inc(volatile int32_t *OF_NONNULL p)
367 {
368 #if !defined(OF_HAVE_THREADS)
369  return ++*p;
370 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
371  return __sync_add_and_fetch(p, 1);
372 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
373  int32_t i;
374 
375  __asm__ __volatile__ (
376  "xorl %0, %0\n\t"
377  "incl %0\n\t"
378  "lock\n\t"
379  "xaddl %0, %1\n\t"
380  "incl %0"
381  : "=&r"(i)
382  : "m"(*p)
383  );
384 
385  return i;
386 #elif defined(OF_PPC_ASM)
387  int32_t i;
388 
389  __asm__ __volatile__ (
390  "0:\n\t"
391  "lwarx %0, 0, %1\n\t"
392  "addi %0, %0, 1\n\t"
393  "stwcx. %0, 0, %1\n\t"
394  "bne- 0b"
395  : "=&r"(i)
396  : "r"(p)
397  );
398 
399  return i;
400 #elif defined(OF_HAVE_OSATOMIC)
401  return OSAtomicIncrement32Barrier(p);
402 #else
403 # error of_atomic_int32_inc not implemented!
404 #endif
405 }
406 
407 static OF_INLINE int
408 of_atomic_int_dec(volatile int *OF_NONNULL p)
409 {
410 #if !defined(OF_HAVE_THREADS)
411  return --*p;
412 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
413  return __sync_sub_and_fetch(p, 1);
414 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
415  int i;
416 
417  if (sizeof(int) == 4)
418  __asm__ __volatile__ (
419  "xorl %0, %0\n\t"
420  "decl %0\n\t"
421  "lock\n\t"
422  "xaddl %0, %1\n\t"
423  "decl %0"
424  : "=&r"(i)
425  : "m"(*p)
426  );
427 # ifdef OF_X86_64_ASM
428  else if (sizeof(int) == 8)
429  __asm__ __volatile__ (
430  "xorq %0, %0\n\t"
431  "decq %0\n\t"
432  "lock\n\t"
433  "xaddq %0, %1\n\t"
434  "decq %0"
435  : "=&r"(i)
436  : "m"(*p)
437  );
438 # endif
439  else
440  abort();
441 
442  return i;
443 #elif defined(OF_PPC_ASM)
444  int i;
445 
446  __asm__ __volatile__ (
447  "0:\n\t"
448  "lwarx %0, 0, %1\n\t"
449  "subi %0, %0, 1\n\t"
450  "stwcx. %0, 0, %1\n\t"
451  "bne- 0b"
452  : "=&r"(i)
453  : "r"(p)
454  );
455 
456  return i;
457 #elif defined(OF_HAVE_OSATOMIC)
458  return OSAtomicDecrement32Barrier(p);
459 #else
460 # error of_atomic_int_dec not implemented!
461 #endif
462 }
463 
464 static OF_INLINE int32_t
465 of_atomic_int32_dec(volatile int32_t *OF_NONNULL p)
466 {
467 #if !defined(OF_HAVE_THREADS)
468  return --*p;
469 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
470  return __sync_sub_and_fetch(p, 1);
471 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
472  int32_t i;
473 
474  __asm__ __volatile__ (
475  "xorl %0, %0\n\t"
476  "decl %0\n\t"
477  "lock\n\t"
478  "xaddl %0, %1\n\t"
479  "decl %0"
480  : "=&r"(i)
481  : "m"(*p)
482  );
483 
484  return i;
485 #elif defined(OF_PPC_ASM)
486  int32_t i;
487 
488  __asm__ __volatile__ (
489  "0:\n\t"
490  "lwarx %0, 0, %1\n\t"
491  "subi %0, %0, 1\n\t"
492  "stwcx. %0, 0, %1\n\t"
493  "bne- 0b"
494  : "=&r"(i)
495  : "r"(p)
496  );
497 
498  return i;
499 #elif defined(OF_HAVE_OSATOMIC)
500  return OSAtomicDecrement32Barrier(p);
501 #else
502 # error of_atomic_int32_dec not implemented!
503 #endif
504 }
505 
506 static OF_INLINE unsigned int
507 of_atomic_int_or(volatile unsigned int *OF_NONNULL p, unsigned int i)
508 {
509 #if !defined(OF_HAVE_THREADS)
510  return (*p |= i);
511 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
512  return __sync_or_and_fetch(p, i);
513 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
514  if (sizeof(int) == 4)
515  __asm__ __volatile__ (
516  "0:\n\t"
517  "movl %2, %0\n\t"
518  "movl %0, %%eax\n\t"
519  "orl %1, %0\n\t"
520  "lock\n\t"
521  "cmpxchg %0, %2\n\t"
522  "jne 0b"
523  : "=&r"(i)
524  : "r"(i), "m"(*p)
525  : "eax", "cc"
526  );
527 # ifdef OF_X86_64_ASM
528  else if (sizeof(int) == 8)
529  __asm__ __volatile__ (
530  "0:\n\t"
531  "movq %2, %0\n\t"
532  "movq %0, %%rax\n\t"
533  "orq %1, %0\n\t"
534  "lock\n\t"
535  "cmpxchg %0, %2\n\t"
536  "jne 0b"
537  : "=&r"(i)
538  : "r"(i), "m"(*p)
539  : "rax", "cc"
540  );
541 # endif
542  else
543  abort();
544 
545  return i;
546 #elif defined(OF_PPC_ASM)
547  __asm__ __volatile__ (
548  "0:\n\t"
549  "lwarx %0, 0, %2\n\t"
550  "or %0, %0, %1\n\t"
551  "stwcx. %0, 0, %2\n\t"
552  "bne- 0b"
553  : "=&r"(i)
554  : "r"(i), "r"(p)
555  );
556 
557  return i;
558 #elif defined(OF_HAVE_OSATOMIC)
559  return OSAtomicOr32Barrier(i, p);
560 #else
561 # error of_atomic_int_or not implemented!
562 #endif
563 }
564 
565 static OF_INLINE uint32_t
566 of_atomic_int32_or(volatile uint32_t *OF_NONNULL p, uint32_t i)
567 {
568 #if !defined(OF_HAVE_THREADS)
569  return (*p |= i);
570 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
571  return __sync_or_and_fetch(p, i);
572 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
573  __asm__ __volatile__ (
574  "0:\n\t"
575  "movl %2, %0\n\t"
576  "movl %0, %%eax\n\t"
577  "orl %1, %0\n\t"
578  "lock\n\t"
579  "cmpxchg %0, %2\n\t"
580  "jne 0b"
581  : "=&r"(i)
582  : "r"(i), "m"(*p)
583  : "eax", "cc"
584  );
585 
586  return i;
587 #elif defined(OF_PPC_ASM)
588  __asm__ __volatile__ (
589  "0:\n\t"
590  "lwarx %0, 0, %2\n\t"
591  "or %0, %0, %1\n\t"
592  "stwcx. %0, 0, %2\n\t"
593  "bne- 0b"
594  : "=&r"(i)
595  : "r"(i), "r"(p)
596  );
597 
598  return i;
599 #elif defined(OF_HAVE_OSATOMIC)
600  return OSAtomicOr32Barrier(i, p);
601 #else
602 # error of_atomic_int32_or not implemented!
603 #endif
604 }
605 
606 static OF_INLINE unsigned int
607 of_atomic_int_and(volatile unsigned int *OF_NONNULL p, unsigned int i)
608 {
609 #if !defined(OF_HAVE_THREADS)
610  return (*p &= i);
611 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
612  return __sync_and_and_fetch(p, i);
613 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
614  if (sizeof(int) == 4)
615  __asm__ __volatile__ (
616  "0:\n\t"
617  "movl %2, %0\n\t"
618  "movl %0, %%eax\n\t"
619  "andl %1, %0\n\t"
620  "lock\n\t"
621  "cmpxchg %0, %2\n\t"
622  "jne 0b"
623  : "=&r"(i)
624  : "r"(i), "m"(*p)
625  : "eax", "cc"
626  );
627 # ifdef OF_X86_64_ASM
628  else if (sizeof(int) == 8)
629  __asm__ __volatile__ (
630  "0:\n\t"
631  "movq %2, %0\n\t"
632  "movq %0, %%rax\n\t"
633  "andq %1, %0\n\t"
634  "lock\n\t"
635  "cmpxchg %0, %2\n\t"
636  "jne 0b"
637  : "=&r"(i)
638  : "r"(i), "m"(*p)
639  : "rax", "cc"
640  );
641 # endif
642  else
643  abort();
644 
645  return i;
646 #elif defined(OF_PPC_ASM)
647  __asm__ __volatile__ (
648  "0:\n\t"
649  "lwarx %0, 0, %2\n\t"
650  "and %0, %0, %1\n\t"
651  "stwcx. %0, 0, %2\n\t"
652  "bne- 0b"
653  : "=&r"(i)
654  : "r"(i), "r"(p)
655  );
656 
657  return i;
658 #elif defined(OF_HAVE_OSATOMIC)
659  return OSAtomicAnd32Barrier(i, p);
660 #else
661 # error of_atomic_int_and not implemented!
662 #endif
663 }
664 
665 static OF_INLINE uint32_t
666 of_atomic_int32_and(volatile uint32_t *OF_NONNULL p, uint32_t i)
667 {
668 #if !defined(OF_HAVE_THREADS)
669  return (*p &= i);
670 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
671  return __sync_and_and_fetch(p, i);
672 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
673  __asm__ __volatile__ (
674  "0:\n\t"
675  "movl %2, %0\n\t"
676  "movl %0, %%eax\n\t"
677  "andl %1, %0\n\t"
678  "lock\n\t"
679  "cmpxchg %0, %2\n\t"
680  "jne 0b"
681  : "=&r"(i)
682  : "r"(i), "m"(*p)
683  : "eax", "cc"
684  );
685 
686  return i;
687 #elif defined(OF_PPC_ASM)
688  __asm__ __volatile__ (
689  "0:\n\t"
690  "lwarx %0, 0, %2\n\t"
691  "and %0, %0, %1\n\t"
692  "stwcx. %0, 0, %2\n\t"
693  "bne- 0b"
694  : "=&r"(i)
695  : "r"(i), "r"(p)
696  );
697 
698  return i;
699 #elif defined(OF_HAVE_OSATOMIC)
700  return OSAtomicAnd32Barrier(i, p);
701 #else
702 # error of_atomic_int32_and not implemented!
703 #endif
704 }
705 
706 static OF_INLINE unsigned int
707 of_atomic_int_xor(volatile unsigned int *OF_NONNULL p, unsigned int i)
708 {
709 #if !defined(OF_HAVE_THREADS)
710  return (*p ^= i);
711 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
712  return __sync_xor_and_fetch(p, i);
713 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
714  if (sizeof(int) == 4)
715  __asm__ __volatile__ (
716  "0:\n\t"
717  "movl %2, %0\n\t"
718  "movl %0, %%eax\n\t"
719  "xorl %1, %0\n\t"
720  "lock\n\t"
721  "cmpxchg %0, %2\n\t"
722  "jne 0b"
723  : "=&r"(i)
724  : "r"(i), "m"(*p)
725  : "eax", "cc"
726  );
727 # ifdef OF_X86_64_ASM
728  else if (sizeof(int) == 8)
729  __asm__ __volatile__ (
730  "0:\n\t"
731  "movq %2, %0\n\t"
732  "movq %0, %%rax\n\t"
733  "xorq %1, %0\n\t"
734  "lock\n\t"
735  "cmpxchg %0, %2\n\t"
736  "jne 0b"
737  : "=&r"(i)
738  : "r"(i), "m"(*p)
739  : "rax", "cc"
740  );
741 # endif
742  else
743  abort();
744 
745  return i;
746 #elif defined(OF_PPC_ASM)
747  __asm__ __volatile__ (
748  "0:\n\t"
749  "lwarx %0, 0, %2\n\t"
750  "xor %0, %0, %1\n\t"
751  "stwcx. %0, 0, %2\n\t"
752  "bne- 0b"
753  : "=&r"(i)
754  : "r"(i), "r"(p)
755  );
756 
757  return i;
758 #elif defined(OF_HAVE_OSATOMIC)
759  return OSAtomicXor32Barrier(i, p);
760 #else
761 # error of_atomic_int_xor not implemented!
762 #endif
763 }
764 
765 static OF_INLINE uint32_t
766 of_atomic_int32_xor(volatile uint32_t *OF_NONNULL p, uint32_t i)
767 {
768 #if !defined(OF_HAVE_THREADS)
769  return (*p ^= i);
770 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
771  return __sync_xor_and_fetch(p, i);
772 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
773  __asm__ __volatile__ (
774  "0:\n\t"
775  "movl %2, %0\n\t"
776  "movl %0, %%eax\n\t"
777  "xorl %1, %0\n\t"
778  "lock\n\t"
779  "cmpxchgl %0, %2\n\t"
780  "jne 0b"
781  : "=&r"(i)
782  : "r"(i), "m"(*p)
783  : "eax", "cc"
784  );
785 
786  return i;
787 #elif defined(OF_PPC_ASM)
788  __asm__ __volatile__ (
789  "0:\n\t"
790  "lwarx %0, 0, %2\n\t"
791  "xor %0, %0, %1\n\t"
792  "stwcx. %0, 0, %2\n\t"
793  "bne- 0b"
794  : "=&r"(i)
795  : "r"(i), "r"(p)
796  );
797 
798  return i;
799 #elif defined(OF_HAVE_OSATOMIC)
800  return OSAtomicXor32Barrier(i, p);
801 #else
802 # error of_atomic_int32_xor not implemented!
803 #endif
804 }
805 
806 static OF_INLINE bool
807 of_atomic_int_cmpswap(volatile int *OF_NONNULL p, int o, int n)
808 {
809 #if !defined(OF_HAVE_THREADS)
810  if (*p == o) {
811  *p = n;
812  return true;
813  }
814 
815  return false;
816 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
817  return __sync_bool_compare_and_swap(p, o, n);
818 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
819  int r;
820 
821  __asm__ __volatile__ (
822  "lock\n\t"
823  "cmpxchg %2, %3\n\t"
824  "sete %b0\n\t"
825  "movzbl %b0, %0"
826  : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */
827  : "r"(n), "m"(*p)
828  : "cc"
829  );
830 
831  return r;
832 #elif defined(OF_PPC_ASM)
833  int r;
834 
835  __asm__ __volatile__ (
836  "0:\n\t"
837  "lwarx %0, 0, %3\n\t"
838  "cmpw %0, %1\n\t"
839  "bne 1f\n\t"
840  "stwcx. %2, 0, %3\n\t"
841  "bne- 0b\n\t"
842  "li %0, 1\n\t"
843  "b 2f\n\t"
844  "1:\n\t"
845  "stwcx. %0, 0, %3\n\t"
846  "li %0, 0\n\t"
847  "2:"
848  : "=&r"(r)
849  : "r"(o), "r"(n), "r"(p)
850  : "cc"
851  );
852 
853  return r;
854 #elif defined(OF_HAVE_OSATOMIC)
855  return OSAtomicCompareAndSwapIntBarrier(o, n, p);
856 #else
857 # error of_atomic_int_cmpswap not implemented!
858 #endif
859 }
860 
861 static OF_INLINE bool
862 of_atomic_int32_cmpswap(volatile int32_t *OF_NONNULL p, int32_t o, int32_t n)
863 {
864 #if !defined(OF_HAVE_THREADS)
865  if (*p == o) {
866  *p = n;
867  return true;
868  }
869 
870  return false;
871 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
872  return __sync_bool_compare_and_swap(p, o, n);
873 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
874  int r;
875 
876  __asm__ __volatile__ (
877  "lock\n\t"
878  "cmpxchg %2, %3\n\t"
879  "sete %b0\n\t"
880  "movzbl %b0, %0"
881  : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */
882  : "r"(n), "m"(*p)
883  : "cc"
884  );
885 
886  return r;
887 #elif defined(OF_PPC_ASM)
888  int r;
889 
890  __asm__ __volatile__ (
891  "0:\n\t"
892  "lwarx %0, 0, %3\n\t"
893  "cmpw %0, %1\n\t"
894  "bne 1f\n\t"
895  "stwcx. %2, 0, %3\n\t"
896  "bne- 0b\n\t"
897  "li %0, 1\n\t"
898  "b 2f\n\t"
899  "1:\n\t"
900  "stwcx. %0, 0, %3\n\t"
901  "li %0, 0\n\t"
902  "2:"
903  : "=&r"(r)
904  : "r"(o), "r"(n), "r"(p)
905  : "cc"
906  );
907 
908  return r;
909 #elif defined(OF_HAVE_OSATOMIC)
910  return OSAtomicCompareAndSwap32Barrier(o, n, p);
911 #else
912 # error of_atomic_int32_cmpswap not implemented!
913 #endif
914 }
915 
916 static OF_INLINE bool
917 of_atomic_ptr_cmpswap(void *volatile OF_NULLABLE *OF_NONNULL p,
918  void *OF_NULLABLE o, void *OF_NULLABLE n)
919 {
920 #if !defined(OF_HAVE_THREADS)
921  if (*p == o) {
922  *p = n;
923  return true;
924  }
925 
926  return false;
927 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
928  return __sync_bool_compare_and_swap(p, o, n);
929 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
930  int r;
931 
932  __asm__ __volatile__ (
933  "lock\n\t"
934  "cmpxchg %2, %3\n\t"
935  "sete %b0\n\t"
936  "movzbl %b0, %0"
937  : "=&d"(r), "+a"(o) /* use d instead of r to avoid a gcc bug */
938  : "r"(n), "m"(*p)
939  : "cc"
940  );
941 
942  return r;
943 #elif defined(OF_PPC_ASM)
944  int r;
945 
946  __asm__ __volatile__ (
947  "0:\n\t"
948  "lwarx %0, 0, %3\n\t"
949  "cmpw %0, %1\n\t"
950  "bne 1f\n\t"
951  "stwcx. %2, 0, %3\n\t"
952  "bne- 0b\n\t"
953  "li %0, 1\n\t"
954  "b 2f\n\t"
955  "1:\n\t"
956  "stwcx. %0, 0, %3\n\t"
957  "li %0, 0\n\t"
958  "2:"
959  : "=&r"(r)
960  : "r"(o), "r"(n), "r"(p)
961  : "cc"
962  );
963 
964  return r;
965 #elif defined(OF_HAVE_OSATOMIC)
966  return OSAtomicCompareAndSwapPtrBarrier(o, n, p);
967 #else
968 # error of_atomic_ptr_cmpswap not implemented!
969 #endif
970 }
971 
972 static OF_INLINE void
973 of_memory_barrier(void)
974 {
975 #if !defined(OF_HAVE_THREADS)
976 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
977  __asm__ __volatile__ (
978  "mfence"
979  );
980 #elif defined(OF_PPC_ASM)
981  __asm__ __volatile__ (
982  "sync"
983  );
984 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
985  __sync_synchronize();
986 #elif defined(OF_HAVE_OSATOMIC)
987  OSMemoryBarrier();
988 #else
989 # error of_memory_barrier not implemented!
990 #endif
991 }
992 
993 static OF_INLINE void
994 of_memory_read_barrier(void)
995 {
996 #if !defined(OF_HAVE_THREADS)
997 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
998  __asm__ __volatile__ (
999  "lfence"
1000  );
1001 #else
1002  of_memory_barrier();
1003 #endif
1004 }
1005 
1006 static OF_INLINE void
1007 of_memory_write_barrier(void)
1008 {
1009 #if !defined(OF_HAVE_THREADS)
1010 #elif defined(OF_X86_64_ASM) || defined(OF_X86_ASM)
1011  __asm__ __volatile__ (
1012  "sfence"
1013  );
1014 #else
1015  of_memory_barrier();
1016 #endif
1017 }
1018 
1019 OF_ASSUME_NONNULL_END