|
25 | 25 | #define pg_write_barrier_impl() __asm__ __volatile__ ("lwsync" : : : "memory") |
26 | 26 | #endif |
27 | 27 |
|
28 | | -#define PG_HAVE_ATOMIC_U32_SUPPORT |
29 | | -typedef struct pg_atomic_uint32 |
30 | | -{ |
31 | | - volatile uint32 value; |
32 | | -} pg_atomic_uint32; |
33 | | - |
34 | | -/* 64bit atomics are only supported in 64bit mode */ |
35 | | -#ifdef __64BIT__ |
36 | | -#define PG_HAVE_ATOMIC_U64_SUPPORT |
37 | | -typedef struct pg_atomic_uint64 |
38 | | -{ |
39 | | - volatile uint64 value pg_attribute_aligned(8); |
40 | | -} pg_atomic_uint64; |
41 | | - |
42 | | -#endif /* __64BIT__ */ |
43 | | - |
44 | | -#define PG_HAVE_ATOMIC_FETCH_ADD_U32 |
45 | | -static inline uint32 |
46 | | -pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_) |
47 | | -{ |
48 | | - uint32 _t; |
49 | | - uint32 res; |
50 | | - |
51 | | - /* |
52 | | - * xlc has a no-longer-documented __fetch_and_add() intrinsic. In xlc |
53 | | - * 12.01.0000.0000, it emits a leading "sync" and trailing "isync". In |
54 | | - * xlc 13.01.0003.0004, it emits neither. Hence, using the intrinsic |
55 | | - * would add redundant syncs on xlc 12. |
56 | | - */ |
57 | | -#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P |
58 | | - if (__builtin_constant_p(add_) && |
59 | | - add_ <= PG_INT16_MAX && add_ >= PG_INT16_MIN) |
60 | | - __asm__ __volatile__( |
61 | | - " sync \n" |
62 | | - " lwarx %1,0,%4 \n" |
63 | | - " addi %0,%1,%3 \n" |
64 | | - " stwcx. %0,0,%4 \n" |
65 | | - " bne $-12 \n" /* branch to lwarx */ |
66 | | - " isync \n" |
67 | | -: "=&r"(_t), "=&r"(res), "+m"(ptr->value) |
68 | | -: "i"(add_), "r"(&ptr->value) |
69 | | -: "memory", "cc"); |
70 | | - else |
71 | | -#endif |
72 | | - __asm__ __volatile__( |
73 | | - " sync \n" |
74 | | - " lwarx %1,0,%4 \n" |
75 | | - " add %0,%1,%3 \n" |
76 | | - " stwcx. %0,0,%4 \n" |
77 | | - " bne $-12 \n" /* branch to lwarx */ |
78 | | - " isync \n" |
79 | | -: "=&r"(_t), "=&r"(res), "+m"(ptr->value) |
80 | | -: "r"(add_), "r"(&ptr->value) |
81 | | -: "memory", "cc"); |
82 | | - |
83 | | - return res; |
84 | | -} |
85 | | - |
86 | | -#ifdef PG_HAVE_ATOMIC_U64_SUPPORT |
87 | | -#define PG_HAVE_ATOMIC_FETCH_ADD_U64 |
88 | | -static inline uint64 |
89 | | -pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_) |
90 | | -{ |
91 | | - uint64 _t; |
92 | | - uint64 res; |
93 | | - |
94 | | - /* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/ */ |
95 | | -#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P |
96 | | - if (__builtin_constant_p(add_) && |
97 | | - add_ <= PG_INT16_MAX && add_ >= PG_INT16_MIN) |
98 | | - __asm__ __volatile__( |
99 | | - " sync \n" |
100 | | - " ldarx %1,0,%4 \n" |
101 | | - " addi %0,%1,%3 \n" |
102 | | - " stdcx. %0,0,%4 \n" |
103 | | - " bne $-12 \n" /* branch to ldarx */ |
104 | | - " isync \n" |
105 | | -: "=&r"(_t), "=&r"(res), "+m"(ptr->value) |
106 | | -: "i"(add_), "r"(&ptr->value) |
107 | | -: "memory", "cc"); |
108 | | - else |
109 | | -#endif |
110 | | - __asm__ __volatile__( |
111 | | - " sync \n" |
112 | | - " ldarx %1,0,%4 \n" |
113 | | - " add %0,%1,%3 \n" |
114 | | - " stdcx. %0,0,%4 \n" |
115 | | - " bne $-12 \n" /* branch to ldarx */ |
116 | | - " isync \n" |
117 | | -: "=&r"(_t), "=&r"(res), "+m"(ptr->value) |
118 | | -: "r"(add_), "r"(&ptr->value) |
119 | | -: "memory", "cc"); |
120 | | - |
121 | | - return res; |
122 | | -} |
123 | | - |
124 | | -#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */ |
125 | | - |
126 | 28 | /* per architecture manual doubleword accesses have single copy atomicity */ |
127 | 29 | #define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY |
0 commit comments