Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-10-12 17:50:36 +0400
committerIgor Sysoev <igor@sysoev.ru>2005-10-12 17:50:36 +0400
commit784522377ec160bc148ff3bb40fb87ede7506d5d (patch)
tree0c76a9c51a1c2ffa35ad3eb05e3b80f6cc19c60a /src/os/unix/ngx_atomic.h
parentbbfe3033bc82427b15ccf73767e786cbb12a7627 (diff)
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_atomic.h')
-rw-r--r--src/os/unix/ngx_atomic.h384
1 files changed, 76 insertions, 308 deletions
diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h
index b3d300314..5856103c6 100644
--- a/src/os/unix/ngx_atomic.h
+++ b/src/os/unix/ngx_atomic.h
@@ -14,275 +14,99 @@
#if ( __i386__ || __i386 )
-#define NGX_HAVE_ATOMIC_OPS 1
-
-typedef int32_t ngx_atomic_int_t;
-typedef uint32_t ngx_atomic_uint_t;
+typedef int32_t ngx_atomic_int_t;
+typedef uint32_t ngx_atomic_uint_t;
typedef volatile ngx_atomic_uint_t ngx_atomic_t;
-#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
-
-
-#if (NGX_SMP)
-#define NGX_SMP_LOCK "lock;"
-#else
-#define NGX_SMP_LOCK
-#endif
-
-/*
- * the "=q" is any of the %eax, %ebx, %ecx, or %edx registers.
- * the '"0" (1)' parameter preloads 1 into %0.
- * the "cc" means that flags were changed.
- *
- * "xadd r, [m]":
- *
- * temp = [m];
- * [m] += r;
- * r = temp;
- */
-
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_inc(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t old;
-
- __asm__ volatile (
-
- NGX_SMP_LOCK
- " xaddl %0, %2; "
- " incl %0; "
-
- : "=q" (old) : "0" (1), "m" (*value) : "cc", "memory");
-
- return old;
-}
-
-
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t old;
-
- __asm__ volatile (
-
- NGX_SMP_LOCK
- " xaddl %0, %2; "
- " decl %0; "
-
- : "=q" (old) : "0" (-1), "m" (*value) : "cc", "memory");
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
- return old;
-}
+#if ( __SUNPRO_C )
-/*
- * 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 cmpxchg anyway.
- *
- * "cmpxchg r, [m]":
- *
- * if (eax == [m]) {
- * zf = 1;
- * [m] = r;
- * } else {
- * zf = 0;
- * eax = [m];
- * }
- */
+#define NGX_HAVE_ATOMIC_OPS 1
-static ngx_inline ngx_atomic_uint_t
+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;
+ ngx_atomic_uint_t set);
- __asm__ volatile (
+ngx_atomic_int_t
+ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
- NGX_SMP_LOCK
- " cmpxchgl %3, %1; "
- " setz %b0; "
- " movzbl %b0, %0; "
+/* the code in src/os/unix/ngx_sunpro_x86.il */
- : "=a" (res) : "m" (*lock), "a" (old), "q" (set) : "cc", "memory");
-
- return res;
-}
-
-#elif ( __amd64__ || __amd64 )
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
#define NGX_HAVE_ATOMIC_OPS 1
-typedef int64_t ngx_atomic_int_t;
-typedef uint64_t ngx_atomic_uint_t;
-typedef volatile ngx_atomic_uint_t ngx_atomic_t;
-#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
-
+#include "ngx_gcc_atomic_x86.h"
-#if (NGX_SMP)
-#define NGX_SMP_LOCK "lock;"
-#else
-#define NGX_SMP_LOCK
#endif
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_inc(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t old;
-
- __asm__ volatile (
-
- NGX_SMP_LOCK
- " xaddq %0, %2; "
- " incq %0; "
-
- : "=r" (old) : "0" (1), "m" (*value) : "cc", "memory");
-
- return old;
-}
-
-
-/* the '"0" (-1LL)' parameter preloads -1 into the 64-bit %0 register */
-
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t old;
-
- __asm__ volatile (
-
- NGX_SMP_LOCK
- " xaddq %0, %2; "
- " decq %0; "
+#elif ( __amd64__ || __amd64 )
- : "=r" (old) : "0" (-1LL), "m" (*value) : "cc", "memory");
+typedef int64_t ngx_atomic_int_t;
+typedef uint64_t ngx_atomic_uint_t;
+typedef volatile ngx_atomic_uint_t ngx_atomic_t;
+#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
- return old;
-}
+#if ( __SUNPRO_C )
-/* the "=a" and "a" are the %rax register. */
+#define NGX_HAVE_ATOMIC_OPS 1
-static ngx_inline ngx_atomic_uint_t
+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_atomic_uint_t set);
- NGX_SMP_LOCK
- " cmpxchgq %3, %1; "
- " setz %b0; "
- " movzbq %b0, %0; "
+ngx_atomic_int_t
+ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
- : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
+/* the code in src/os/unix/ngx_sunpro_amd64.il */
- return res;
-}
-
-#elif ( __sparc__ || __sparcv9 )
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
#define NGX_HAVE_ATOMIC_OPS 1
-#if (NGX_PTR_SIZE == 8)
-typedef int64_t ngx_atomic_int_t;
-typedef uint64_t ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
-#define NGX_CASXA "casxa"
-#else
-typedef int32_t ngx_atomic_int_t;
-typedef uint32_t ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
-#define NGX_CASXA "casa"
-#endif
-
-typedef volatile ngx_atomic_uint_t ngx_atomic_t;
-
-
-/*
- * the "+r" means the general register used for both input and output.
- *
- * "casa [r1] 0x80, r2, r0" and
- * "casxa [r1] 0x80, r2, r0" do the following:
- *
- * if ([r1] == r2) {
- * swap(r0, [r1]);
- * } else {
- * r0 = [r1];
- * }
- *
- * so "r0 == r2" means that the operation was successfull.
- */
-
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_inc(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t old, new, res;
-
- old = *value;
-
- for ( ;; ) {
+#include "ngx_gcc_atomic_amd64.h"
- new = old + 1;
- res = new;
-
- __asm__ volatile (
-
- NGX_CASXA " [%1] 0x80, %2, %0"
-
- : "+r" (res) : "r" (value), "r" (old) : "memory");
+#endif
- if (res == old) {
- return new;
- }
- old = res;
- }
-}
+#elif ( __sparc__ || __sparcv9 )
+#if (NGX_PTR_SIZE == 8)
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t old, new, res;
+typedef int64_t ngx_atomic_int_t;
+typedef uint64_t ngx_atomic_uint_t;
+#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
- old = *value;
+#else
- for ( ;; ) {
+typedef int32_t ngx_atomic_int_t;
+typedef uint32_t ngx_atomic_uint_t;
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
- new = old - 1;
- res = new;
+#endif
- __asm__ volatile (
+typedef volatile ngx_atomic_uint_t ngx_atomic_t;
- NGX_CASXA " [%1] 0x80, %2, %0"
- : "+r" (res) : "r" (value), "r" (old) : "memory");
+#if ( __SUNPRO_C )
- if (res == old) {
- return new;
- }
+#define NGX_HAVE_ATOMIC_OPS 1
- old = res;
- }
-}
+#include "ngx_sunpro_atomic_sparc64.h"
-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)
-{
- __asm__ volatile (
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
- NGX_CASXA " [%1] 0x80, %2, %0"
+#define NGX_HAVE_ATOMIC_OPS 1
- : "+r" (set) : "r" (lock), "r" (old) : "memory");
+#include "ngx_gcc_atomic_sparc64.h"
- return (set == old);
-}
+#endif
#elif ( __ppc__ || __powerpc__ )
@@ -290,116 +114,60 @@ ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
#define NGX_HAVE_ATOMIC_OPS 1
#if (NGX_PTR_SIZE == 8)
-typedef int64_t ngx_atomic_int_t;
-typedef uint64_t ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
-#else
-typedef int32_t ngx_atomic_int_t;
-typedef uint32_t ngx_atomic_uint_t;
-#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
-#endif
-
-typedef volatile ngx_atomic_uint_t ngx_atomic_t;
+typedef int64_t ngx_atomic_int_t;
+typedef uint64_t ngx_atomic_uint_t;
+#define NGX_ATOMIC_T_LEN sizeof("-9223372036854775808") - 1
-/*
- * the ppc assembler treats ";" as comment, so we have to use "\n".
- * the minus in "bne-" is a hint for the branch prediction unit that
- * this branch is unlikely to be taken.
- *
- * the "=&r" means that no input registers can be used.
- * the "=&b" means that the base registers can be used only, i.e.
- * any register except r0. the r0 register always has a zero value and
- * could not be used in "addi r0, r0, 1".
- * the "1b" means the nearest backward label "1" and the "1f" means
- * the nearest forward label "1".
- */
+#else
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_inc(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t res;
+typedef int32_t ngx_atomic_int_t;
+typedef uint32_t ngx_atomic_uint_t;
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
- __asm__ volatile (
+#endif
- "1: lwarx %0, 0, %1 \n" /* load from [value] into "res" */
- /* and store reservation */
- " addi %0, %0, 1 \n" /* add "1" to "res" */
- " stwcx. %0, 0, %1 \n" /* store "res" into [value] if reservation */
- /* is not cleared */
- " bne- 1b \n" /* try again if reservation was cleared */
+typedef volatile ngx_atomic_uint_t ngx_atomic_t;
- : "=&b" (res) : "r" (value) : "cc", "memory");
- return res;
-}
+#include "ngx_gcc_atomic_ppc.h"
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
- ngx_atomic_uint_t res;
+#endif
- __asm__ volatile (
- "1: lwarx %0, 0, %1 \n" /* load from [value] into "res" */
- /* and store reservation */
- " addi %0, %0, -1 \n" /* sub "1" from "res" */
- " stwcx. %0, 0, %1 \n" /* store "res" into [value] if reservation */
- /* is not cleared */
- " bne- 1b \n" /* try again if reservation was cleared */
+#if !(NGX_HAVE_ATOMIC_OPS)
- : "=&b" (res) : "r" (value) : "cc", "memory");
+#define NGX_HAVE_ATOMIC_OPS 0
- return res;
-}
+typedef int32_t ngx_atomic_int_t;
+typedef uint32_t ngx_atomic_uint_t;
+typedef volatile ngx_atomic_uint_t ngx_atomic_t;
+#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
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 set)
{
- ngx_atomic_uint_t res, temp;
-
- __asm__ volatile (
-
- " li %0, 0 \n" /* preset "0" to "res" */
- " lwarx %1, 0, %2 \n" /* load from [lock] into "temp" */
- /* and store reservation */
- " cmpw %1, %3 \n" /* compare "temp" and "old" */
- " bne- 1f \n" /* not equal */
- " stwcx. %4, 0, %2 \n" /* store "set" into [lock] if reservation */
- /* is not cleared */
- " bne- 1f \n" /* the reservation was cleared */
- " li %0, 1 \n" /* set "1" to "res" */
- "1: \n"
-
- : "=&r" (res), "=&r" (temp)
- : "r" (lock), "r" (old), "r" (set)
- : "cc", "memory");
-
- return res;
-}
+ if (*lock == old {
+ *lock = set;
+ return 1;
+ }
+ return 0;
+}
-#else
-#define NGX_HAVE_ATOMIC_OPS 0
-
-typedef int32_t ngx_atomic_int_t;
-typedef uint32_t ngx_atomic_uint_t;
-typedef volatile ngx_atomic_uint_t ngx_atomic_t;
-#define NGX_ATOMIC_T_LEN sizeof("-2147483648") - 1
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
+{
+ ngx_atomic_int_t old;
-#define ngx_atomic_inc(x) ++(*(x))
-#define ngx_atomic_dec(x) --(*(x))
+ old = *value;
+ *value += add;
-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)
-{
- *lock = set;
- return 1;
+ return old;
}
#endif