upstream nginx-0.7.31
[nginx.git] / nginx / src / os / unix / ngx_atomic.h
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #ifndef _NGX_ATOMIC_H_INCLUDED_
8 #define _NGX_ATOMIC_H_INCLUDED_
9
10
11 #include <ngx_config.h>
12 #include <ngx_core.h>
13
14
15 #if (NGX_DARWIN_ATOMIC)
16
17 /*
18  * use Darwin 8 atomic(3) and barrier(3) operations
19  * optimized at run-time for UP and SMP
20  */
21
22 #include <libkern/OSAtomic.h>
23
24 /* "bool" conflicts with perl's CORE/handy.h */
25 #undef bool
26
27
28 #define NGX_HAVE_ATOMIC_OPS  1
29
30 #if (NGX_PTR_SIZE == 8)
31
32 typedef int64_t                     ngx_atomic_int_t;
33 typedef uint64_t                    ngx_atomic_uint_t;
34 #define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
35
36 #define ngx_atomic_cmp_set(lock, old, new)                                    \
37     OSAtomicCompareAndSwap64Barrier(old, new, (int64_t *) lock)
38
39 #define ngx_atomic_fetch_add(value, add)                                      \
40     (OSAtomicAdd64(add, (int64_t *) value) - add)
41
42 #else
43
44 typedef int32_t                     ngx_atomic_int_t;
45 typedef uint32_t                    ngx_atomic_uint_t;
46 #define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
47
48 #define ngx_atomic_cmp_set(lock, old, new)                                    \
49     OSAtomicCompareAndSwap32Barrier(old, new, (int32_t *) lock)
50
51 #define ngx_atomic_fetch_add(value, add)                                      \
52     (OSAtomicAdd32(add, (int32_t *) value) - add)
53
54 #endif
55
56 #define ngx_memory_barrier()        OSMemoryBarrier()
57
58 #define ngx_cpu_pause()
59
60 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
61
62
63 #else /* !(NGX_DARWIN) */
64
65
66 #if ( __i386__ || __i386 )
67
68 typedef int32_t                     ngx_atomic_int_t;
69 typedef uint32_t                    ngx_atomic_uint_t;
70 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
71 #define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
72
73
74 #if ( __SUNPRO_C )
75
76 #define NGX_HAVE_ATOMIC_OPS  1
77
78 ngx_atomic_uint_t
79 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
80     ngx_atomic_uint_t set);
81
82 ngx_atomic_int_t
83 ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
84
85 /*
86  * Sun Studio 12 exits with segmentation fault on '__asm ("pause")',
87  * so ngx_cpu_pause is declared in src/os/unix/ngx_sunpro_x86.il
88  */
89
90 void
91 ngx_cpu_pause(void);
92
93 /* the code in src/os/unix/ngx_sunpro_x86.il */
94
95 #define ngx_memory_barrier()        __asm (".volatile"); __asm (".nonvolatile")
96
97
98 #else /* ( __GNUC__ || __INTEL_COMPILER ) */
99
100 #define NGX_HAVE_ATOMIC_OPS  1
101
102 #include "ngx_gcc_atomic_x86.h"
103
104 #endif
105
106
107 #elif ( __amd64__ || __amd64 )
108
109 typedef int64_t                     ngx_atomic_int_t;
110 typedef uint64_t                    ngx_atomic_uint_t;
111 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
112 #define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
113
114
115 #if ( __SUNPRO_C )
116
117 #define NGX_HAVE_ATOMIC_OPS  1
118
119 ngx_atomic_uint_t
120 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
121     ngx_atomic_uint_t set);
122
123 ngx_atomic_int_t
124 ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
125
126 /*
127  * Sun Studio 12 exits with segmentation fault on '__asm ("pause")',
128  * so ngx_cpu_pause is declared in src/os/unix/ngx_sunpro_amd64.il
129  */
130
131 void
132 ngx_cpu_pause(void);
133
134 /* the code in src/os/unix/ngx_sunpro_amd64.il */
135
136 #define ngx_memory_barrier()        __asm (".volatile"); __asm (".nonvolatile")
137
138
139 #else /* ( __GNUC__ || __INTEL_COMPILER ) */
140
141 #define NGX_HAVE_ATOMIC_OPS  1
142
143 #include "ngx_gcc_atomic_amd64.h"
144
145 #endif
146
147
148 #elif ( __sparc__ || __sparc || __sparcv9 )
149
150 #if (NGX_PTR_SIZE == 8)
151
152 typedef int64_t                     ngx_atomic_int_t;
153 typedef uint64_t                    ngx_atomic_uint_t;
154 #define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
155
156 #else
157
158 typedef int32_t                     ngx_atomic_int_t;
159 typedef uint32_t                    ngx_atomic_uint_t;
160 #define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
161
162 #endif
163
164 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
165
166
167 #if ( __SUNPRO_C )
168
169 #define NGX_HAVE_ATOMIC_OPS  1
170
171 #include "ngx_sunpro_atomic_sparc64.h"
172
173
174 #else /* ( __GNUC__ || __INTEL_COMPILER ) */
175
176 #define NGX_HAVE_ATOMIC_OPS  1
177
178 #include "ngx_gcc_atomic_sparc64.h"
179
180 #endif
181
182
183 #elif ( __powerpc__ || __POWERPC__ )
184
185 #define NGX_HAVE_ATOMIC_OPS  1
186
187 #if (NGX_PTR_SIZE == 8)
188
189 typedef int64_t                     ngx_atomic_int_t;
190 typedef uint64_t                    ngx_atomic_uint_t;
191 #define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
192
193 #else
194
195 typedef int32_t                     ngx_atomic_int_t;
196 typedef uint32_t                    ngx_atomic_uint_t;
197 #define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
198
199 #endif
200
201 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
202
203
204 #include "ngx_gcc_atomic_ppc.h"
205
206
207 #endif
208
209 #endif
210
211
212 #if !(NGX_HAVE_ATOMIC_OPS)
213
214 #define NGX_HAVE_ATOMIC_OPS  0
215
216 typedef int32_t                     ngx_atomic_int_t;
217 typedef uint32_t                    ngx_atomic_uint_t;
218 typedef volatile ngx_atomic_uint_t  ngx_atomic_t;
219 #define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
220
221
222 static ngx_inline ngx_atomic_uint_t
223 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
224      ngx_atomic_uint_t set)
225 {
226      if (*lock == old) {
227          *lock = set;
228          return 1;
229      }
230
231      return 0;
232 }
233
234
235 static ngx_inline ngx_atomic_int_t
236 ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
237 {
238      ngx_atomic_int_t  old;
239
240      old = *value;
241      *value += add;
242
243      return old;
244 }
245
246 #define ngx_memory_barrier()
247 #define ngx_cpu_pause()
248
249 #endif
250
251
252 void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin);
253
254 #define ngx_trylock(lock)  (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1))
255 #define ngx_unlock(lock)    *(lock) = 0
256
257
258 #endif /* _NGX_ATOMIC_H_INCLUDED_ */