nginx-0.3.2-RELEASE import

    *) 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.
diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h
index b3d3003..5856103 100644
--- a/src/os/unix/ngx_atomic.h
+++ b/src/os/unix/ngx_atomic.h
@@ -14,275 +14,99 @@
 
 #if ( __i386__ || __i386 )
 
+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 ( __SUNPRO_C )
+
 #define NGX_HAVE_ATOMIC_OPS  1
 
-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");
-
-    return old;
-}
-
-
-/*
- * 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];
- *     }
- */
-
-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;
-}
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
+
+#define NGX_HAVE_ATOMIC_OPS  1
+
+#include "ngx_gcc_atomic_x86.h"
+
+#endif
 
 
 #elif ( __amd64__ || __amd64 )
 
+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 ( __SUNPRO_C )
+
 #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
-
-
-#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;       "
-
-    : "=r" (old) : "0" (-1LL), "m" (*value) : "cc", "memory");
-
-    return old;
-}
-
-
-/* the "=a" and "a" are the %rax register. */
-
-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
-    "    cmpxchgq  %3, %1;   "
-    "    setz      %b0;      "
-    "    movzbq    %b0, %0;  "
+/* the code in src/os/unix/ngx_sunpro_amd64.il */
 
-    : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
 
-    return res;
-}
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
+
+#define NGX_HAVE_ATOMIC_OPS  1
+
+#include "ngx_gcc_atomic_amd64.h"
+
+#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
-#define NGX_CASXA         "casxa"
+
+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
-#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.
- */
+#if ( __SUNPRO_C )
 
-static ngx_inline ngx_atomic_uint_t
-ngx_atomic_inc(ngx_atomic_t *value)
-{
-    ngx_atomic_uint_t  old, new, res;
+#define NGX_HAVE_ATOMIC_OPS  1
 
-    old = *value;
-
-    for ( ;; ) {
-
-        new = old + 1;
-        res = new;
-
-        __asm__ volatile (
-
-        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;
+#else /* ( __GNUC__ || __INTEL_COMPILER ) */
 
-    old = *value;
+#define NGX_HAVE_ATOMIC_OPS  1
 
-    for ( ;; ) {
+#include "ngx_gcc_atomic_sparc64.h"
 
-        new = old - 1;
-        res = new;
-
-        __asm__ volatile (
-
-        NGX_CASXA " [%1] 0x80, %2, %0"
-
-        : "+r" (res) : "r" (value), "r" (old) : "memory");
-
-        if (res == old) {
-            return new;
-        }
-
-        old = res;
-    }
-}
-
-
-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 @@
 #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
diff --git a/src/os/unix/ngx_channel.c b/src/os/unix/ngx_channel.c
index 01a0514..051f466 100644
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -192,30 +192,14 @@
         return NGX_ERROR;
     }
 
+    c->pool = cycle->pool;
+
     rev = c->read;
     wev = c->write;
 
-    ngx_memzero(c, sizeof(ngx_connection_t));
-
-    c->read = rev;
-    c->write = wev;
-    c->fd = fd;
-    c->log = cycle->log;
-
-    c->pool = cycle->pool;
-
-    ngx_memzero(rev, sizeof(ngx_event_t));
-    ngx_memzero(wev, sizeof(ngx_event_t));
-
     rev->log = cycle->log;
     wev->log = cycle->log;
 
-    rev->index = NGX_INVALID_INDEX;
-    wev->index = NGX_INVALID_INDEX;
-
-    rev->data = c;
-    wev->data = c;
-
 #if (NGX_THREADS)
     rev->lock = &c->lock;
     wev->lock = &c->lock;
diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c
index f8f98c7..67cad1a 100644
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -8,9 +8,10 @@
 #include <ngx_core.h>
 
 
-ssize_t ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
+ssize_t
+ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
 {
-    ssize_t n;
+    ssize_t  n;
 
     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
                    "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
@@ -53,9 +54,10 @@
 }
 
 
-ssize_t ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
+ssize_t
+ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
 {
-    ssize_t n;
+    ssize_t  n;
 
     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
                    "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
@@ -109,7 +111,8 @@
 }
 
 
-ngx_fd_t ngx_open_tempfile(u_char *name, ngx_uint_t persistent)
+ngx_fd_t
+ngx_open_tempfile(u_char *name, ngx_uint_t persistent)
 {
     ngx_fd_t  fd;
 
@@ -125,8 +128,9 @@
 
 #define NGX_IOVS  8
 
-ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl,
-                                off_t offset, ngx_pool_t *pool)
+ssize_t
+ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
+    ngx_pool_t *pool)
 {
     u_char        *prev;
     size_t         size;
@@ -216,7 +220,8 @@
 }
 
 
