atomic.h revision 7427525c28d58c423a68930160e3b0fe577fe953
1/******************************************************************************/
2#ifdef JEMALLOC_H_TYPES
3
4#endif /* JEMALLOC_H_TYPES */
5/******************************************************************************/
6#ifdef JEMALLOC_H_STRUCTS
7
8#endif /* JEMALLOC_H_STRUCTS */
9/******************************************************************************/
10#ifdef JEMALLOC_H_EXTERNS
11
12#define	atomic_read_uint64(p)	atomic_add_uint64(p, 0)
13#define	atomic_read_uint32(p)	atomic_add_uint32(p, 0)
14
15#if (LG_SIZEOF_PTR == 3)
16#  define atomic_read_z(p)						\
17    (size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)0)
18#  define atomic_add_z(p, x)						\
19    (size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x)
20#  define atomic_sub_z(p, x)						\
21    (size_t)atomic_sub_uint64((uint64_t *)p, (uint64_t)x)
22#elif (LG_SIZEOF_PTR == 2)
23#  define atomic_read_z(p)						\
24    (size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)0)
25#  define atomic_add_z(p, x)						\
26    (size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x)
27#  define atomic_sub_z(p, x)						\
28    (size_t)atomic_sub_uint32((uint32_t *)p, (uint32_t)x)
29#endif
30
31#endif /* JEMALLOC_H_EXTERNS */
32/******************************************************************************/
33#ifdef JEMALLOC_H_INLINES
34
35#ifndef JEMALLOC_ENABLE_INLINE
36uint64_t	atomic_add_uint64(uint64_t *p, uint64_t x);
37uint64_t	atomic_sub_uint64(uint64_t *p, uint64_t x);
38uint32_t	atomic_add_uint32(uint32_t *p, uint32_t x);
39uint32_t	atomic_sub_uint32(uint32_t *p, uint32_t x);
40#endif
41
42#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ATOMIC_C_))
43/******************************************************************************/
44/* 64-bit operations. */
45#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
46JEMALLOC_INLINE uint64_t
47atomic_add_uint64(uint64_t *p, uint64_t x)
48{
49
50	return (__sync_add_and_fetch(p, x));
51}
52
53JEMALLOC_INLINE uint64_t
54atomic_sub_uint64(uint64_t *p, uint64_t x)
55{
56
57	return (__sync_sub_and_fetch(p, x));
58}
59#elif (defined(JEMALLOC_OSATOMIC))
60JEMALLOC_INLINE uint64_t
61atomic_add_uint64(uint64_t *p, uint64_t x)
62{
63
64	return (OSAtomicAdd64((int64_t)x, (int64_t *)p));
65}
66
67JEMALLOC_INLINE uint64_t
68atomic_sub_uint64(uint64_t *p, uint64_t x)
69{
70
71	return (OSAtomicAdd64(-((int64_t)x), (int64_t *)p));
72}
73#elif (defined(__amd64_) || defined(__x86_64__))
74JEMALLOC_INLINE uint64_t
75atomic_add_uint64(uint64_t *p, uint64_t x)
76{
77
78	asm volatile (
79	    "lock; xaddq %0, %1;"
80	    : "+r" (x), "=m" (*p) /* Outputs. */
81	    : "m" (*p) /* Inputs. */
82	    );
83
84	return (x);
85}
86
87JEMALLOC_INLINE uint64_t
88atomic_sub_uint64(uint64_t *p, uint64_t x)
89{
90
91	x = (uint64_t)(-(int64_t)x);
92	asm volatile (
93	    "lock; xaddq %0, %1;"
94	    : "+r" (x), "=m" (*p) /* Outputs. */
95	    : "m" (*p) /* Inputs. */
96	    );
97
98	return (x);
99}
100#else
101#  if (LG_SIZEOF_PTR == 3)
102#    error "Missing implementation for 64-bit atomic operations"
103#  endif
104#endif
105
106/******************************************************************************/
107/* 32-bit operations. */
108#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
109JEMALLOC_INLINE uint32_t
110atomic_add_uint32(uint32_t *p, uint32_t x)
111{
112
113	return (__sync_add_and_fetch(p, x));
114}
115
116JEMALLOC_INLINE uint32_t
117atomic_sub_uint32(uint32_t *p, uint32_t x)
118{
119
120	return (__sync_sub_and_fetch(p, x));
121}
122#elif (defined(JEMALLOC_OSATOMIC))
123JEMALLOC_INLINE uint32_t
124atomic_add_uint32(uint32_t *p, uint32_t x)
125{
126
127	return (OSAtomicAdd32((int32_t)x, (int32_t *)p));
128}
129
130JEMALLOC_INLINE uint32_t
131atomic_sub_uint32(uint32_t *p, uint32_t x)
132{
133
134	return (OSAtomicAdd32(-((int32_t)x), (int32_t *)p));
135}
136#elif (defined(__i386__) || defined(__amd64_) || defined(__x86_64__))
137JEMALLOC_INLINE uint32_t
138atomic_add_uint32(uint32_t *p, uint32_t x)
139{
140
141	asm volatile (
142	    "lock; xaddl %0, %1;"
143	    : "+r" (x), "=m" (*p) /* Outputs. */
144	    : "m" (*p) /* Inputs. */
145	    );
146
147	return (x);
148}
149
150JEMALLOC_INLINE uint32_t
151atomic_sub_uint32(uint32_t *p, uint32_t x)
152{
153
154	x = (uint32_t)(-(int32_t)x);
155	asm volatile (
156	    "lock; xaddl %0, %1;"
157	    : "+r" (x), "=m" (*p) /* Outputs. */
158	    : "m" (*p) /* Inputs. */
159	    );
160
161	return (x);
162}
163#else
164#  error "Missing implementation for 32-bit atomic operations"
165#endif
166#endif
167
168#endif /* JEMALLOC_H_INLINES */
169/******************************************************************************/
170