diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-10-12 13:50:36 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-10-12 13:50:36 +0000 |
commit | 784522377ec160bc148ff3bb40fb87ede7506d5d (patch) | |
tree | 0c76a9c51a1c2ffa35ad3eb05e3b80f6cc19c60a /src/os/unix/ngx_gcc_atomic_x86.h | |
parent | bbfe3033bc82427b15ccf73767e786cbb12a7627 (diff) | |
download | nginx-release-0.3.2.tar.gz nginx-release-0.3.2.zip |
nginx-0.3.2-RELEASE importrelease-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.
Diffstat (limited to 'src/os/unix/ngx_gcc_atomic_x86.h')
-rw-r--r-- | src/os/unix/ngx_gcc_atomic_x86.h | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/os/unix/ngx_gcc_atomic_x86.h b/src/os/unix/ngx_gcc_atomic_x86.h new file mode 100644 index 000000000..e3c0c9379 --- /dev/null +++ b/src/os/unix/ngx_gcc_atomic_x86.h @@ -0,0 +1,103 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#if (NGX_SMP) +#define NGX_SMP_LOCK "lock;" +#else +#define NGX_SMP_LOCK +#endif + + +/* + * "cmpxchgl r, [m]": + * + * if (eax == [m]) { + * zf = 1; + * [m] = r; + * } else { + * zf = 0; + * eax = [m]; + * } + * + * + * The "q" is any of the %eax, %ebx, %ecx, or %edx registers. + * The "=a" and "a" are the %eax register. Although we can return result + * in any register, we use %eax because it is used in cmpxchgl anyway. + * The "cc" means that flags were changed. + */ + +static ngx_inline ngx_atomic_uint_t +ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old, + ngx_atomic_uint_t set) +{ + ngx_atomic_uint_t res; + + __asm__ volatile ( + + NGX_SMP_LOCK + " cmpxchgl %3, %1; " + " setz %b0; " + " movzbl %b0, %0; " + + : "=a" (res) : "m" (*lock), "a" (old), "q" (set) : "cc", "memory"); + + return res; +} + + +/* + * "xaddl r, [m]": + * + * temp = [m]; + * [m] += r; + * r = temp; + * + * + * The "+q" is any of the %eax, %ebx, %ecx, or %edx registers. + * The "cc" means that flags were changed. + */ + + +#if !(__GNUC__ == 2 && __GNUC_MINOR__ <= 7) + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + __asm__ volatile ( + + NGX_SMP_LOCK + " xaddl %0, %1; " + + : "+q" (add) : "m" (*value) : "cc", "memory"); + + return add; +} + + +#else /* (__GNUC__ == 2 && __GNUC_MINOR__ <= 7) */ + +/* + * gcc 2.7 does not support "+q", so we have to use the fixed %eax ("=a" and + * "a") and this adds two superfluous instructions in the end of code, + * something like this: "mov %eax, %edx / mov %edx, %eax". + */ + +static ngx_inline ngx_atomic_int_t +ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add) +{ + ngx_atomic_uint_t old; + + __asm__ volatile ( + + NGX_SMP_LOCK + " xaddl %2, %1; " + + : "=a" (old) : "m" (*value), "a" (add) : "cc", "memory"); + + return old; +} + +#endif |