-ngx_int_t ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
+ngx_int_t
+ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
 {
     dir->dir = opendir((const char *) name->data);
 
@@ -228,3 +233,61 @@
 
     return NGX_OK;
 }
+
+
+ngx_int_t
+ngx_lock_file(ngx_file_t *file)
+{
+    ngx_err_t     err;
+    struct flock  fl;
+
+    fl.l_whence = SEEK_SET;
+    fl.l_len = 0;
+    fl.l_pid = 0;
+    fl.l_type = F_WRLCK;
+    fl.l_start = 0;
+
+    if (fcntl(file->fd, F_SETLK, &fl) == -1) {
+        err = ngx_errno;
+
+        if (err == NGX_EAGAIN) {
+            return NGX_BUSY;
+        }
+
+        ngx_log_error(NGX_LOG_ALERT, file->log, err,
+                      "fcntl(%s, F_SETLK, F_WRLCK) failed", file->name.data);
+
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_unlock_file(ngx_file_t *file)
+{
+    ngx_err_t     err;
+    struct flock  fl;
+
+    fl.l_whence = SEEK_SET;
+    fl.l_len = 0;
+    fl.l_pid = 0;
+    fl.l_type = F_UNLCK;
+    fl.l_start = 0;
+
+    if (fcntl(file->fd, F_SETLK, &fl) == -1) {
+        err = ngx_errno;
+
+        if (err == NGX_EAGAIN) {
+            return NGX_BUSY;
+        }
+
+        ngx_log_error(NGX_LOG_ALERT, file->log, err,
+                      "fcntl(%s, F_SETLK, F_UNLCK) failed", file->name.data);
+
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
diff --git a/src/os/unix/ngx_gcc_atomic_amd64.h b/src/os/unix/ngx_gcc_atomic_amd64.h
new file mode 100644
index 0000000..07b2d50
--- /dev/null
+++ b/src/os/unix/ngx_gcc_atomic_amd64.h
@@ -0,0 +1,74 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#if (NGX_SMP)
+#define NGX_SMP_LOCK  "lock;"
+#else
+#define NGX_SMP_LOCK
+#endif
+
+
+/*
+ * "cmpxchgq  r, [m]":
+ *
+ *     if (rax == [m]) {
+ *         zf = 1;
+ *         [m] = r;
+ *     } else {
+ *         zf = 0;
+ *         rax = [m];
+ *     }
+ *
+ *
+ * The "r" is any register, %rax (%r0) - %r16.
+ * The "=a" and "a" are the %rax register.  Although we can return result
+ * in any register, we use %rax because it is used in cmpxchgq 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
+    "    cmpxchgq  %3, %1;   "
+    "    setz      %b0;      "
+    "    movzbq    %b0, %0;  "
+
+    : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "cc", "memory");
+
+    return res;
+}
+
+
+/*
+ * "xaddq  r, [m]":
+ *
+ *     temp = [m];
+ *     [m] += r;
+ *     r = temp;
+ *
+ *
+ * The "+r" is any register, %rax (%r0) - %r16.
+ * The "cc" means that flags were changed.
+ */
+
+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
+    "    xaddq  %0, %1;   "
+
+    : "+q" (add) : "m" (*value) : "cc", "memory");
+
+    return add;
+}
diff --git a/src/os/unix/ngx_gcc_atomic_ppc.h b/src/os/unix/ngx_gcc_atomic_ppc.h
new file mode 100644
index 0000000..8fc3bc0
--- /dev/null
+++ b/src/os/unix/ngx_gcc_atomic_ppc.h
@@ -0,0 +1,66 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+/*
+ * 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 "1b" means the nearest backward label "1" and the "1f" means
+ * the nearest forward label "1".
+ *  
+ * 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 "=&b" means that no input registers can be used.
+ */
+
+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"
+
+    : "=&b" (res), "=&b" (temp)
+    : "b" (lock), "b" (old), "b" (set)
+    : "cc", "memory");
+
+    return res;
+}
+
+
+static ngx_inline ngx_atomic_int_t
+ngx_atomic_fetch_add(ngx_atomic_t *value, ngx_atomic_int_t add)
+{
+    ngx_atomic_uint_t  res, temp;
+
+    __asm__ volatile (
+
+    "1:  lwarx   %0, 0, %2   \n" /* load from [value] into "res"             */
+                                 /*   and store reservation                  */
+    "    add     %1, %0, %3  \n" /* "res" + "add" store in "temp"            */
+    "    stwcx.  %1, 0, %2   \n" /* store "temp" into [value] if reservation */
+                                 /*   is not cleared                         */
+    "    bne-    1b          \n" /* try again if reservation was cleared     */
+
+    : "=&b" (res), "=&b" (temp)
+    : "b" (value), "b" (add)
+    : "cc", "memory");
+
+    return res;
+}
diff --git a/src/os/unix/ngx_gcc_atomic_sparc64.h b/src/os/unix/ngx_gcc_atomic_sparc64.h
new file mode 100644
index 0000000..c7022a9
--- /dev/null
+++ b/src/os/unix/ngx_gcc_atomic_sparc64.h
@@ -0,0 +1,69 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+/*
+ * "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.
+ *
+ *
+ * The "r" means the general register.
+ * The "+r" means the general register used for both input and output.
+ */
+
+
+#if (NGX_PTR_SIZE == 4)
+#define NGX_CASA  "casa"
+#else
+#define NGX_CASA  "casxa"
+#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)
+{
+    __asm__ volatile (
+
+    NGX_CASA " [%1] 0x80, %2, %0"
+
+    : "+r" (set) : "r" (lock), "r" (old) : "memory");
+
+    return (set == old);
+}   
+
+
+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, res;
+
+    old = *value;
+
+    for ( ;; ) {
+
+        res = old + add;
+
+        __asm__ volatile (
+
+        NGX_CASA " [%1] 0x80, %2, %0"
+
+        : "+r" (res) : "r" (value), "r" (old) : "memory");
+
+        if (res == old) {
+            return res;
+        }
+
+        old = res;
+    }
+}
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 0000000..e3c0c93
--- /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
diff --git a/src/os/unix/ngx_readv_chain.c b/src/os/unix/ngx_readv_chain.c
index 47d8f3b..08b5cc0 100644
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -182,7 +182,7 @@
                 return NGX_ERROR;
             }
 
