diff 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
line wrap: on
line diff
--- 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;
-}
+#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
 
 
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
-    ngx_atomic_uint_t  old;
+#if ( __SUNPRO_C )
 
-    __asm__ volatile (
+#define NGX_HAVE_ATOMIC_OPS  1
 
-         NGX_SMP_LOCK
-    "    xaddl  %0, %2;   "
-    "    decl   %0;       "
+ngx_atomic_uint_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
+    ngx_atomic_uint_t set);
 
-    : "=q" (old) : "0" (-1), "m" (*value) : "cc", "memory");
+ngx_atomic_int_t
+ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
 
-    return old;
-}
+/* the code in src/os/unix/ngx_sunpro_x86.il */
 
 
-/*
- * 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];
- *     }
- */
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
+
+#define NGX_HAVE_ATOMIC_OPS  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  res;
-
-    __asm__ volatile (
+#include "ngx_gcc_atomic_x86.h"
 
-         NGX_SMP_LOCK
-    "    cmpxchgl  %3, %1;   "
-    "    setz      %b0;      "
-    "    movzbl    %b0, %0;  "
-
-    : "=a" (res) : "m" (*lock), "a" (old), "q" (set) : "cc", "memory");
-
-    return res;
-}
+#endif
 
 
 #elif ( __amd64__ || __amd64 )
 
-#define NGX_HAVE_ATOMIC_OPS  1
-
-typedef int64_t  ngx_atomic_int_t;
-typedef uint64_t  ngx_atomic_uint_t;
+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
-
-
-#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;
-}
+#define NGX_ATOMIC_T_LEN            sizeof("-9223372036854775808") - 1
 
 
-/* the '"0" (-1LL)' parameter preloads -1 into the 64-bit %0 register */
+#if ( __SUNPRO_C )
 
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
-    ngx_atomic_uint_t  old;
-
-    __asm__ volatile (
+#define NGX_HAVE_ATOMIC_OPS  1
 
-         NGX_SMP_LOCK
-    "    xaddq  %0, %2;   "
-    "    decq   %0;       "
+ngx_atomic_uint_t
+ngx_atomic_cmp_set(ngx_atomic_t *lock, ngx_atomic_uint_t old,
+    ngx_atomic_uint_t set);
 
-    : "=r" (old) : "0" (-1LL), "m" (*value) : "cc", "memory");
+ngx_atomic_int_t
+ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add);
 
-    return old;
-}
+/* the code in src/os/unix/ngx_sunpro_amd64.il */
 
 
-/* the "=a" and "a" are the %rax register. */
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
 
-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 (
+#define NGX_HAVE_ATOMIC_OPS  1
 
-         NGX_SMP_LOCK
-    "    cmpxchgq  %3, %1;   "
-    "    setz      %b0;      "
-    "    movzbq    %b0, %0;  "
+#include "ngx_gcc_atomic_amd64.h"
 
-    : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
-
-    return res;
-}
+#endif
 
 
 #elif ( __sparc__ || __sparcv9 )
 
-#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
 
-#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"
+
+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;
 
 
-/*
- * 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;
+#if ( __SUNPRO_C )
 
-    old = *value;
-
-    for ( ;; ) {
-
-        new = old + 1;
-        res = new;
-
-        __asm__ volatile (
+#define NGX_HAVE_ATOMIC_OPS  1
 
-        NGX_CASXA " [%1] 0x80, %2, %0"
-
-        : "+r" (res) : "r" (value), "r" (old) : "memory");
-
-        if (res == old) {
-            return new;
-        }
-
-        old = res;
-    }
-}
+#include "ngx_sunpro_atomic_sparc64.h"
 
 
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_dec(ngx_atomic_t *value)
-{
-    ngx_atomic_uint_t  old, new, res;
-
-    old = *value;
-
-    for ( ;; ) {
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
 
-        new = old - 1;
-        res = new;
-
-        __asm__ volatile (
-
-        NGX_CASXA " [%1] 0x80, %2, %0"
-
-        : "+r" (res) : "r" (value), "r" (old) : "memory");
+#define NGX_HAVE_ATOMIC_OPS  1
 
-        if (res == old) {
-            return new;
-        }
-
-        old = res;
-    }
-}
-
+#include "ngx_gcc_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 (
-
-    NGX_CASXA " [%1] 0x80, %2, %0"
-
-    : "+r" (set) : "r" (lock), "r" (old) : "memory");
-
-    return (set == old);
-}
+#endif
 
 
 #elif ( __ppc__ || __powerpc__ )
@@ -290,116 +114,60 @@ ngx_atomic_cmp_set(ngx_atomic_t *lock, n
 #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
+
+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
+
+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;
 
 
-/*
- * 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".
- */
-
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_inc(ngx_atomic_t *value)
-{
-    ngx_atomic_uint_t  res;
-
-    __asm__ volatile (
-
-    "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     */
-
-    : "=&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;
-
-    __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     */
-
-    : "=&b" (res) : "r" (value) : "cc", "memory");
-
-    return res;
-}
+#endif
 
 
-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, 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;
-}
-
-
-#else
+#if !(NGX_HAVE_ATOMIC_OPS)
 
 #define NGX_HAVE_ATOMIC_OPS  0
 
-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
+#define NGX_ATOMIC_T_LEN            sizeof("-2147483648") - 1
 
-#define ngx_atomic_inc(x)  ++(*(x))
-#define ngx_atomic_dec(x)  --(*(x))
 
 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;
+     if (*lock == old {
+         *lock = set;
+         return 1;
+     }
+
+     return 0;
+}
+
+
+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;
+
+     old = *value;
+     *value += add;
+
+     return old;
 }
 
 #endif