1a78e148bSantirez /******************************************************************************/
2a78e148bSantirez #ifdef JEMALLOC_H_TYPES
3a78e148bSantirez 
4a78e148bSantirez #endif /* JEMALLOC_H_TYPES */
5a78e148bSantirez /******************************************************************************/
6a78e148bSantirez #ifdef JEMALLOC_H_STRUCTS
7a78e148bSantirez 
8a78e148bSantirez #endif /* JEMALLOC_H_STRUCTS */
9a78e148bSantirez /******************************************************************************/
10a78e148bSantirez #ifdef JEMALLOC_H_EXTERNS
11a78e148bSantirez 
12a78e148bSantirez #define	atomic_read_uint64(p)	atomic_add_uint64(p, 0)
13a78e148bSantirez #define	atomic_read_uint32(p)	atomic_add_uint32(p, 0)
14*5268379eSantirez #define	atomic_read_p(p)	atomic_add_p(p, NULL)
15ad4c0b41Santirez #define	atomic_read_z(p)	atomic_add_z(p, 0)
16ad4c0b41Santirez #define	atomic_read_u(p)	atomic_add_u(p, 0)
17a78e148bSantirez 
18a78e148bSantirez #endif /* JEMALLOC_H_EXTERNS */
19a78e148bSantirez /******************************************************************************/
20a78e148bSantirez #ifdef JEMALLOC_H_INLINES
21a78e148bSantirez 
22*5268379eSantirez /*
23*5268379eSantirez  * All arithmetic functions return the arithmetic result of the atomic
24*5268379eSantirez  * operation.  Some atomic operation APIs return the value prior to mutation, in
25*5268379eSantirez  * which case the following functions must redundantly compute the result so
26*5268379eSantirez  * that it can be returned.  These functions are normally inlined, so the extra
27*5268379eSantirez  * operations can be optimized away if the return values aren't used by the
28*5268379eSantirez  * callers.
29*5268379eSantirez  *
30*5268379eSantirez  *   <t> atomic_read_<t>(<t> *p) { return (*p); }
31*5268379eSantirez  *   <t> atomic_add_<t>(<t> *p, <t> x) { return (*p + x); }
32*5268379eSantirez  *   <t> atomic_sub_<t>(<t> *p, <t> x) { return (*p - x); }
33*5268379eSantirez  *   bool atomic_cas_<t>(<t> *p, <t> c, <t> s)
34*5268379eSantirez  *   {
35*5268379eSantirez  *     if (*p != c)
36*5268379eSantirez  *       return (true);
37*5268379eSantirez  *     *p = s;
38*5268379eSantirez  *     return (false);
39*5268379eSantirez  *   }
40*5268379eSantirez  *   void atomic_write_<t>(<t> *p, <t> x) { *p = x; }
41*5268379eSantirez  */
42*5268379eSantirez 
43a78e148bSantirez #ifndef JEMALLOC_ENABLE_INLINE
44a78e148bSantirez uint64_t	atomic_add_uint64(uint64_t *p, uint64_t x);
45a78e148bSantirez uint64_t	atomic_sub_uint64(uint64_t *p, uint64_t x);
46*5268379eSantirez bool	atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s);
47*5268379eSantirez void	atomic_write_uint64(uint64_t *p, uint64_t x);
48a78e148bSantirez uint32_t	atomic_add_uint32(uint32_t *p, uint32_t x);
49a78e148bSantirez uint32_t	atomic_sub_uint32(uint32_t *p, uint32_t x);
50*5268379eSantirez bool	atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s);
51*5268379eSantirez void	atomic_write_uint32(uint32_t *p, uint32_t x);
52*5268379eSantirez void	*atomic_add_p(void **p, void *x);
53*5268379eSantirez void	*atomic_sub_p(void **p, void *x);
54*5268379eSantirez bool	atomic_cas_p(void **p, void *c, void *s);
55*5268379eSantirez void	atomic_write_p(void **p, const void *x);
56ad4c0b41Santirez size_t	atomic_add_z(size_t *p, size_t x);
57ad4c0b41Santirez size_t	atomic_sub_z(size_t *p, size_t x);
58*5268379eSantirez bool	atomic_cas_z(size_t *p, size_t c, size_t s);
59*5268379eSantirez void	atomic_write_z(size_t *p, size_t x);
60ad4c0b41Santirez unsigned	atomic_add_u(unsigned *p, unsigned x);
61ad4c0b41Santirez unsigned	atomic_sub_u(unsigned *p, unsigned x);
62*5268379eSantirez bool	atomic_cas_u(unsigned *p, unsigned c, unsigned s);
63*5268379eSantirez void	atomic_write_u(unsigned *p, unsigned x);
64a78e148bSantirez #endif
65a78e148bSantirez 
66a78e148bSantirez #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))
67a78e148bSantirez /******************************************************************************/
68a78e148bSantirez /* 64-bit operations. */
69ad4c0b41Santirez #if (LG_SIZEOF_PTR == 3 || LG_SIZEOF_INT == 3)
70*5268379eSantirez #  if (defined(__amd64__) || defined(__x86_64__))
71a78e148bSantirez JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t * p,uint64_t x)72a78e148bSantirez atomic_add_uint64(uint64_t *p, uint64_t x)
73a78e148bSantirez {
74*5268379eSantirez 	uint64_t t = x;
75a78e148bSantirez 
76a78e148bSantirez 	asm volatile (
77a78e148bSantirez 	    "lock; xaddq %0, %1;"
78*5268379eSantirez 	    : "+r" (t), "=m" (*p) /* Outputs. */
79a78e148bSantirez 	    : "m" (*p) /* Inputs. */
80a78e148bSantirez 	    );
81a78e148bSantirez 
82*5268379eSantirez 	return (t + x);
83a78e148bSantirez }
84a78e148bSantirez 
85a78e148bSantirez JEMALLOC_INLINE uint64_t
atomic_sub_uint64(uint64_t * p,uint64_t x)86a78e148bSantirez atomic_sub_uint64(uint64_t *p, uint64_t x)
87a78e148bSantirez {
88*5268379eSantirez 	uint64_t t;
89a78e148bSantirez 
90a78e148bSantirez 	x = (uint64_t)(-(int64_t)x);
91*5268379eSantirez 	t = x;
92a78e148bSantirez 	asm volatile (
93a78e148bSantirez 	    "lock; xaddq %0, %1;"
94*5268379eSantirez 	    : "+r" (t), "=m" (*p) /* Outputs. */
95a78e148bSantirez 	    : "m" (*p) /* Inputs. */
96a78e148bSantirez 	    );
97a78e148bSantirez 
98*5268379eSantirez 	return (t + x);
99*5268379eSantirez }
100*5268379eSantirez 
101*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint64(uint64_t * p,uint64_t c,uint64_t s)102*5268379eSantirez atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
103*5268379eSantirez {
104*5268379eSantirez 	uint8_t success;
105*5268379eSantirez 
106*5268379eSantirez 	asm volatile (
107*5268379eSantirez 	    "lock; cmpxchgq %4, %0;"
108*5268379eSantirez 	    "sete %1;"
109*5268379eSantirez 	    : "=m" (*p), "=a" (success) /* Outputs. */
110*5268379eSantirez 	    : "m" (*p), "a" (c), "r" (s) /* Inputs. */
111*5268379eSantirez 	    : "memory" /* Clobbers. */
112*5268379eSantirez 	    );
113*5268379eSantirez 
114*5268379eSantirez 	return (!(bool)success);
115*5268379eSantirez }
116*5268379eSantirez 
117*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint64(uint64_t * p,uint64_t x)118*5268379eSantirez atomic_write_uint64(uint64_t *p, uint64_t x)
119*5268379eSantirez {
120*5268379eSantirez 
121*5268379eSantirez 	asm volatile (
122*5268379eSantirez 	    "xchgq %1, %0;" /* Lock is implied by xchgq. */
123*5268379eSantirez 	    : "=m" (*p), "+r" (x) /* Outputs. */
124*5268379eSantirez 	    : "m" (*p) /* Inputs. */
125*5268379eSantirez 	    : "memory" /* Clobbers. */
126*5268379eSantirez 	    );
127*5268379eSantirez }
128*5268379eSantirez #  elif (defined(JEMALLOC_C11ATOMICS))
129*5268379eSantirez JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t * p,uint64_t x)130*5268379eSantirez atomic_add_uint64(uint64_t *p, uint64_t x)
131*5268379eSantirez {
132*5268379eSantirez 	volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
133*5268379eSantirez 	return (atomic_fetch_add(a, x) + x);
134*5268379eSantirez }
135*5268379eSantirez 
136*5268379eSantirez JEMALLOC_INLINE uint64_t
atomic_sub_uint64(uint64_t * p,uint64_t x)137*5268379eSantirez atomic_sub_uint64(uint64_t *p, uint64_t x)
138*5268379eSantirez {
139*5268379eSantirez 	volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
140*5268379eSantirez 	return (atomic_fetch_sub(a, x) - x);
141*5268379eSantirez }
142*5268379eSantirez 
143*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint64(uint64_t * p,uint64_t c,uint64_t s)144*5268379eSantirez atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
145*5268379eSantirez {
146*5268379eSantirez 	volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
147*5268379eSantirez 	return (!atomic_compare_exchange_strong(a, &c, s));
148*5268379eSantirez }
149*5268379eSantirez 
150*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint64(uint64_t * p,uint64_t x)151*5268379eSantirez atomic_write_uint64(uint64_t *p, uint64_t x)
152*5268379eSantirez {
153*5268379eSantirez 	volatile atomic_uint_least64_t *a = (volatile atomic_uint_least64_t *)p;
154*5268379eSantirez 	atomic_store(a, x);
155a78e148bSantirez }
156ad4c0b41Santirez #  elif (defined(JEMALLOC_ATOMIC9))
157ad4c0b41Santirez JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t * p,uint64_t x)158ad4c0b41Santirez atomic_add_uint64(uint64_t *p, uint64_t x)
159ad4c0b41Santirez {
160ad4c0b41Santirez 
161ad4c0b41Santirez 	/*
162ad4c0b41Santirez 	 * atomic_fetchadd_64() doesn't exist, but we only ever use this
163ad4c0b41Santirez 	 * function on LP64 systems, so atomic_fetchadd_long() will do.
164ad4c0b41Santirez 	 */
165ad4c0b41Santirez 	assert(sizeof(uint64_t) == sizeof(unsigned long));
166ad4c0b41Santirez 
167ad4c0b41Santirez 	return (atomic_fetchadd_long(p, (unsigned long)x) + x);
168ad4c0b41Santirez }
169ad4c0b41Santirez 
170ad4c0b41Santirez JEMALLOC_INLINE uint64_t
atomic_sub_uint64(uint64_t * p,uint64_t x)171ad4c0b41Santirez atomic_sub_uint64(uint64_t *p, uint64_t x)
172ad4c0b41Santirez {
173ad4c0b41Santirez 
174ad4c0b41Santirez 	assert(sizeof(uint64_t) == sizeof(unsigned long));
175ad4c0b41Santirez 
176ad4c0b41Santirez 	return (atomic_fetchadd_long(p, (unsigned long)(-(long)x)) - x);
177ad4c0b41Santirez }
178*5268379eSantirez 
179*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint64(uint64_t * p,uint64_t c,uint64_t s)180*5268379eSantirez atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
181*5268379eSantirez {
182*5268379eSantirez 
183*5268379eSantirez 	assert(sizeof(uint64_t) == sizeof(unsigned long));
184*5268379eSantirez 
185*5268379eSantirez 	return (!atomic_cmpset_long(p, (unsigned long)c, (unsigned long)s));
186*5268379eSantirez }
187*5268379eSantirez 
188*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint64(uint64_t * p,uint64_t x)189*5268379eSantirez atomic_write_uint64(uint64_t *p, uint64_t x)
190*5268379eSantirez {
191*5268379eSantirez 
192*5268379eSantirez 	assert(sizeof(uint64_t) == sizeof(unsigned long));
193*5268379eSantirez 
194*5268379eSantirez 	atomic_store_rel_long(p, x);
195*5268379eSantirez }
196*5268379eSantirez #  elif (defined(JEMALLOC_OSATOMIC))
197*5268379eSantirez JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t * p,uint64_t x)198*5268379eSantirez atomic_add_uint64(uint64_t *p, uint64_t x)
199*5268379eSantirez {
200*5268379eSantirez 
201*5268379eSantirez 	return (OSAtomicAdd64((int64_t)x, (int64_t *)p));
202*5268379eSantirez }
203*5268379eSantirez 
204*5268379eSantirez JEMALLOC_INLINE uint64_t
atomic_sub_uint64(uint64_t * p,uint64_t x)205*5268379eSantirez atomic_sub_uint64(uint64_t *p, uint64_t x)
206*5268379eSantirez {
207*5268379eSantirez 
208*5268379eSantirez 	return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));
209*5268379eSantirez }
210*5268379eSantirez 
211*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint64(uint64_t * p,uint64_t c,uint64_t s)212*5268379eSantirez atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
213*5268379eSantirez {
214*5268379eSantirez 
215*5268379eSantirez 	return (!OSAtomicCompareAndSwap64(c, s, (int64_t *)p));
216*5268379eSantirez }
217*5268379eSantirez 
218*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint64(uint64_t * p,uint64_t x)219*5268379eSantirez atomic_write_uint64(uint64_t *p, uint64_t x)
220*5268379eSantirez {
221*5268379eSantirez 	uint64_t o;
222*5268379eSantirez 
223*5268379eSantirez 	/*The documented OSAtomic*() API does not expose an atomic exchange. */
224*5268379eSantirez 	do {
225*5268379eSantirez 		o = atomic_read_uint64(p);
226*5268379eSantirez 	} while (atomic_cas_uint64(p, o, x));
227*5268379eSantirez }
228*5268379eSantirez #  elif (defined(_MSC_VER))
229*5268379eSantirez JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t * p,uint64_t x)230*5268379eSantirez atomic_add_uint64(uint64_t *p, uint64_t x)
231*5268379eSantirez {
232*5268379eSantirez 
233*5268379eSantirez 	return (InterlockedExchangeAdd64(p, x) + x);
234*5268379eSantirez }
235*5268379eSantirez 
236*5268379eSantirez JEMALLOC_INLINE uint64_t
atomic_sub_uint64(uint64_t * p,uint64_t x)237*5268379eSantirez atomic_sub_uint64(uint64_t *p, uint64_t x)
238*5268379eSantirez {
239*5268379eSantirez 
240*5268379eSantirez 	return (InterlockedExchangeAdd64(p, -((int64_t)x)) - x);
241*5268379eSantirez }
242*5268379eSantirez 
243*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint64(uint64_t * p,uint64_t c,uint64_t s)244*5268379eSantirez atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
245*5268379eSantirez {
246*5268379eSantirez 	uint64_t o;
247*5268379eSantirez 
248*5268379eSantirez 	o = InterlockedCompareExchange64(p, s, c);
249*5268379eSantirez 	return (o != c);
250*5268379eSantirez }
251*5268379eSantirez 
252*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint64(uint64_t * p,uint64_t x)253*5268379eSantirez atomic_write_uint64(uint64_t *p, uint64_t x)
254*5268379eSantirez {
255*5268379eSantirez 
256*5268379eSantirez 	InterlockedExchange64(p, x);
257*5268379eSantirez }
258*5268379eSantirez #  elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || \
259*5268379eSantirez     defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_8))
260ad4c0b41Santirez JEMALLOC_INLINE uint64_t
atomic_add_uint64(uint64_t * p,uint64_t x)261ad4c0b41Santirez atomic_add_uint64(uint64_t *p, uint64_t x)
262ad4c0b41Santirez {
263ad4c0b41Santirez 
264ad4c0b41Santirez 	return (__sync_add_and_fetch(p, x));
265ad4c0b41Santirez }
266ad4c0b41Santirez 
267ad4c0b41Santirez JEMALLOC_INLINE uint64_t
atomic_sub_uint64(uint64_t * p,uint64_t x)268ad4c0b41Santirez atomic_sub_uint64(uint64_t *p, uint64_t x)
269ad4c0b41Santirez {
270ad4c0b41Santirez 
271ad4c0b41Santirez 	return (__sync_sub_and_fetch(p, x));
272ad4c0b41Santirez }
273*5268379eSantirez 
274*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint64(uint64_t * p,uint64_t c,uint64_t s)275*5268379eSantirez atomic_cas_uint64(uint64_t *p, uint64_t c, uint64_t s)
276*5268379eSantirez {
277*5268379eSantirez 
278*5268379eSantirez 	return (!__sync_bool_compare_and_swap(p, c, s));
279*5268379eSantirez }
280*5268379eSantirez 
281*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint64(uint64_t * p,uint64_t x)282*5268379eSantirez atomic_write_uint64(uint64_t *p, uint64_t x)
283*5268379eSantirez {
284*5268379eSantirez 
285*5268379eSantirez 	__sync_lock_test_and_set(p, x);
286*5268379eSantirez }
287a78e148bSantirez #  else
288a78e148bSantirez #    error "Missing implementation for 64-bit atomic operations"
289a78e148bSantirez #  endif
290a78e148bSantirez #endif
291a78e148bSantirez 
292a78e148bSantirez /******************************************************************************/
293a78e148bSantirez /* 32-bit operations. */
294*5268379eSantirez #if (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
295a78e148bSantirez JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t * p,uint32_t x)296a78e148bSantirez atomic_add_uint32(uint32_t *p, uint32_t x)
297a78e148bSantirez {
298*5268379eSantirez 	uint32_t t = x;
299a78e148bSantirez 
300a78e148bSantirez 	asm volatile (
301a78e148bSantirez 	    "lock; xaddl %0, %1;"
302*5268379eSantirez 	    : "+r" (t), "=m" (*p) /* Outputs. */
303a78e148bSantirez 	    : "m" (*p) /* Inputs. */
304a78e148bSantirez 	    );
305a78e148bSantirez 
306*5268379eSantirez 	return (t + x);
307a78e148bSantirez }
308a78e148bSantirez 
309a78e148bSantirez JEMALLOC_INLINE uint32_t
atomic_sub_uint32(uint32_t * p,uint32_t x)310a78e148bSantirez atomic_sub_uint32(uint32_t *p, uint32_t x)
311a78e148bSantirez {
312*5268379eSantirez 	uint32_t t;
313a78e148bSantirez 
314a78e148bSantirez 	x = (uint32_t)(-(int32_t)x);
315*5268379eSantirez 	t = x;
316a78e148bSantirez 	asm volatile (
317a78e148bSantirez 	    "lock; xaddl %0, %1;"
318*5268379eSantirez 	    : "+r" (t), "=m" (*p) /* Outputs. */
319a78e148bSantirez 	    : "m" (*p) /* Inputs. */
320a78e148bSantirez 	    );
321a78e148bSantirez 
322*5268379eSantirez 	return (t + x);
323*5268379eSantirez }
324*5268379eSantirez 
325*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint32(uint32_t * p,uint32_t c,uint32_t s)326*5268379eSantirez atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
327*5268379eSantirez {
328*5268379eSantirez 	uint8_t success;
329*5268379eSantirez 
330*5268379eSantirez 	asm volatile (
331*5268379eSantirez 	    "lock; cmpxchgl %4, %0;"
332*5268379eSantirez 	    "sete %1;"
333*5268379eSantirez 	    : "=m" (*p), "=a" (success) /* Outputs. */
334*5268379eSantirez 	    : "m" (*p), "a" (c), "r" (s) /* Inputs. */
335*5268379eSantirez 	    : "memory"
336*5268379eSantirez 	    );
337*5268379eSantirez 
338*5268379eSantirez 	return (!(bool)success);
339*5268379eSantirez }
340*5268379eSantirez 
341*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint32(uint32_t * p,uint32_t x)342*5268379eSantirez atomic_write_uint32(uint32_t *p, uint32_t x)
343*5268379eSantirez {
344*5268379eSantirez 
345*5268379eSantirez 	asm volatile (
346*5268379eSantirez 	    "xchgl %1, %0;" /* Lock is implied by xchgl. */
347*5268379eSantirez 	    : "=m" (*p), "+r" (x) /* Outputs. */
348*5268379eSantirez 	    : "m" (*p) /* Inputs. */
349*5268379eSantirez 	    : "memory" /* Clobbers. */
350*5268379eSantirez 	    );
351*5268379eSantirez }
352*5268379eSantirez #  elif (defined(JEMALLOC_C11ATOMICS))
353*5268379eSantirez JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t * p,uint32_t x)354*5268379eSantirez atomic_add_uint32(uint32_t *p, uint32_t x)
355*5268379eSantirez {
356*5268379eSantirez 	volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
357*5268379eSantirez 	return (atomic_fetch_add(a, x) + x);
358*5268379eSantirez }
359*5268379eSantirez 
360*5268379eSantirez JEMALLOC_INLINE uint32_t
atomic_sub_uint32(uint32_t * p,uint32_t x)361*5268379eSantirez atomic_sub_uint32(uint32_t *p, uint32_t x)
362*5268379eSantirez {
363*5268379eSantirez 	volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
364*5268379eSantirez 	return (atomic_fetch_sub(a, x) - x);
365*5268379eSantirez }
366*5268379eSantirez 
367*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint32(uint32_t * p,uint32_t c,uint32_t s)368*5268379eSantirez atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
369*5268379eSantirez {
370*5268379eSantirez 	volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
371*5268379eSantirez 	return (!atomic_compare_exchange_strong(a, &c, s));
372*5268379eSantirez }
373*5268379eSantirez 
374*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint32(uint32_t * p,uint32_t x)375*5268379eSantirez atomic_write_uint32(uint32_t *p, uint32_t x)
376*5268379eSantirez {
377*5268379eSantirez 	volatile atomic_uint_least32_t *a = (volatile atomic_uint_least32_t *)p;
378*5268379eSantirez 	atomic_store(a, x);
379a78e148bSantirez }
380ad4c0b41Santirez #elif (defined(JEMALLOC_ATOMIC9))
381ad4c0b41Santirez JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t * p,uint32_t x)382ad4c0b41Santirez atomic_add_uint32(uint32_t *p, uint32_t x)
383ad4c0b41Santirez {
384ad4c0b41Santirez 
385ad4c0b41Santirez 	return (atomic_fetchadd_32(p, x) + x);
386ad4c0b41Santirez }
387ad4c0b41Santirez 
388ad4c0b41Santirez JEMALLOC_INLINE uint32_t
atomic_sub_uint32(uint32_t * p,uint32_t x)389ad4c0b41Santirez atomic_sub_uint32(uint32_t *p, uint32_t x)
390ad4c0b41Santirez {
391ad4c0b41Santirez 
392ad4c0b41Santirez 	return (atomic_fetchadd_32(p, (uint32_t)(-(int32_t)x)) - x);
393ad4c0b41Santirez }
394*5268379eSantirez 
395*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint32(uint32_t * p,uint32_t c,uint32_t s)396*5268379eSantirez atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
397*5268379eSantirez {
398*5268379eSantirez 
399*5268379eSantirez 	return (!atomic_cmpset_32(p, c, s));
400*5268379eSantirez }
401*5268379eSantirez 
402*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint32(uint32_t * p,uint32_t x)403*5268379eSantirez atomic_write_uint32(uint32_t *p, uint32_t x)
404*5268379eSantirez {
405*5268379eSantirez 
406*5268379eSantirez 	atomic_store_rel_32(p, x);
407*5268379eSantirez }
408*5268379eSantirez #elif (defined(JEMALLOC_OSATOMIC))
409*5268379eSantirez JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t * p,uint32_t x)410*5268379eSantirez atomic_add_uint32(uint32_t *p, uint32_t x)
411*5268379eSantirez {
412*5268379eSantirez 
413*5268379eSantirez 	return (OSAtomicAdd32((int32_t)x, (int32_t *)p));
414*5268379eSantirez }
415*5268379eSantirez 
416*5268379eSantirez JEMALLOC_INLINE uint32_t
atomic_sub_uint32(uint32_t * p,uint32_t x)417*5268379eSantirez atomic_sub_uint32(uint32_t *p, uint32_t x)
418*5268379eSantirez {
419*5268379eSantirez 
420*5268379eSantirez 	return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));
421*5268379eSantirez }
422*5268379eSantirez 
423*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint32(uint32_t * p,uint32_t c,uint32_t s)424*5268379eSantirez atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
425*5268379eSantirez {
426*5268379eSantirez 
427*5268379eSantirez 	return (!OSAtomicCompareAndSwap32(c, s, (int32_t *)p));
428*5268379eSantirez }
429*5268379eSantirez 
430*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint32(uint32_t * p,uint32_t x)431*5268379eSantirez atomic_write_uint32(uint32_t *p, uint32_t x)
432*5268379eSantirez {
433*5268379eSantirez 	uint32_t o;
434*5268379eSantirez 
435*5268379eSantirez 	/*The documented OSAtomic*() API does not expose an atomic exchange. */
436*5268379eSantirez 	do {
437*5268379eSantirez 		o = atomic_read_uint32(p);
438*5268379eSantirez 	} while (atomic_cas_uint32(p, o, x));
439*5268379eSantirez }
440*5268379eSantirez #elif (defined(_MSC_VER))
441*5268379eSantirez JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t * p,uint32_t x)442*5268379eSantirez atomic_add_uint32(uint32_t *p, uint32_t x)
443*5268379eSantirez {
444*5268379eSantirez 
445*5268379eSantirez 	return (InterlockedExchangeAdd(p, x) + x);
446*5268379eSantirez }
447*5268379eSantirez 
448*5268379eSantirez JEMALLOC_INLINE uint32_t
atomic_sub_uint32(uint32_t * p,uint32_t x)449*5268379eSantirez atomic_sub_uint32(uint32_t *p, uint32_t x)
450*5268379eSantirez {
451*5268379eSantirez 
452*5268379eSantirez 	return (InterlockedExchangeAdd(p, -((int32_t)x)) - x);
453*5268379eSantirez }
454*5268379eSantirez 
455*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint32(uint32_t * p,uint32_t c,uint32_t s)456*5268379eSantirez atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
457*5268379eSantirez {
458*5268379eSantirez 	uint32_t o;
459*5268379eSantirez 
460*5268379eSantirez 	o = InterlockedCompareExchange(p, s, c);
461*5268379eSantirez 	return (o != c);
462*5268379eSantirez }
463*5268379eSantirez 
464*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint32(uint32_t * p,uint32_t x)465*5268379eSantirez atomic_write_uint32(uint32_t *p, uint32_t x)
466*5268379eSantirez {
467*5268379eSantirez 
468*5268379eSantirez 	InterlockedExchange(p, x);
469*5268379eSantirez }
470*5268379eSantirez #elif (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || \
471*5268379eSantirez  defined(JE_FORCE_SYNC_COMPARE_AND_SWAP_4))
472ad4c0b41Santirez JEMALLOC_INLINE uint32_t
atomic_add_uint32(uint32_t * p,uint32_t x)473ad4c0b41Santirez atomic_add_uint32(uint32_t *p, uint32_t x)
474ad4c0b41Santirez {
475ad4c0b41Santirez 
476ad4c0b41Santirez 	return (__sync_add_and_fetch(p, x));
477ad4c0b41Santirez }
478ad4c0b41Santirez 
479ad4c0b41Santirez JEMALLOC_INLINE uint32_t
atomic_sub_uint32(uint32_t * p,uint32_t x)480ad4c0b41Santirez atomic_sub_uint32(uint32_t *p, uint32_t x)
481ad4c0b41Santirez {
482ad4c0b41Santirez 
483ad4c0b41Santirez 	return (__sync_sub_and_fetch(p, x));
484ad4c0b41Santirez }
485*5268379eSantirez 
486*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_uint32(uint32_t * p,uint32_t c,uint32_t s)487*5268379eSantirez atomic_cas_uint32(uint32_t *p, uint32_t c, uint32_t s)
488*5268379eSantirez {
489*5268379eSantirez 
490*5268379eSantirez 	return (!__sync_bool_compare_and_swap(p, c, s));
491*5268379eSantirez }
492*5268379eSantirez 
493*5268379eSantirez JEMALLOC_INLINE void
atomic_write_uint32(uint32_t * p,uint32_t x)494*5268379eSantirez atomic_write_uint32(uint32_t *p, uint32_t x)
495*5268379eSantirez {
496*5268379eSantirez 
497*5268379eSantirez 	__sync_lock_test_and_set(p, x);
498*5268379eSantirez }
499a78e148bSantirez #else
500a78e148bSantirez #  error "Missing implementation for 32-bit atomic operations"
501a78e148bSantirez #endif
502ad4c0b41Santirez 
503ad4c0b41Santirez /******************************************************************************/
504*5268379eSantirez /* Pointer operations. */
505*5268379eSantirez JEMALLOC_INLINE void *
atomic_add_p(void ** p,void * x)506*5268379eSantirez atomic_add_p(void **p, void *x)
507*5268379eSantirez {
508*5268379eSantirez 
509*5268379eSantirez #if (LG_SIZEOF_PTR == 3)
510*5268379eSantirez 	return ((void *)atomic_add_uint64((uint64_t *)p, (uint64_t)x));
511*5268379eSantirez #elif (LG_SIZEOF_PTR == 2)
512*5268379eSantirez 	return ((void *)atomic_add_uint32((uint32_t *)p, (uint32_t)x));
513*5268379eSantirez #endif
514*5268379eSantirez }
515*5268379eSantirez 
516*5268379eSantirez JEMALLOC_INLINE void *
atomic_sub_p(void ** p,void * x)517*5268379eSantirez atomic_sub_p(void **p, void *x)
518*5268379eSantirez {
519*5268379eSantirez 
520*5268379eSantirez #if (LG_SIZEOF_PTR == 3)
521*5268379eSantirez 	return ((void *)atomic_add_uint64((uint64_t *)p,
522*5268379eSantirez 	    (uint64_t)-((int64_t)x)));
523*5268379eSantirez #elif (LG_SIZEOF_PTR == 2)
524*5268379eSantirez 	return ((void *)atomic_add_uint32((uint32_t *)p,
525*5268379eSantirez 	    (uint32_t)-((int32_t)x)));
526*5268379eSantirez #endif
527*5268379eSantirez }
528*5268379eSantirez 
529*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_p(void ** p,void * c,void * s)530*5268379eSantirez atomic_cas_p(void **p, void *c, void *s)
531*5268379eSantirez {
532*5268379eSantirez 
533*5268379eSantirez #if (LG_SIZEOF_PTR == 3)
534*5268379eSantirez 	return (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));
535*5268379eSantirez #elif (LG_SIZEOF_PTR == 2)
536*5268379eSantirez 	return (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));
537*5268379eSantirez #endif
538*5268379eSantirez }
539*5268379eSantirez 
540*5268379eSantirez JEMALLOC_INLINE void
atomic_write_p(void ** p,const void * x)541*5268379eSantirez atomic_write_p(void **p, const void *x)
542*5268379eSantirez {
543*5268379eSantirez 
544*5268379eSantirez #if (LG_SIZEOF_PTR == 3)
545*5268379eSantirez 	atomic_write_uint64((uint64_t *)p, (uint64_t)x);
546*5268379eSantirez #elif (LG_SIZEOF_PTR == 2)
547*5268379eSantirez 	atomic_write_uint32((uint32_t *)p, (uint32_t)x);
548*5268379eSantirez #endif
549*5268379eSantirez }
550*5268379eSantirez 
551*5268379eSantirez /******************************************************************************/
552ad4c0b41Santirez /* size_t operations. */
553ad4c0b41Santirez JEMALLOC_INLINE size_t
atomic_add_z(size_t * p,size_t x)554ad4c0b41Santirez atomic_add_z(size_t *p, size_t x)
555ad4c0b41Santirez {
556ad4c0b41Santirez 
557ad4c0b41Santirez #if (LG_SIZEOF_PTR == 3)
558ad4c0b41Santirez 	return ((size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x));
559ad4c0b41Santirez #elif (LG_SIZEOF_PTR == 2)
560ad4c0b41Santirez 	return ((size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x));
561ad4c0b41Santirez #endif
562ad4c0b41Santirez }
563ad4c0b41Santirez 
564ad4c0b41Santirez JEMALLOC_INLINE size_t
atomic_sub_z(size_t * p,size_t x)565ad4c0b41Santirez atomic_sub_z(size_t *p, size_t x)
566ad4c0b41Santirez {
567ad4c0b41Santirez 
568ad4c0b41Santirez #if (LG_SIZEOF_PTR == 3)
569ad4c0b41Santirez 	return ((size_t)atomic_add_uint64((uint64_t *)p,
570ad4c0b41Santirez 	    (uint64_t)-((int64_t)x)));
571ad4c0b41Santirez #elif (LG_SIZEOF_PTR == 2)
572ad4c0b41Santirez 	return ((size_t)atomic_add_uint32((uint32_t *)p,
573ad4c0b41Santirez 	    (uint32_t)-((int32_t)x)));
574ad4c0b41Santirez #endif
575ad4c0b41Santirez }
576ad4c0b41Santirez 
577*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_z(size_t * p,size_t c,size_t s)578*5268379eSantirez atomic_cas_z(size_t *p, size_t c, size_t s)
579*5268379eSantirez {
580*5268379eSantirez 
581*5268379eSantirez #if (LG_SIZEOF_PTR == 3)
582*5268379eSantirez 	return (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));
583*5268379eSantirez #elif (LG_SIZEOF_PTR == 2)
584*5268379eSantirez 	return (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));
585*5268379eSantirez #endif
586*5268379eSantirez }
587*5268379eSantirez 
588*5268379eSantirez JEMALLOC_INLINE void
atomic_write_z(size_t * p,size_t x)589*5268379eSantirez atomic_write_z(size_t *p, size_t x)
590*5268379eSantirez {
591*5268379eSantirez 
592*5268379eSantirez #if (LG_SIZEOF_PTR == 3)
593*5268379eSantirez 	atomic_write_uint64((uint64_t *)p, (uint64_t)x);
594*5268379eSantirez #elif (LG_SIZEOF_PTR == 2)
595*5268379eSantirez 	atomic_write_uint32((uint32_t *)p, (uint32_t)x);
596*5268379eSantirez #endif
597*5268379eSantirez }
598*5268379eSantirez 
599ad4c0b41Santirez /******************************************************************************/
600ad4c0b41Santirez /* unsigned operations. */
601ad4c0b41Santirez JEMALLOC_INLINE unsigned
atomic_add_u(unsigned * p,unsigned x)602ad4c0b41Santirez atomic_add_u(unsigned *p, unsigned x)
603ad4c0b41Santirez {
604ad4c0b41Santirez 
605ad4c0b41Santirez #if (LG_SIZEOF_INT == 3)
606ad4c0b41Santirez 	return ((unsigned)atomic_add_uint64((uint64_t *)p, (uint64_t)x));
607ad4c0b41Santirez #elif (LG_SIZEOF_INT == 2)
608ad4c0b41Santirez 	return ((unsigned)atomic_add_uint32((uint32_t *)p, (uint32_t)x));
609ad4c0b41Santirez #endif
610ad4c0b41Santirez }
611ad4c0b41Santirez 
612ad4c0b41Santirez JEMALLOC_INLINE unsigned
atomic_sub_u(unsigned * p,unsigned x)613ad4c0b41Santirez atomic_sub_u(unsigned *p, unsigned x)
614ad4c0b41Santirez {
615ad4c0b41Santirez 
616ad4c0b41Santirez #if (LG_SIZEOF_INT == 3)
617ad4c0b41Santirez 	return ((unsigned)atomic_add_uint64((uint64_t *)p,
618ad4c0b41Santirez 	    (uint64_t)-((int64_t)x)));
619ad4c0b41Santirez #elif (LG_SIZEOF_INT == 2)
620ad4c0b41Santirez 	return ((unsigned)atomic_add_uint32((uint32_t *)p,
621ad4c0b41Santirez 	    (uint32_t)-((int32_t)x)));
622ad4c0b41Santirez #endif
623ad4c0b41Santirez }
624*5268379eSantirez 
625*5268379eSantirez JEMALLOC_INLINE bool
atomic_cas_u(unsigned * p,unsigned c,unsigned s)626*5268379eSantirez atomic_cas_u(unsigned *p, unsigned c, unsigned s)
627*5268379eSantirez {
628*5268379eSantirez 
629*5268379eSantirez #if (LG_SIZEOF_INT == 3)
630*5268379eSantirez 	return (atomic_cas_uint64((uint64_t *)p, (uint64_t)c, (uint64_t)s));
631*5268379eSantirez #elif (LG_SIZEOF_INT == 2)
632*5268379eSantirez 	return (atomic_cas_uint32((uint32_t *)p, (uint32_t)c, (uint32_t)s));
633*5268379eSantirez #endif
634*5268379eSantirez }
635*5268379eSantirez 
636*5268379eSantirez JEMALLOC_INLINE void
atomic_write_u(unsigned * p,unsigned x)637*5268379eSantirez atomic_write_u(unsigned *p, unsigned x)
638*5268379eSantirez {
639*5268379eSantirez 
640*5268379eSantirez #if (LG_SIZEOF_INT == 3)
641*5268379eSantirez 	atomic_write_uint64((uint64_t *)p, (uint64_t)x);
642*5268379eSantirez #elif (LG_SIZEOF_INT == 2)
643*5268379eSantirez 	atomic_write_uint32((uint32_t *)p, (uint32_t)x);
644*5268379eSantirez #endif
645*5268379eSantirez }
646*5268379eSantirez 
647ad4c0b41Santirez /******************************************************************************/
648a78e148bSantirez #endif
649a78e148bSantirez 
650a78e148bSantirez #endif /* JEMALLOC_H_INLINES */
651a78e148bSantirez /******************************************************************************/
652