diff src/os/unix/ngx_gcc_atomic_x86.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
children 408f195b3482
line wrap: on
line diff
new file mode 100644
--- /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