-            iov->iov_base = chain->buf->last;
+            iov->iov_base = (void *) chain->buf->last;
             iov->iov_len = chain->buf->end - chain->buf->last;
         }
 
diff --git a/src/os/unix/ngx_sunpro_amd64.il b/src/os/unix/ngx_sunpro_amd64.il
new file mode 100644
index 0000000..0cd94b0
--- /dev/null
+++ b/src/os/unix/ngx_sunpro_amd64.il
@@ -0,0 +1,30 @@
+/
+/ Copyright (C) Igor Sysoev
+/
+
+/ ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
+/     ngx_atomic_uint_t old, ngx_atomic_uint_t set);
+/
+/ the arguments are passed in %rdi, %rsi, %rdx
+/ the result is returned in the %rax
+
+        .inline ngx_atomic_cmp_set,0
+        movq      %rsi, %rax
+        lock
+        cmpxchgq  %rdx, (%rdi)
+        setz      %al
+        movzbq    %al, %rax
+        .end
+
+
+/ ngx_atomic_int_t ngx_atomic_fetch_add(ngx_atomic_t *value,
+/     ngx_atomic_int_t add);
+/
+/ the arguments are passed in %rdi, %rsi
+/ the result is returned in the %rax
+
+        .inline ngx_atomic_fetch_add,0
+        movq      %rsi, %rax
+        lock
+        xaddq     %rax, (%rdi)
+        .end
diff --git a/src/os/unix/ngx_sunpro_atomic_sparc64.h b/src/os/unix/ngx_sunpro_atomic_sparc64.h
new file mode 100644
index 0000000..e634416
--- /dev/null
+++ b/src/os/unix/ngx_sunpro_atomic_sparc64.h
@@ -0,0 +1,52 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#if (NGX_PTR_SIZE == 4)
+#define NGX_CASA  ngx_casa
+#else
+#define NGX_CASA  ngx_casxa
+#endif
+
+
+ngx_atomic_uint_t
+ngx_casa(ngx_atomic_uint_t set, ngx_atomic_uint_t old, ngx_atomic_t *lock);
+
+ngx_atomic_uint_t
+ngx_casxa(ngx_atomic_uint_t set, ngx_atomic_uint_t old, ngx_atomic_t *lock);
+
+/* the code in src/os/unix/ngx_sunpro_sparc64.il */
+
+
+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_CASA(set, old, lock);
+
+    return (set == old);
+}   
+
+
+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, res;
+
+    old = *value;
+
+    for ( ;; ) {
+
+        res = old + add;
+
+        NGX_CASA(res, old, value);
+
+        if (res == old) {
+            return res;
+        }
+
+        old = res;
+    }
+}
diff --git a/src/os/unix/ngx_sunpro_sparc64.il b/src/os/unix/ngx_sunpro_sparc64.il
new file mode 100644
index 0000000..d2708ed
--- /dev/null
+++ b/src/os/unix/ngx_sunpro_sparc64.il
@@ -0,0 +1,35 @@
+/
+/ Copyright (C) Igor Sysoev
+/
+
+
+/  "casa   [%o2] 0x80, %o1, %o0"  and
+/  "casxa  [%o2] 0x80, %o1, %o0"  do the following:
+/ 
+/       if ([%o2] == %o1) {
+/           swap(%o0, [%o2]);
+/       } else {
+/           %o0 = [%o2];
+/       }
+
+
+/ ngx_atomic_uint_t ngx_casa(ngx_atomic_uint_t set, ngx_atomic_uint_t old,
+/      ngx_atomic_t *lock);
+/
+/ the arguments are passed in the %o0, %o1, %o2
+/ the result is returned in the %o0
+
+        .inline ngx_casa,0
+        casa    [%o2] 0x80, %o1, %o0
+        .end
+
+
+/ ngx_atomic_uint_t ngx_casxa(ngx_atomic_uint_t set, ngx_atomic_uint_t old,
+/      ngx_atomic_t *lock);
+/
+/ the arguments are passed in the %o0, %o1, %o2
+/ the result is returned in the %o0
+
+        .inline ngx_casxa,0
+        casxa   [%o2] 0x80, %o1, %o0
+        .end
diff --git a/src/os/unix/ngx_sunpro_x86.il b/src/os/unix/ngx_sunpro_x86.il
new file mode 100644
index 0000000..a16568a
--- /dev/null
+++ b/src/os/unix/ngx_sunpro_x86.il
@@ -0,0 +1,31 @@
+/
+/ Copyright (C) Igor Sysoev
+/
+
+/ ngx_atomic_uint_t ngx_atomic_cmp_set(ngx_atomic_t *lock,
+/     ngx_atomic_uint_t old, ngx_atomic_uint_t set);
+/
+/ the arguments are passed on the stack (%esp), 4(%esp), 8(%esp)
+
+        .inline ngx_atomic_cmp_set,0
+        movl      (%esp), %ecx
+        movl      4(%esp), %eax
+        movl      8(%esp), %edx
+        lock
+        cmpxchgl  %edx, (%ecx)
+        setz      %al
+        movzbl    %al, %eax
+        .end
+
+
+/ ngx_atomic_int_t ngx_atomic_fetch_add(ngx_atomic_t *value,
+/     ngx_atomic_int_t add);
+/
+/ the arguments are passed on the stack (%esp), 4(%esp)
+
+        .inline ngx_atomic_fetch_add,0
+        movl      (%esp), %ecx
+        movl      4(%esp), %eax
+        lock
+        xaddl     %eax, (%ecx)
+        .end
diff --git a/src/os/unix/ngx_time.h b/src/os/unix/ngx_time.h
index 63a0ad9..f9fe3c5 100644
--- a/src/os/unix/ngx_time.h
+++ b/src/os/unix/ngx_time.h
@@ -12,31 +12,32 @@
 #include <ngx_core.h>
 
 
