Annotation of embedaddon/nginx/src/os/unix/ngx_gcc_atomic_x86.h, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #if (NGX_SMP)
9: #define NGX_SMP_LOCK "lock;"
10: #else
11: #define NGX_SMP_LOCK
12: #endif
13:
14:
15: /*
16: * "cmpxchgl r, [m]":
17: *
18: * if (eax == [m]) {
19: * zf = 1;
20: * [m] = r;
21: * } else {
22: * zf = 0;
23: * eax = [m];
24: * }
25: *
26: *
27: * The "r" means the general register.
28: * The "=a" and "a" are the %eax register.
29: * Although we can return result in any register, we use "a" because it is
30: * used in cmpxchgl anyway. The result is actually in %al but not in %eax,
31: * however, as the code is inlined gcc can test %al as well as %eax,
32: * and icc adds "movzbl %al, %eax" by itself.
33: *
34: * The "cc" means that flags were changed.
35: */
36:
37: static ngx_inline ngx_atomic_uint_t
38: ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
39: ngx_atomic_uint_t set)
40: {
41: u_char res;
42:
43: __asm__ volatile (
44:
45: NGX_SMP_LOCK
46: " cmpxchgl %3, %1; "
47: " sete %0; "
48:
49: : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
50:
51: return res;
52: }
53:
54:
55: /*
56: * "xaddl r, [m]":
57: *
58: * temp = [m];
59: * [m] += r;
60: * r = temp;
61: *
62: *
63: * The "+r" means the general register.
64: * The "cc" means that flags were changed.
65: */
66:
67:
68: #if !(( __GNUC__ == 2 && __GNUC_MINOR__ <= 7 ) || ( __INTEL_COMPILER >= 800 ))
69:
70: /*
71: * icc 8.1 and 9.0 compile broken code with -march=pentium4 option:
72: * ngx_atomic_fetch_add() always return the input "add" value,
73: * so we use the gcc 2.7 version.
74: *
75: * icc 8.1 and 9.0 with -march=pentiumpro option or icc 7.1 compile
76: * correct code.
77: */
78:
79: static ngx_inline ngx_atomic_int_t
80: ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
81: {
82: __asm__ volatile (
83:
84: NGX_SMP_LOCK
85: " xaddl %0, %1; "
86:
87: : "+r" (add) : "m" (*value) : "cc", "memory");
88:
89: return add;
90: }
91:
92:
93: #else
94:
95: /*
96: * gcc 2.7 does not support "+r", so we have to use the fixed
97: * %eax ("=a" and "a") and this adds two superfluous instructions in the end
98: * of code, something like this: "mov %eax, %edx / mov %edx, %eax".
99: */
100:
101: static ngx_inline ngx_atomic_int_t
102: ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
103: {
104: ngx_atomic_uint_t old;
105:
106: __asm__ volatile (
107:
108: NGX_SMP_LOCK
109: " xaddl %2, %1; "
110:
111: : "=a" (old) : "m" (*value), "a" (add) : "cc", "memory");
112:
113: return old;
114: }
115:
116: #endif
117:
118:
119: /*
120: * on x86 the write operations go in a program order, so we need only
121: * to disable the gcc reorder optimizations
122: */
123:
124: #define ngx_memory_barrier() __asm__ volatile ("" ::: "memory")
125:
126: /* old "as" does not support "pause" opcode */
127: #define ngx_cpu_pause() __asm__ (".byte 0xf3, 0x90")
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>