comparison src/os/unix/ngx_atomic.h @ 110:dad2fe8ecf08 NGINX_0_3_2

nginx 0.3.2 *) Feature: the Sun Studio 10 C compiler support. *) Feature: the "proxy_upstream_max_fails", "proxy_upstream_fail_timeout", "fastcgi_upstream_max_fails", and "fastcgi_upstream_fail_timeout" directives.
author Igor Sysoev <http://sysoev.ru>
date Wed, 12 Oct 2005 00:00:00 +0400
parents d6800bbe720e
children 408f195b3482
comparison
equal deleted inserted replaced
109:97da525033a1 110:dad2fe8ecf08
12 #include <ngx_core.h> 12 #include <ngx_core.h>
13 13
14 14
15 #if ( __i386__ || __i386 ) 15 #if ( __i386__ || __i386 )
16 16
17 typedef int32_t ngx_atomic_int_t;
18 typedef uint32_t ngx_atomic_uint_t;
19 typedef volatile ngx_atomic_uint_t ngx_atomic_t;
20 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
21
22
23 #if ( __SUNPRO_C )
24
17 #define NGX_HAVE_ATOMIC_OPS 1 25 #define NGX_HAVE_ATOMIC_OPS 1
18 26
19 typedef int32_t ngx_atomic_int_t; 27 ngx_atomic_uint_t
20 typedef uint32_t ngx_atomic_uint_t; 28 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
21 typedef volatile ngx_atomic_uint_t ngx_atomic_t; 29 ngx_atomic_uint_t set);
22 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 30
31 ngx_atomic_int_t
32 ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
33
34 /* the code in src/os/unix/ngx_sunpro_x86.il */
23 35
24 36
25 #if (NGX_SMP) 37 #else /* ( __GNUC__ || __INTEL_COMPILER ) */
26 #define NGX_SMP_LOCK "lock;" 38
27 #else 39 #define NGX_HAVE_ATOMIC_OPS 1
28 #define NGX_SMP_LOCK 40
41 #include "ngx_gcc_atomic_x86.h"
42
29 #endif 43 #endif
30
31 /*
32 * the "=q" is any of the %eax, %ebx, %ecx, or %edx registers.
33 * the '"0" (1)' parameter preloads 1 into %0.
34 * the "cc" means that flags were changed.
35 *
36 * "xadd r, [m]":
37 *
38 * temp = [m];
39 * [m] += r;
40 * r = temp;
41 */
42
43 static ngx_inline ngx_atomic_uint_t
44 ngx_atomic_inc(ngx_atomic_t *value)
45 {
46 ngx_atomic_uint_t old;
47
48 __asm__ volatile (
49
50 NGX_SMP_LOCK
51 " xaddl %0, %2; "
52 " incl %0; "
53
54 : "=q" (old) : "0" (1), "m" (*value) : "cc", "memory");
55
56 return old;
57 }
58
59
60 static ngx_inline ngx_atomic_uint_t
61 ngx_atomic_dec(ngx_atomic_t *value)
62 {
63 ngx_atomic_uint_t old;
64
65 __asm__ volatile (
66
67 NGX_SMP_LOCK
68 " xaddl %0, %2; "
69 " decl %0; "
70
71 : "=q" (old) : "0" (-1), "m" (*value) : "cc", "memory");
72
73 return old;
74 }
75
76
77 /*
78 * the "q" is any of the %eax, %ebx, %ecx, or %edx registers.
79 * the "=a" and "a" are the %eax register. Although we can return result
80 * in any register, we use %eax because it is used in cmpxchg anyway.
81 *
82 * "cmpxchg r, [m]":
83 *
84 * if (eax == [m]) {
85 * zf = 1;
86 * [m] = r;
87 * } else {
88 * zf = 0;
89 * eax = [m];
90 * }
91 */
92
93 static ngx_inline ngx_atomic_uint_t
94 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
95 ngx_atomic_uint_t set)
96 {
97 ngx_atomic_uint_t res;
98
99 __asm__ volatile (
100
101 NGX_SMP_LOCK
102 " cmpxchgl %3, %1; "
103 " setz %b0; "
104 " movzbl %b0, %0; "
105
106 : "=a" (res) : "m" (*lock), "a" (old), "q" (set) : "cc", "memory");
107
108 return res;
109 }
110 44
111 45
112 #elif ( __amd64__ || __amd64 ) 46 #elif ( __amd64__ || __amd64 )
113 47
48 typedef int64_t ngx_atomic_int_t;
49 typedef uint64_t ngx_atomic_uint_t;
50 typedef volatile ngx_atomic_uint_t ngx_atomic_t;
51 #define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
52
53
54 #if ( __SUNPRO_C )
55
114 #define NGX_HAVE_ATOMIC_OPS 1 56 #define NGX_HAVE_ATOMIC_OPS 1
115 57
116 typedef int64_t ngx_atomic_int_t; 58 ngx_atomic_uint_t
117 typedef uint64_t ngx_atomic_uint_t; 59 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
118 typedef volatile ngx_atomic_uint_t ngx_atomic_t; 60 ngx_atomic_uint_t set);
119 #define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 61
62 ngx_atomic_int_t
63 ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
64
65 /* the code in src/os/unix/ngx_sunpro_amd64.il */
120 66
121 67
122 #if (NGX_SMP) 68 #else /* ( __GNUC__ || __INTEL_COMPILER ) */
123 #define NGX_SMP_LOCK "lock;" 69
124 #else 70 #define NGX_HAVE_ATOMIC_OPS 1
125 #define NGX_SMP_LOCK 71
72 #include "ngx_gcc_atomic_amd64.h"
73
126 #endif 74 #endif
127
128
129 static ngx_inline ngx_atomic_uint_t
130 ngx_atomic_inc(ngx_atomic_t *value)
131 {
132 ngx_atomic_uint_t old;
133
134 __asm__ volatile (
135
136 NGX_SMP_LOCK
137 " xaddq %0, %2; "
138 " incq %0; "
139
140 : "=r" (old) : "0" (1), "m" (*value) : "cc", "memory");
141
142 return old;
143 }
144
145
146 /* the '"0" (-1LL)' parameter preloads -1 into the 64-bit %0 register */
147
148 static ngx_inline ngx_atomic_uint_t
149 ngx_atomic_dec(ngx_atomic_t *value)
150 {
151 ngx_atomic_uint_t old;
152
153 __asm__ volatile (
154
155 NGX_SMP_LOCK
156 " xaddq %0, %2; "
157 " decq %0; "
158
159 : "=r" (old) : "0" (-1LL), "m" (*value) : "cc", "memory");
160
161 return old;
162 }
163
164
165 /* the "=a" and "a" are the %rax register. */
166
167 static ngx_inline ngx_atomic_uint_t
168 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
169 ngx_atomic_uint_t set)
170 {
171 ngx_atomic_uint_t res;
172
173 __asm__ volatile (
174
175 NGX_SMP_LOCK
176 " cmpxchgq %3, %1; "
177 " setz %b0; "
178 " movzbq %b0, %0; "
179
180 : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
181
182 return res;
183 }
184 75
185 76
186 #elif ( __sparc__ || __sparcv9 ) 77 #elif ( __sparc__ || __sparcv9 )
187 78
188 #define NGX_HAVE_ATOMIC_OPS 1 79 #if (NGX_PTR_SIZE == 8)
189 80
190 #if (NGX_PTR_SIZE == 8) 81 typedef int64_t ngx_atomic_int_t;
191 typedef int64_t ngx_atomic_int_t; 82 typedef uint64_t ngx_atomic_uint_t;
192 typedef uint64_t ngx_atomic_uint_t; 83 #define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
193 #define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 84
194 #define NGX_CASXA "casxa"
195 #else 85 #else
196 typedef int32_t ngx_atomic_int_t; 86
197 typedef uint32_t ngx_atomic_uint_t; 87 typedef int32_t ngx_atomic_int_t;
198 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 88 typedef uint32_t ngx_atomic_uint_t;
199 #define NGX_CASXA "casa" 89 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
90
200 #endif 91 #endif
201 92
202 typedef volatile ngx_atomic_uint_t ngx_atomic_t; 93 typedef volatile ngx_atomic_uint_t ngx_atomic_t;
203 94
204 95
205 /* 96 #if ( __SUNPRO_C )
206 * the "+r" means the general register used for both input and output.
207 *
208 * "casa [r1] 0x80, r2, r0" and
209 * "casxa [r1] 0x80, r2, r0" do the following:
210 *
211 * if ([r1] == r2) {
212 * swap(r0, [r1]);
213 * } else {
214 * r0 = [r1];
215 * }
216 *
217 * so "r0 == r2" means that the operation was successfull.
218 */
219 97
220 static ngx_inline ngx_atomic_uint_t 98 #define NGX_HAVE_ATOMIC_OPS 1
221 ngx_atomic_inc(ngx_atomic_t *value)
222 {
223 ngx_atomic_uint_t old, new, res;
224 99
225 old = *value; 100 #include "ngx_sunpro_atomic_sparc64.h"
226
227 for ( ;; ) {
228
229 new = old + 1;
230 res = new;
231
232 __asm__ volatile (
233
234 NGX_CASXA " [%1] 0x80, %2, %0"
235
236 : "+r" (res) : "r" (value), "r" (old) : "memory");
237
238 if (res == old) {
239 return new;
240 }
241
242 old = res;
243 }
244 }
245 101
246 102
247 static ngx_inline ngx_atomic_uint_t 103 #else /* ( __GNUC__ || __INTEL_COMPILER ) */
248 ngx_atomic_dec(ngx_atomic_t *value)
249 {
250 ngx_atomic_uint_t old, new, res;
251 104
252 old = *value; 105 #define NGX_HAVE_ATOMIC_OPS 1
253 106
254 for ( ;; ) { 107 #include "ngx_gcc_atomic_sparc64.h"
255 108
256 new = old - 1; 109 #endif
257 res = new;
258
259 __asm__ volatile (
260
261 NGX_CASXA " [%1] 0x80, %2, %0"
262
263 : "+r" (res) : "r" (value), "r" (old) : "memory");
264
265 if (res == old) {
266 return new;
267 }
268
269 old = res;
270 }
271 }
272
273
274 static ngx_inline ngx_atomic_uint_t
275 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
276 ngx_atomic_uint_t set)
277 {
278 __asm__ volatile (
279
280 NGX_CASXA " [%1] 0x80, %2, %0"
281
282 : "+r" (set) : "r" (lock), "r" (old) : "memory");
283
284 return (set == old);
285 }
286 110
287 111
288 #elif ( __ppc__ || __powerpc__ ) 112 #elif ( __ppc__ || __powerpc__ )
289 113
290 #define NGX_HAVE_ATOMIC_OPS 1 114 #define NGX_HAVE_ATOMIC_OPS 1
291 115
292 #if (NGX_PTR_SIZE == 8) 116 #if (NGX_PTR_SIZE == 8)
293 typedef int64_t ngx_atomic_int_t; 117
294 typedef uint64_t ngx_atomic_uint_t; 118 typedef int64_t ngx_atomic_int_t;
295 #define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1 119 typedef uint64_t ngx_atomic_uint_t;
120 #define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
121
296 #else 122 #else
297 typedef int32_t ngx_atomic_int_t; 123
298 typedef uint32_t ngx_atomic_uint_t; 124 typedef int32_t ngx_atomic_int_t;
299 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 125 typedef uint32_t ngx_atomic_uint_t;
126 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
127
300 #endif 128 #endif
301 129
302 typedef volatile ngx_atomic_uint_t ngx_atomic_t; 130 typedef volatile ngx_atomic_uint_t ngx_atomic_t;
303 131
304 132
305 /* 133 #include "ngx_gcc_atomic_ppc.h"
306 * the ppc assembler treats ";" as comment, so we have to use "\n".
307 * the minus in "bne-" is a hint for the branch prediction unit that
308 * this branch is unlikely to be taken.
309 *
310 * the "=&r" means that no input registers can be used.
311 * the "=&b" means that the base registers can be used only, i.e.
312 * any register except r0. the r0 register always has a zero value and
313 * could not be used in "addi r0, r0, 1".
314 * the "1b" means the nearest backward label "1" and the "1f" means
315 * the nearest forward label "1".
316 */
317
318 static ngx_inline ngx_atomic_uint_t
319 ngx_atomic_inc(ngx_atomic_t *value)
320 {
321 ngx_atomic_uint_t res;
322
323 __asm__ volatile (
324
325 "1: lwarx %0, 0, %1 \n" /* load from [value] into "res" */
326 /* and store reservation */
327 " addi %0, %0, 1 \n" /* add "1" to "res" */
328 " stwcx. %0, 0, %1 \n" /* store "res" into [value] if reservation */
329 /* is not cleared */
330 " bne- 1b \n" /* try again if reservation was cleared */
331
332 : "=&b" (res) : "r" (value) : "cc", "memory");
333
334 return res;
335 }
336 134
337 135
338 static ngx_inline ngx_atomic_uint_t 136 #endif
339 ngx_atomic_dec(ngx_atomic_t *value)
340 {
341 ngx_atomic_uint_t res;
342
343 __asm__ volatile (
344
345 "1: lwarx %0, 0, %1 \n" /* load from [value] into "res" */
346 /* and store reservation */
347 " addi %0, %0, -1 \n" /* sub "1" from "res" */
348 " stwcx. %0, 0, %1 \n" /* store "res" into [value] if reservation */
349 /* is not cleared */
350 " bne- 1b \n" /* try again if reservation was cleared */
351
352 : "=&b" (res) : "r" (value) : "cc", "memory");
353
354 return res;
355 }
356 137
357 138
358 static ngx_inline ngx_atomic_uint_t 139 #if !(NGX_HAVE_ATOMIC_OPS)
359 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
360 ngx_atomic_uint_t set)
361 {
362 ngx_atomic_uint_t res, temp;
363
364 __asm__ volatile (
365
366 " li %0, 0 \n" /* preset "0" to "res" */
367 " lwarx %1, 0, %2 \n" /* load from [lock] into "temp" */
368 /* and store reservation */
369 " cmpw %1, %3 \n" /* compare "temp" and "old" */
370 " bne- 1f \n" /* not equal */
371 " stwcx. %4, 0, %2 \n" /* store "set" into [lock] if reservation */
372 /* is not cleared */
373 " bne- 1f \n" /* the reservation was cleared */
374 " li %0, 1 \n" /* set "1" to "res" */
375 "1: \n"
376
377 : "=&r" (res), "=&r" (temp)
378 : "r" (lock), "r" (old), "r" (set)
379 : "cc", "memory");
380
381 return res;
382 }
383
384
385 #else
386 140
387 #define NGX_HAVE_ATOMIC_OPS 0 141 #define NGX_HAVE_ATOMIC_OPS 0
388 142
389 typedef int32_t ngx_atomic_int_t; 143 typedef int32_t ngx_atomic_int_t;
390 typedef uint32_t ngx_atomic_uint_t; 144 typedef uint32_t ngx_atomic_uint_t;
391 typedef volatile ngx_atomic_uint_t ngx_atomic_t; 145 typedef volatile ngx_atomic_uint_t ngx_atomic_t;
392 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1 146 #define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
393 147
394 #define ngx_atomic_inc(x) ++(*(x))
395 #define ngx_atomic_dec(x) --(*(x))
396 148
397 static ngx_inline ngx_atomic_uint_t 149 static ngx_inline ngx_atomic_uint_t
398 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, 150 ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
399 ngx_atomic_uint_t set) 151 ngx_atomic_uint_t set)
400 { 152 {
401 *lock = set; 153 if (*lock == old {
402 return 1; 154 *lock = set;
155 return 1;
156 }
157
158 return 0;
159 }
160
161
162 static ngx_inline ngx_atomic_int_t
163 ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
164 {
165 ngx_atomic_int_t old;
166
167 old = *value;
168 *value += add;
169
170 return old;
403 } 171 }
404 172
405 #endif 173 #endif
406 174
407 175