-typedef ngx_rbtree_key_t  ngx_msec_t;
+typedef ngx_rbtree_key_t      ngx_msec_t;
+typedef ngx_rbtree_key_int_t  ngx_msec_int_t;
 
-typedef struct tm         ngx_tm_t;
+typedef struct tm             ngx_tm_t;
 
-#define ngx_tm_sec        tm_sec
-#define ngx_tm_min        tm_min
-#define ngx_tm_hour       tm_hour
-#define ngx_tm_mday       tm_mday
-#define ngx_tm_mon        tm_mon
-#define ngx_tm_year       tm_year
-#define ngx_tm_wday       tm_wday
-#define ngx_tm_isdst      tm_isdst
+#define ngx_tm_sec            tm_sec
+#define ngx_tm_min            tm_min
+#define ngx_tm_hour           tm_hour
+#define ngx_tm_mday           tm_mday
+#define ngx_tm_mon            tm_mon
+#define ngx_tm_year           tm_year
+#define ngx_tm_wday           tm_wday
+#define ngx_tm_isdst          tm_isdst
 
-#define ngx_tm_sec_t      int
-#define ngx_tm_min_t      int
-#define ngx_tm_hour_t     int
-#define ngx_tm_mday_t     int
-#define ngx_tm_mon_t      int
-#define ngx_tm_year_t     int
-#define ngx_tm_wday_t     int
+#define ngx_tm_sec_t          int
+#define ngx_tm_min_t          int
+#define ngx_tm_hour_t         int
+#define ngx_tm_mday_t         int
+#define ngx_tm_mon_t          int
+#define ngx_tm_year_t         int
+#define ngx_tm_wday_t         int
 
 
 #if (NGX_HAVE_GMTOFF)
-#define ngx_tm_gmtoff     tm_gmtoff
-#define ngx_tm_zone       tm_zone
+#define ngx_tm_gmtoff         tm_gmtoff
+#define ngx_tm_zone           tm_zone
 #endif
 
 
diff --git a/src/os/unix/ngx_writev_chain.c b/src/os/unix/ngx_writev_chain.c
index 9baeb1f..f95c2ca 100644
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -81,7 +81,7 @@
             size = cl->buf->last - cl->buf->pos;
 
             if (send + size > limit) {
-                size = (ssize_t) limit - send;
+                size = (ssize_t) (limit - send);
             }
 
             if (prev == cl->buf->pos) {