changeset 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 97da525033a1
children a175b609c76d
files CHANGES CHANGES.ru auto/cc/conf auto/cc/gcc auto/cc/icc auto/cc/name auto/cc/sunc auto/lib/openssl/conf auto/lib/pcre/conf auto/make auto/os/solaris auto/sources configure src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_config.h src/core/ngx_connection.c src/core/ngx_cycle.c src/core/ngx_cycle.h src/core/ngx_file.c src/core/ngx_file.h src/core/ngx_inet.c src/core/ngx_string.c src/event/modules/ngx_kqueue_module.c src/event/ngx_event.c src/event/ngx_event_accept.c src/event/ngx_event_connect.c src/event/ngx_event_timer.c src/event/ngx_event_timer.h src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_proxy_module.c src/http/ngx_http.c src/http/ngx_http_request.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_variables.c src/os/unix/ngx_atomic.h src/os/unix/ngx_channel.c src/os/unix/ngx_files.c src/os/unix/ngx_gcc_atomic_amd64.h src/os/unix/ngx_gcc_atomic_ppc.h src/os/unix/ngx_gcc_atomic_sparc64.h src/os/unix/ngx_gcc_atomic_x86.h src/os/unix/ngx_readv_chain.c src/os/unix/ngx_sunpro_amd64.il src/os/unix/ngx_sunpro_atomic_sparc64.h src/os/unix/ngx_sunpro_sparc64.il src/os/unix/ngx_sunpro_x86.il src/os/unix/ngx_time.h src/os/unix/ngx_writev_chain.c
diffstat 50 files changed, 1033 insertions(+), 581 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,12 @@
+
+Changes with nginx 0.3.2                                         12 Oct 2005
+
+    *) 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.
+
 
 Changes with nginx 0.3.1                                         10 Oct 2005
 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,3 +1,12 @@
+
+Изменения в nginx 0.3.2                                           12.10.2005
+
+    *) Добавление: поддержка Sun Studio 10 C compiler.
+
+    *) Добавление: директивы proxy_upstream_max_fails, 
+       proxy_upstream_fail_timeout, fastcgi_upstream_max_fails и 
+       fastcgi_upstream_fail_timeout.
+
 
 Изменения в nginx 0.3.1                                           10.10.2005
 
--- a/auto/cc/conf
+++ b/auto/cc/conf
@@ -44,7 +44,7 @@ else
         gcc)
             # gcc 2.7.2.3, 2.8.1, 2.95.4, egcs-1.1.2
             #     3.0.4, 3.1.1, 3.2.3, 3.3.2, 3.3.3, 3.3.4, 3.4.0, 3.4.2
-            #     4.0.0
+            #     4.0.0, 4.0.1, 4.1.0
 
             . auto/cc/gcc
         ;;
@@ -55,6 +55,12 @@ else
             . auto/cc/icc
         ;;
 
+        sunc)
+            # Sun C 5.7 Patch 117837-04 2005/05/11
+
+            . auto/cc/sunc
+        ;;
+
         ccc)
             # Compaq C V6.5-207
 
--- a/auto/cc/gcc
+++ b/auto/cc/gcc
@@ -33,6 +33,17 @@ if [ $ngx_found = yes ]; then
     PIPE="-pipe"
 fi
 
+
+case "$NGX_PLATFORM" in
+
+    *:sun4u)
+        # "-mcpu=v9" enables the "casxa" assembler instruction
+        CFLAGS="$CFLAGS -mcpu=v9"
+    ;;
+
+esac
+
+
 # optimizations
 
 #NGX_GCC_OPT="-O2"
@@ -49,7 +60,7 @@ case $CPU in
         CPU_OPT="-march=pentium"
     ;;
 
-    pentiumpro)
+    pentiumpro | pentium3)
         # optimize for Pentium Pro, Pentium II and Pentium III
         CPU_OPT="-march=pentiumpro"
     ;;
--- a/auto/cc/icc
+++ b/auto/cc/icc
@@ -94,6 +94,8 @@ CFLAGS="$CFLAGS -wd1418"
 CFLAGS="$CFLAGS -wd1419"
 # explicit conversion of a 64-bit integral type to a smaller integral type
 CFLAGS="$CFLAGS -wd1683"
+# conversion from pointer to same-sized integral type, warning on offsetof()
+CFLAGS="$CFLAGS -wd1684"
 
 case "$NGX_ICC_VER" in
     8.* | 9.*)
--- a/auto/cc/name
+++ b/auto/cc/name
@@ -39,6 +39,11 @@ if `$CC -V 2>&1 | grep '^Intel(R) C' 2>&
     echo " using Intel C++ compiler"
 
 else
+if `$CC -V 2>&1 | grep 'Sun C' 2>&1 >/dev/null`; then
+    NGX_CC_NAME=sunc
+    echo " using Sun C compiler"
+
+else
 if `$CC -V 2>&1 | grep '^Compaq C' 2>&1 >/dev/null`; then
     NGX_CC_NAME=ccc
     echo " using Compaq C compiler"
@@ -54,6 +59,7 @@ else
 
 fi # acc
 fi # ccc
+fi # sunc
 fi # icc
 fi # gcc
 fi # bcc
new file mode 100644
--- /dev/null
+++ b/auto/cc/sunc
@@ -0,0 +1,95 @@
+
+# Copyright (C) Igor Sysoev
+
+
+# Sun C 5.7 Patch 117837-04 2005/05/11
+
+NGX_SUNC_VER=`$CC -V 2>&1 | grep 'Sun C' 2>&1 \
+                         | sed -e 's/^.* Sun C \(.*\)/\1/'`
+
+echo " + Sun C version: $NGX_SUNC_VER"
+
+have=NGX_COMPILER value="\"Sun C $NGX_SUNC_VER\"" . auto/define
+
+
+case "$NGX_PLATFORM" in
+
+    *:i86pc)
+        NGX_AUX=" src/os/unix/ngx_sunpro_x86.il"
+    ;;
+
+    *:sun4u)
+        # "-xarch=v9" enables the "casa" assembler instruction
+        CFLAGS="$CFLAGS -xarch=v9"
+        CORE_LINK="$CORE_LINK -xarch=v9"
+        NGX_AUX=" src/os/unix/ngx_sunpro_sparc64.il"
+    ;;
+
+esac
+
+
+# optimizations
+
+CFLAGS="$CFLAGS -fast"
+
+
+case $CPU in
+    pentium)
+        # optimize for Pentium and Athlon
+        CPU_OPT="-xchip=pentium"
+    ;;
+
+    pentiumpro)
+        # optimize for Pentium Pro, Pentium II
+        CPU_OPT="-xchip=pentium_pro"
+    ;;
+
+    pentium3)
+        # optimize for Pentium III
+        CPU_OPT="-xchip=pentium3"
+        #CPU_OPT="$CPU_OPT -xarch=sse"
+        CPU_OPT="$CPU_OPT -xcache=16/32/4:256/32/4"
+    ;;
+
+    pentium4)
+        # optimize for Pentium 4
+        CPU_OPT="-xchip=pentium4"
+        #CPU_OPT="$CPU_OPT -xarch=sse2"
+        CPU_OPT="$CPU_OPT -xcache=8/64/4:256/128/8"
+    ;;
+
+    opteron)
+        # optimize for Opteron
+        CPU_OPT="-xchip=opteron"
+        #CPU_OPT="$CPU_OPT -xarch=sse2"
+        CPU_OPT="$CPU_OPT -xcache=64/64/2:1024/64/16"
+    ;;
+
+    amd64)
+        # build 64-bit amd64 binary
+        CPU_OPT="-xarch=amd64"
+        CORE_LINK="$CORE_LINK -xarch=amd64"
+        NGX_AUX=" src/os/unix/ngx_sunpro_amd64.il"
+    ;;
+
+esac
+
+
+CFLAGS="$CFLAGS $CPU_OPT"
+
+
+if [ ".$PCRE_OPT" = "." ]; then
+    PCRE_OPT="-fast $CPU_OPT"
+fi
+
+if [ ".$MD5_OPT" = "." ]; then
+    MD5_OPT="-fast $CPU_OPT"
+fi
+
+if [ ".$ZLIB_OPT" = "." ]; then
+    ZLIB_OPT="-fast $CPU_OPT"
+fi
+
+
+# stop on warning
+CFLAGS="$CFLAGS -errwarn=%all"
--- a/auto/lib/openssl/conf
+++ b/auto/lib/openssl/conf
@@ -36,6 +36,12 @@ else
         if [ $ngx_found = yes ]; then
             CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
             OPENSSL=YES
+
+            case "$NGX_SYSTEM" in
+                SunOS)
+                    CORE_LIBS="$CORE_LIBS -ldl"
+                ;;
+            esac
         fi
 
     fi
--- a/auto/lib/pcre/conf
+++ b/auto/lib/pcre/conf
@@ -17,7 +17,7 @@ if [ $PCRE != NONE ]; then
             CORE_LIBS="$CORE_LIBS $PCRE/pcre.lib"
         ;;
 
-        icc*)
+        icc* | sunc )
             have=NGX_PCRE . auto/have
             CORE_DEPS="$CORE_DEPS $PCRE/pcre.h"
 
--- a/auto/make
+++ b/auto/make
@@ -200,7 +200,7 @@ fi
 cat << END                                                    >> $NGX_MAKEFILE
 
 $ngx_modules_obj:	\$(CORE_DEPS)$ngx_cont$ngx_modules_c
-	$ngx_cc$ngx_tab$ngx_objout$ngx_modules_obj$ngx_tab$ngx_modules_c
+	$ngx_cc$ngx_tab$ngx_objout$ngx_modules_obj$ngx_tab$ngx_modules_c$NGX_AUX
 
 END
 
@@ -219,7 +219,7 @@ do
     cat << END                                                >> $NGX_MAKEFILE
 
 $ngx_obj:	\$(CORE_DEPS)$ngx_cont$ngx_src
-	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src
+	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
 
 END
 
@@ -248,7 +248,7 @@ if [ $HTTP = YES ]; then
         cat << END                                            >> $NGX_MAKEFILE
 
 $ngx_obj:	\$(CORE_DEPS) \$(HTTP_DEPS)$ngx_cont$ngx_src
-	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src
+	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
 
 END
      done
@@ -278,7 +278,7 @@ if [ $IMAP = YES ]; then
         cat << END                                            >> $NGX_MAKEFILE
 
 $ngx_obj:	\$(CORE_DEPS) \$(IMAP_DEPS)$ngx_cont$ngx_src
-	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src
+	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
 
 END
      done
@@ -310,7 +310,7 @@ if test -n "$NGX_ADDON_SRCS"; then
         cat << END                                            >> $NGX_MAKEFILE
 
 $ngx_obj:	\$(ADDON_DEPS)$ngx_cont$ngx_src
-	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src
+	$ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src$NGX_AUX
 
 END
      done
--- a/auto/os/solaris
+++ b/auto/os/solaris
@@ -12,17 +12,7 @@ CORE_LIBS="$CORE_LIBS -lsocket -lnsl -lr
 # Solaris's make does not support a blank line between target and rules
 ngx_spacer=
 
-CC_AUX_FLAGS="$CC_AUX_FLAGS -D_FILE_OFFSET_BITS=64 -lrt"
-
-
-case "$NGX_PLATFORM" in
-
-    *:sun4u)
-        # "-mcpu=v9" enables the "casa" assembler instruction
-        CFLAGS="$CFLAGS -mcpu=v9"
-    ;;
-
-esac
+CC_AUX_FLAGS="$CC_AUX_FLAGS -D_FILE_OFFSET_BITS=64 -lsocket -lnsl -lrt"
 
 
 if [ $ZLIB_ASM != NO ]; then
--- a/auto/sources
+++ b/auto/sources
@@ -123,12 +123,23 @@ UNIX_DEPS="$CORE_DEPS $EVENT_DEPS \
             src/os/unix/ngx_process.h \
             src/os/unix/ngx_setproctitle.h \
             src/os/unix/ngx_atomic.h \
+            src/os/unix/ngx_gcc_atomic_x86.h \
             src/os/unix/ngx_thread.h \
             src/os/unix/ngx_socket.h \
             src/os/unix/ngx_os.h \
             src/os/unix/ngx_user.h \
             src/os/unix/ngx_process_cycle.h"
 
+# add to UNIX_DEPS
+#            src/os/unix/ngx_gcc_atomic_amd64.h \
+#            src/os/unix/ngx_gcc_atomic_sparc64.h \
+#            src/os/unix/ngx_gcc_atomic_ppc.h \
+#            src/os/unix/ngx_sunpro_atomic_sparc64.h \
+#            src/os/unix/ngx_sunpro_x86.il \
+#            src/os/unix/ngx_sunpro_amd64.il \
+#            src/os/unix/ngx_sunpro_sparc64.il \
+
+
 UNIX_SRCS="$CORE_SRCS $EVENT_SRCS \
             src/core/ngx_unix_domain.c \
             src/os/unix/ngx_time.c \
--- a/configure
+++ b/configure
@@ -23,8 +23,8 @@ if [ "$NGX_PLATFORM" != win32 ]; then
     . auto/headers
 fi
 
+. auto/os/conf
 . auto/cc/conf
-. auto/os/conf
 
 if [ "$NGX_PLATFORM" != win32 ]; then
     . auto/os/features
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.3.1"
+#define NGINX_VER          "nginx/0.3.2"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_OLDPID_EXT     ".oldbin"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -660,7 +660,7 @@ ngx_conf_full_name(ngx_cycle_t *cycle, n
 
     name->len = cycle->root.len + old.len;
 
-    if (cycle->connections0) {
+    if (cycle->connections) {
         name->data = ngx_palloc(cycle->pool, name->len + 1);
         if (name->data == NULL) {
             return  NGX_ERROR;
--- a/src/core/ngx_config.h
+++ b/src/core/ngx_config.h
@@ -106,7 +106,7 @@ typedef long               ngx_flag_t;
 
 /* TODO: auto_conf: ngx_inline   inline __inline __inline__ */
 #ifndef ngx_inline
-#define ngx_inline   __inline
+#define ngx_inline   inline
 #endif
 
 #define NGX_ACCEPT_THRESHOLD   100
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -372,7 +372,9 @@ ngx_close_listening_sockets(ngx_cycle_t 
 ngx_connection_t *
 ngx_get_connection(ngx_socket_t s, ngx_log_t *log)
 {
-    ngx_connection_t *c;
+    ngx_uint_t         instance;
+    ngx_event_t       *rev, *wev;
+    ngx_connection_t  *c;
 
     /* disable warning: Win32 SOCKET is u_int while UNIX socket is int */
 
@@ -407,6 +409,32 @@ ngx_get_connection(ngx_socket_t s, ngx_l
         ngx_cycle->files[s] = c;
     }
 
+    rev = c->read;
+    wev = c->write;
+
+    ngx_memzero(c, sizeof(ngx_connection_t));
+
+    c->read = rev;
+    c->write = wev;
+    c->fd = s;
+    c->log = log;
+
+    instance = rev->instance;
+
+    ngx_memzero(rev, sizeof(ngx_event_t));
+    ngx_memzero(wev, sizeof(ngx_event_t));
+
+    rev->instance = !instance;
+    wev->instance = !instance;
+
+    rev->index = NGX_INVALID_INDEX;
+    wev->index = NGX_INVALID_INDEX;
+
+    rev->data = c;
+    wev->data = c;
+
+    wev->write = 1;
+
     return c;
 }
 
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -627,7 +627,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
         }
     }
 
-    if (old_cycle->connections0 == NULL) {
+    if (old_cycle->connections == NULL) {
         /* an old cycle is an init cycle */
         ngx_destroy_pool(old_cycle->pool);
         return cycle;
@@ -959,7 +959,7 @@ static void ngx_clean_old_cycles(ngx_eve
         found = 0;
 
         for (n = 0; n < cycle[i]->connection_n; n++) {
-            if (cycle[i]->connections0[n].fd != (ngx_socket_t) -1) {
+            if (cycle[i]->connections[n].fd != (ngx_socket_t) -1) {
                 found = 1;
 
                 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "live fd:%d", n);
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -39,9 +39,9 @@ struct ngx_cycle_s {
     ngx_uint_t                connection_n;
     ngx_uint_t                files_n;
 
-    ngx_connection_t         *connections0;
-    ngx_event_t              *read_events0;
-    ngx_event_t              *write_events0;
+    ngx_connection_t         *connections;
+    ngx_event_t              *read_events;
+    ngx_event_t              *write_events;
 
     ngx_cycle_t              *old_cycle;
 
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -36,7 +36,7 @@ ngx_write_chain_to_temp_file(ngx_temp_fi
 
 ngx_int_t
 ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool,
-    int persistent)
+    ngx_uint_t persistent)
 {
     ngx_err_t                 err;
     ngx_atomic_uint_t         n;
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -55,7 +55,7 @@ typedef struct {
 
 ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain);
 ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path,
-    ngx_pool_t *pool, int persistent);
+    ngx_pool_t *pool, ngx_uint_t persistent);
 void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path);
 ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
 ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -343,10 +343,6 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, 
             peers->peer[i].name.len = len + u->port_text.len;
 
             peers->peer[i].uri_separator = "";
-
-            peers->peer[i].weight = 1;
-            peers->peer[i].max_fails = 1;
-            peers->peer[i].fail_timeout = 10;
         }
 
     } else {
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -115,6 +115,7 @@ ngx_vsnprintf(u_char *buf, size_t max, c
     uint32_t        ui32;
     int64_t         i64;
     uint64_t        ui64;
+    ngx_msec_t      ms;
     ngx_str_t      *s;
     ngx_uint_t      width, sign, hexadecimal, max_width;
     static u_char   hex[] = "0123456789abcdef";
@@ -221,8 +222,14 @@ ngx_vsnprintf(u_char *buf, size_t max, c
                 break;
 
             case 'M':
-                ui64 = (uint64_t) va_arg(args, ngx_msec_t);
-                sign = 0;
+                ms = (ngx_msec_t) va_arg(args, ngx_msec_t);
+                if ((ngx_msec_int_t) ms == -1) {
+                    sign = 1;
+                    i64 = -1;
+                } else {
+                    sign = 0;
+                    ui64 = (uint64_t) ms;
+                }
                 break;
 
             case 'z':
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -511,7 +511,7 @@ ngx_kqueue_process_events(ngx_cycle_t *c
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
-                   "kevent timer: %d, changes: %d", timer, n);
+                   "kevent timer: %M, changes: %d", timer, n);
 
     events = kevent(ngx_kqueue, change_list, n, event_list, nevents, tp);
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -40,7 +40,7 @@ ngx_uint_t            ngx_event_flags;
 ngx_event_actions_t   ngx_event_actions;
 
 
-ngx_atomic_t          connection_counter;
+ngx_atomic_t          connection_counter = 1;
 ngx_atomic_t         *ngx_connection_counter = &connection_counter;
 
 
@@ -49,6 +49,7 @@ ngx_atomic_t         *ngx_accept_mutex;
 ngx_uint_t            ngx_accept_mutex_held;
 ngx_msec_t            ngx_accept_mutex_delay;
 ngx_int_t             ngx_accept_disabled;
+ngx_file_t            ngx_accept_mutex_lock_file;
 
 
 #if (NGX_STAT_STUB)
@@ -349,7 +350,7 @@ ngx_event_module_init(ngx_cycle_t *cycle
 
     ecf = (*cf)[ngx_event_core_module.ctx_index];
 
-    ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
+    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
                   "using the \"%s\" event method", ecf->name);
 
 #if !(NGX_WIN32)
@@ -501,21 +502,21 @@ ngx_event_process_init(ngx_cycle_t *cycl
 
 #endif
 
-    cycle->connections0 = ngx_alloc(sizeof(ngx_connection_t) * ecf->connections,
+    cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * ecf->connections,
                                    cycle->log);
-    if (cycle->connections0 == NULL) {
+    if (cycle->connections == NULL) {
         return NGX_ERROR;
     }
 
-    c = cycle->connections0;
+    c = cycle->connections;
 
-    cycle->read_events0 = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
+    cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
                                    cycle->log);
-    if (cycle->read_events0 == NULL) {
+    if (cycle->read_events == NULL) {
         return NGX_ERROR;
     }
 
-    rev = cycle->read_events0;
+    rev = cycle->read_events;
     for (i = 0; i < cycle->connection_n; i++) {
         rev[i].closed = 1;
         rev[i].instance = 1;
@@ -525,13 +526,13 @@ ngx_event_process_init(ngx_cycle_t *cycl
 #endif
     }
 
-    cycle->write_events0 = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
+    cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
                                     cycle->log);
-    if (cycle->write_events0 == NULL) {
+    if (cycle->write_events == NULL) {
         return NGX_ERROR;
     }
 
-    wev = cycle->write_events0;
+    wev = cycle->write_events;
     for (i = 0; i < cycle->connection_n; i++) {
         wev[i].closed = 1;
 #if (NGX_THREADS)
@@ -547,8 +548,8 @@ ngx_event_process_init(ngx_cycle_t *cycl
         i--;
 
         c[i].data = next;
-        c[i].read = &cycle->read_events0[i];
-        c[i].write = &cycle->write_events0[i];
+        c[i].read = &cycle->read_events[i];
+        c[i].write = &cycle->write_events[i];
         c[i].fd = (ngx_socket_t) -1;
 
         next = &c[i];
@@ -572,14 +573,6 @@ ngx_event_process_init(ngx_cycle_t *cycl
             return NGX_ERROR;
         }
 
-        rev = c->read;
-        wev = c->write;
-
-        ngx_memzero(c, sizeof(ngx_connection_t));
-
-        c->read = rev;
-        c->write = wev;
-        c->fd = ls[i].fd;
         c->log = &ls[i].log;
 
         c->listening = &ls[i];
@@ -588,18 +581,9 @@ ngx_event_process_init(ngx_cycle_t *cycl
         c->ctx = ls[i].ctx;
         c->servers = ls[i].servers;
 
-        ngx_memzero(rev, sizeof(ngx_event_t));
-        ngx_memzero(wev, sizeof(ngx_event_t));
-
-        /* required by poll */
-        wev->index = NGX_INVALID_INDEX;
+        rev = c->read;
 
         rev->log = c->log;
-        rev->data = c;
-        rev->index = NGX_INVALID_INDEX;
-
-        rev->available = 0;
-
         rev->accept = 1;
 
 #if (NGX_HAVE_DEFERRED_ACCEPT)
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -22,7 +22,6 @@ ngx_event_accept(ngx_event_t *ev)
     socklen_t          sl;
     ngx_err_t          err;
     ngx_log_t         *log;
-    ngx_uint_t         instance;
     ngx_socket_t       s;
     ngx_event_t       *rev, *wev;
     ngx_listening_t   *ls;
@@ -76,8 +75,8 @@ ngx_event_accept(ngx_event_t *ev)
         }
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_inc(ngx_stat_accepted);
-        ngx_atomic_inc(ngx_stat_active);
+        ngx_atomic_fetch_add(ngx_stat_accepted, 1);
+        ngx_atomic_fetch_add(ngx_stat_active, 1);
 #endif
 
         ngx_accept_disabled = NGX_ACCEPT_THRESHOLD
@@ -94,16 +93,6 @@ ngx_event_accept(ngx_event_t *ev)
             return;
         }
 
-        rev = c->read;
-        wev = c->write;
-
-        ngx_memzero(c, sizeof(ngx_connection_t));
-
-        c->read = rev;
-        c->write = wev;
-        c->fd = s;
-        c->log = ev->log;
-
         c->pool = ngx_create_pool(ls->pool_size, ev->log);
         if (c->pool == NULL) {
             ngx_close_accepted_connection(c);
@@ -164,21 +153,9 @@ ngx_event_accept(ngx_event_t *ev)
         c->ctx = lc->ctx;
         c->servers = lc->servers;
 
-        instance = rev->instance;
-
-        ngx_memzero(rev, sizeof(ngx_event_t));
-        ngx_memzero(wev, sizeof(ngx_event_t));
-
-        rev->instance = !instance;
-        wev->instance = !instance;
+        rev = c->read;
+        wev = c->write;
 
-        rev->index = NGX_INVALID_INDEX;
-        wev->index = NGX_INVALID_INDEX;
-
-        rev->data = c;
-        wev->data = c;
-
-        wev->write = 1;
         wev->ready = 1;
 
         if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
@@ -197,18 +174,18 @@ ngx_event_accept(ngx_event_t *ev)
         wev->log = log;
 
         /*
-         * TODO: MT: - atomic increment (x86: lock xadd)
+         * TODO: MT: - ngx_atomic_fetch_add()
          *             or protection by critical section or light mutex
          *
          * TODO: MP: - allocated in a shared memory
-         *           - atomic increment (x86: lock xadd)
+         *           - ngx_atomic_fetch_add()
          *             or protection by critical section or light mutex
          */
 
-        c->number = ngx_atomic_inc(ngx_connection_counter);
+        c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_inc(ngx_stat_handled);
+        ngx_atomic_fetch_add(ngx_stat_handled, 1);
 #endif
 
 #if (NGX_THREADS)
@@ -391,7 +368,7 @@ ngx_close_accepted_connection(ngx_connec
     }
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_dec(ngx_stat_active);
+    ngx_atomic_fetch_add(ngx_stat_active, -1);
 #endif
 }
 
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -14,7 +14,7 @@ ngx_int_t
 ngx_event_connect_peer(ngx_peer_connection_t *pc)
 {
     int                rc;
-    ngx_uint_t         instance, level, i;
+    ngx_uint_t         level, i;
     u_int              event;
     time_t             now;
     ngx_err_t          err;
@@ -81,7 +81,7 @@ ngx_event_connect_peer(ngx_peer_connecti
         for ( ;; ) {
             peer = &pc->peers->peer[pc->cur_peer];
 
-            if (peer->fails <= peer->max_fails) {
+            if (peer->max_fails == 0 || peer->fails <= peer->max_fails) {
                 break;
             }
 
@@ -139,16 +139,6 @@ ngx_event_connect_peer(ngx_peer_connecti
         return NGX_ERROR;
     }
 
-    rev = c->read;
-    wev = c->write;
-
-    ngx_memzero(c, sizeof(ngx_connection_t));
-
-    c->read = rev;
-    c->write = wev;
-    c->fd = s;
-    c->log = pc->log;
-
     if (pc->rcvbuf) {
         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
                        (const void *) &pc->rcvbuf, sizeof(int)) == -1) {
@@ -191,21 +181,8 @@ ngx_event_connect_peer(ngx_peer_connecti
         c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
     }
 
-    instance = rev->instance;
-
-    ngx_memzero(rev, sizeof(ngx_event_t));
-    ngx_memzero(wev, sizeof(ngx_event_t));
-
-    rev->instance = !instance;
-    wev->instance = !instance;
-
-    rev->index = NGX_INVALID_INDEX;
-    wev->index = NGX_INVALID_INDEX;
-
-    rev->data = c;
-    wev->data = c;
-
-    wev->write = 1;
+    rev = c->read;
+    wev = c->write;
 
     rev->log = pc->log;
     wev->log = pc->log;
@@ -213,15 +190,15 @@ ngx_event_connect_peer(ngx_peer_connecti
     pc->connection = c;
 
     /*
-     * TODO: MT: - atomic increment (x86: lock xadd)
+     * TODO: MT: - ngx_atomic_fetch_add()
      *             or protection by critical section or mutex
      *
      * TODO: MP: - allocated in a shared memory
-     *           - atomic increment (x86: lock xadd)
+     *           - ngx_atomic_fetch_add()
      *             or protection by critical section or mutex
      */
 
-    c->number = ngx_atomic_inc(ngx_connection_counter);
+    c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
 
 #if (NGX_THREADS)
     rev->lock = pc->lock;
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -45,8 +45,8 @@ ngx_event_timer_init(ngx_log_t *log)
 ngx_msec_t
 ngx_event_find_timer(void)
 {
-    ngx_rbtree_key_int_t   timer;
-    ngx_rbtree_node_t     *node, *root, *sentinel;
+    ngx_msec_int_t      timer;
+    ngx_rbtree_node_t  *node, *root, *sentinel;
 
     if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {
         return NGX_TIMER_INFINITE;
@@ -63,8 +63,7 @@ ngx_event_find_timer(void)
 
     ngx_mutex_unlock(ngx_event_timer_mutex);
 
-    timer = (ngx_rbtree_key_int_t) node->key
-                                     - (ngx_rbtree_key_int_t) ngx_current_time;
+    timer = (ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_time;
 
     return (ngx_msec_t) (timer > 0 ? timer : 0);
 }
@@ -94,9 +93,7 @@ ngx_event_expire_timers(void)
 
         /* node->key <= ngx_current_time */
 
-        if ((ngx_rbtree_key_int_t) node->key
-                                      - (ngx_rbtree_key_int_t) ngx_current_time
-            <= 0)
+        if ((ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_time <= 0)
         {
             ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer));
 
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -60,8 +60,8 @@ ngx_event_del_timer(ngx_event_t *ev)
 static ngx_inline void
 ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer)
 {
-    ngx_rbtree_key_t      key;
-    ngx_rbtree_key_int_t  diff;
+    ngx_msec_t      key;
+    ngx_msec_int_t  diff;
 
     key = ngx_current_time + timer;
 
@@ -73,7 +73,7 @@ ngx_event_add_timer(ngx_event_t *ev, ngx
          * the rbtree operations for the fast connections.
          */
 
-        diff = (ngx_rbtree_key_int_t) (key - ev->timer.key);
+        diff = (ngx_msec_int_t) (key - ev->timer.key);
 
         if (ngx_abs(diff) < NGX_TIMER_LAZY_DELAY) {
             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -151,10 +151,6 @@ static ngx_str_t  ngx_http_fastcgi_scrip
 static ngx_conf_post_t  ngx_http_fastcgi_lowat_post =
     { ngx_http_fastcgi_lowat_check };
 
-static ngx_conf_enum_t  ngx_http_fastcgi_set_methods[] = {
-    { ngx_string("get"), NGX_HTTP_GET },
-    { ngx_null_string, 0 }
-};
 
 static ngx_conf_bitmask_t  ngx_http_fastcgi_next_upstream_masks[] = {
     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
@@ -210,13 +206,6 @@ static ngx_command_t  ngx_http_fastcgi_c
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.header_buffer_size),
       NULL },
 
-    { ngx_string("fastcgi_method"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_enum_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.method),
-      ngx_http_fastcgi_set_methods },
-
     { ngx_string("fastcgi_pass_request_headers"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -294,6 +283,20 @@ static ngx_command_t  ngx_http_fastcgi_c
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
       &ngx_http_fastcgi_next_upstream_masks },
 
+    { ngx_string("fastcgi_upstream_max_fails"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_fails),
+      NULL },
+
+    { ngx_string("fastcgi_upstream_fail_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_sec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.fail_timeout),
+      NULL },
+
     { ngx_string("fastcgi_param"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
       ngx_conf_set_table_elt_slot,
@@ -1443,7 +1446,9 @@ ngx_http_fastcgi_create_loc_conf(ngx_con
     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; 
     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
 
-    conf->upstream.method = NGX_CONF_UNSET_UINT;
+    conf->upstream.max_fails = NGX_CONF_UNSET_UINT;
+    conf->upstream.fail_timeout = NGX_CONF_UNSET;
+
     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
     conf->upstream.pass_request_body = NGX_CONF_UNSET;
 
@@ -1591,15 +1596,25 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
                                |NGX_HTTP_UPSTREAM_FT_ERROR
                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
 
+    ngx_conf_merge_unsigned_value(conf->upstream.max_fails,
+                              prev->upstream.max_fails, 1);
+
+    ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
+                              prev->upstream.fail_timeout, 10);
+
+    if (conf->peers && conf->peers->number > 1) {
+        for (i = 0; i < conf->peers->number; i++) {
+            conf->peers->peer[i].weight = 1;
+            conf->peers->peer[i].max_fails = conf->upstream.max_fails;
+            conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+        }
+    }
+
     ngx_conf_merge_path_value(conf->upstream.temp_path,
                               prev->upstream.temp_path,
                               NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0,
                               ngx_garbage_collector_temp_handler, cf);
 
-    if (conf->upstream.method == NGX_CONF_UNSET_UINT) {
-        conf->upstream.method = prev->upstream.method; 
-    }
-
     ngx_conf_merge_value(conf->upstream.pass_request_headers,
                               prev->upstream.pass_request_headers, 1);
     ngx_conf_merge_value(conf->upstream.pass_request_body,
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -46,6 +46,7 @@ typedef struct {
 
     ngx_array_t                 *redirects;
 
+    ngx_str_t                    method;
     ngx_str_t                    host_header;
     ngx_str_t                    port_text;
 
@@ -100,10 +101,6 @@ static char *ngx_http_proxy_lowat_check(
 static ngx_conf_post_t  ngx_http_proxy_lowat_post =
     { ngx_http_proxy_lowat_check };
 
-static ngx_conf_enum_t  ngx_http_proxy_set_methods[] = {
-    { ngx_string("get"), NGX_HTTP_GET },
-    { ngx_null_string, 0 }
-};
 
 static ngx_conf_bitmask_t  ngx_http_proxy_next_upstream_masks[] = {
     { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
@@ -168,10 +165,10 @@ static ngx_command_t  ngx_http_proxy_com
 
     { ngx_string("proxy_method"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_enum_slot,
+      ngx_conf_set_str_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_proxy_loc_conf_t, upstream.method),
-      ngx_http_proxy_set_methods },
+      offsetof(ngx_http_proxy_loc_conf_t, method),
+      NULL },
 
     { ngx_string("proxy_pass_request_headers"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
@@ -243,6 +240,20 @@ static ngx_command_t  ngx_http_proxy_com
       offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
       &ngx_http_proxy_next_upstream_masks },
 
+    { ngx_string("proxy_upstream_max_fails"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.max_fails),
+      NULL },
+
+    { ngx_string("proxy_upstream_fail_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_sec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.fail_timeout),
+      NULL },
+
     { ngx_string("proxy_pass_x_powered_by"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -299,13 +310,6 @@ ngx_module_t  ngx_http_proxy_module = {
 };
 
 
-static ngx_str_t ngx_http_proxy_methods[] = {
-    ngx_string("GET "),
-    ngx_string("HEAD "),
-    ngx_string("POST ")
-};
-
-
 static char  ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
 
 
@@ -394,7 +398,7 @@ ngx_http_proxy_create_request(ngx_http_r
     ngx_uint_t                    i, key;
     uintptr_t                     escape;
     ngx_buf_t                    *b;
-    ngx_str_t                    *hh;
+    ngx_str_t                    *hh, method;
     ngx_chain_t                  *cl, *body;
     ngx_list_part_t              *part;
     ngx_table_elt_t              *header;
@@ -410,12 +414,21 @@ ngx_http_proxy_create_request(ngx_http_r
 
     len = sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
 
-    if (u->method) {
-        len += ngx_http_proxy_methods[u->method - 1].len + u->conf->uri.len;
+    if (u->method.len) {
+        /* HEAD was changed to GET to cache response */
+        method = u->method;
+        method.len++;
+
+    } else if (plcf->method.len) {
+        method = plcf->method;
+
     } else {
-        len += r->method_name.len + 1 + u->conf->uri.len;
+        method = r->method_name;
+        method.len++;
     }
 
+    len += method.len + u->conf->uri.len;
+
     escape = 0;
 
     loc_len = r->valid_location ? u->conf->location->len : 0;
@@ -493,14 +506,7 @@ ngx_http_proxy_create_request(ngx_http_r
 
     /* the request line */
 
-    if (u->method) {
-        b->last = ngx_cpymem(b->last,
-                             ngx_http_proxy_methods[u->method - 1].data,
-                             ngx_http_proxy_methods[u->method - 1].len);
-    } else {
-        b->last = ngx_cpymem(b->last, r->method_name.data,
-                             r->method_name.len + 1);
-    }
+    b->last = ngx_cpymem(b->last, method.data, method.len);
 
     u->uri.data = b->last;
 
@@ -1288,6 +1294,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
      *     conf->upstream.uri = { 0, NULL };
      *     conf->upstream.location = NULL;
      *
+     *     conf->method = NULL;
      *     conf->headers_source = NULL;
      *     conf->headers_set_len = NULL;
      *     conf->headers_set = NULL;
@@ -1306,10 +1313,12 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
     conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;  
     conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
 
-    conf->upstream.method = NGX_CONF_UNSET_UINT;
+    conf->upstream.max_fails = NGX_CONF_UNSET_UINT;
+    conf->upstream.fail_timeout = NGX_CONF_UNSET;
+
     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
     conf->upstream.pass_request_body = NGX_CONF_UNSET;
-    
+
     conf->upstream.redirect_errors = NGX_CONF_UNSET;
 
     /* "proxy_cyclic_temp_file" is disabled */
@@ -1440,10 +1449,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
         && conf->upstream.max_temp_file_size < size)
     {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-             "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
+             "\"proxy_max_temp_file_size\" must be equal to zero to disable "
              "the temporary files usage or must be equal or bigger than "
-             "maximum of the value of \"fastcgi_header_buffer_size\" and "
-             "one of the \"fastcgi_buffers\"");
+             "maximum of the value of \"proxy_header_buffer_size\" and "
+             "one of the \"proxy_buffers\"");
 
         return NGX_CONF_ERROR;
     }
@@ -1455,13 +1464,31 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
                                |NGX_HTTP_UPSTREAM_FT_ERROR
                                |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
 
+    ngx_conf_merge_unsigned_value(conf->upstream.max_fails,
+                              prev->upstream.max_fails, 1);
+
+    ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
+                              prev->upstream.fail_timeout, 10);
+
+    if (conf->peers && conf->peers->number > 1) {
+        for (i = 0; i < conf->peers->number; i++) {
+            conf->peers->peer[i].weight = 1;
+            conf->peers->peer[i].max_fails = conf->upstream.max_fails;
+            conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+        }
+    }
+
     ngx_conf_merge_path_value(conf->upstream.temp_path,
                               prev->upstream.temp_path,
                               NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
                               ngx_garbage_collector_temp_handler, cf);
 
-    if (conf->upstream.method == NGX_CONF_UNSET_UINT) {
-        conf->upstream.method = prev->upstream.method;
+    if (conf->method.len == 0) {
+        conf->method = prev->method;
+
+    } else {
+        conf->method.data[conf->method.len] = ' ';
+        conf->method.len++;
     }
 
     ngx_conf_merge_value(conf->upstream.pass_request_headers,
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -721,10 +721,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
         }
     }
 
-#if (NGX_DEBUG)
+#if (NGX_DEBUG0)
     {
     u_char      address[20];
-    ngx_uint_t  p, a, n;
+    ngx_uint_t  p, a, nn;
 
     in_port = in_ports.elts;
     for (p = 0; p < in_ports.nelts; p++) {
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -174,13 +174,13 @@ ngx_http_init_connection(ngx_connection_
             ngx_mutex_unlock(ngx_posted_events_mutex);
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_inc(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
             return;
         }
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_inc(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
 
         ngx_http_init_request(rev);
@@ -195,7 +195,7 @@ ngx_http_init_connection(ngx_connection_
     }
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_inc(ngx_stat_reading);
+    ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
 
 }
@@ -226,7 +226,7 @@ void ngx_http_init_request(ngx_event_t *
         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_dec(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
         ngx_http_close_connection(c);
@@ -238,7 +238,7 @@ void ngx_http_init_request(ngx_event_t *
     if (hc) {
 
 #if (NGX_STAT_STUB)
-        ngx_atomic_inc(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, 1);
 #endif
 
     } else {
@@ -246,7 +246,7 @@ void ngx_http_init_request(ngx_event_t *
         if (hc == NULL) {
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_dec(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
             ngx_http_close_connection(c);
@@ -270,7 +270,7 @@ void ngx_http_init_request(ngx_event_t *
         if (r == NULL) {
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_dec(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
             ngx_http_close_connection(c);
@@ -281,7 +281,7 @@ void ngx_http_init_request(ngx_event_t *
     }
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_dec(ngx_stat_reading);
+    ngx_atomic_fetch_add(ngx_stat_reading, -1);
 #endif
 
     c->data = r;
@@ -439,9 +439,9 @@ void ngx_http_init_request(ngx_event_t *
     r->log_handler = ngx_http_log_error_handler;
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_inc(ngx_stat_reading);
+    ngx_atomic_fetch_add(ngx_stat_reading, 1);
     r->stat_reading = 1;
-    ngx_atomic_inc(ngx_stat_requests);
+    ngx_atomic_fetch_add(ngx_stat_requests, 1);
 #endif
 
     rev->handler(rev);
@@ -669,9 +669,9 @@ ngx_http_process_request_line(ngx_event_
                 }
 
 #if (NGX_STAT_STUB)
-                ngx_atomic_dec(ngx_stat_reading);
+                ngx_atomic_fetch_add(ngx_stat_reading, -1);
                 r->stat_reading = 0;
-                ngx_atomic_inc(ngx_stat_writing);
+                ngx_atomic_fetch_add(ngx_stat_writing, 1);
                 r->stat_writing = 1;
 #endif
 
@@ -899,9 +899,9 @@ ngx_http_process_request_headers(ngx_eve
             }
 
 #if (NGX_STAT_STUB)
-            ngx_atomic_dec(ngx_stat_reading);
+            ngx_atomic_fetch_add(ngx_stat_reading, -1);
             r->stat_reading = 0;
-            ngx_atomic_inc(ngx_stat_writing);
+            ngx_atomic_fetch_add(ngx_stat_writing, 1);
             r->stat_writing = 1;
 #endif
 
@@ -2396,11 +2396,11 @@ ngx_http_close_request(ngx_http_request_
 
 #if (NGX_STAT_STUB)
     if (r->stat_reading) {
-        ngx_atomic_dec(ngx_stat_reading);
+        ngx_atomic_fetch_add(ngx_stat_reading, -1);
     }
 
     if (r->stat_writing) {
-        ngx_atomic_dec(ngx_stat_writing);
+        ngx_atomic_fetch_add(ngx_stat_writing, -1);
     }
 #endif
 
@@ -2457,7 +2457,7 @@ ngx_http_close_connection(ngx_connection
 #endif
 
 #if (NGX_STAT_STUB)
-    ngx_atomic_dec(ngx_stat_active);
+    ngx_atomic_fetch_add(ngx_stat_active, -1);
 #endif
 
     pool = c->pool;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -251,13 +251,6 @@ ngx_http_upstream_init(ngx_http_request_
         u->request_bufs = r->request_body->bufs;
     }
 
-    if (u->conf->method == NGX_CONF_UNSET_UINT) {
-        u->method = r->method;
-
-    } else {
-        u->method = u->conf->method;
-    }
-
     if (u->create_request(r) != NGX_OK) {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -62,7 +62,9 @@ typedef struct {
     size_t                          temp_file_write_size_conf;
 
     ngx_uint_t                      next_upstream;
-    ngx_uint_t                      method;
+    ngx_uint_t                      max_fails;
+
+    time_t                          fail_timeout;
 
     ngx_bufs_t                      bufs;
 
@@ -156,7 +158,7 @@ struct ngx_http_upstream_s {
 
     ngx_msec_t                      timeout;
 
-    ngx_uint_t                      method;
+    ngx_str_t                       method;
 
     ngx_http_log_handler_pt         saved_log_handler;
 
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -33,6 +33,8 @@ static ngx_http_variable_value_t *
 static ngx_http_variable_value_t *
     ngx_http_variable_request_filename(ngx_http_request_t *r, uintptr_t data);
 static ngx_http_variable_value_t *
+    ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data);
+static ngx_http_variable_value_t *
     ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data);
 
 
@@ -107,8 +109,7 @@ static ngx_http_variable_t  ngx_http_cor
     { ngx_string("server_name"), ngx_http_variable_request,
       offsetof(ngx_http_request_t, server_name), 0, 0 },
 
-    { ngx_string("request_method"), ngx_http_variable_request,
-      offsetof(ngx_http_request_t, method_name), 0, 0 },
+    { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 },
 
     { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 },
 
@@ -641,6 +642,33 @@ ngx_http_variable_request_filename(ngx_h
 
 
 static ngx_http_variable_value_t *
+ngx_http_variable_request_method(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_http_variable_value_t  *vv;
+
+    if (r->method_name.data == NULL) {
+        return NGX_HTTP_VAR_NOT_FOUND;
+    }
+
+    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (vv == NULL) {
+        return NULL;
+    }
+
+    vv->value = 0;
+
+    if (r->upstream && r->upstream->method.len) {
+        vv->text = r->upstream->method;
+
+    } else {
+        vv->text = r->method_name;
+    }
+
+    return vv;
+}
+
+
+static ngx_http_variable_value_t *
 ngx_http_variable_remote_user(ngx_http_request_t *r, uintptr_t data)
 {
     ngx_int_t                   rc;
--- 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
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -192,30 +192,14 @@ ngx_add_channel_event(ngx_cycle_t *cycle
         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;
--- 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_read_file(ngx_file_t *file, 
 }
 
 
-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 @@ ssize_t ngx_write_file(ngx_file_t *file,
 }
 
 
-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 @@ ngx_fd_t ngx_open_tempfile(u_char *name,
 
 #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 @@ ssize_t ngx_write_chain_to_file(ngx_file
 }
 
 
-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 @@ ngx_int_t ngx_open_dir(ngx_str_t *name, 
 
     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;
+}
new file mode 100644
--- /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;
+}
new file mode 100644
--- /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;
+}
new file mode 100644
--- /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;
+    }
+}
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
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -182,7 +182,7 @@ ngx_readv_chain(ngx_connection_t *c, ngx
                 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;
         }
 
new file mode 100644
--- /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
new file mode 100644
--- /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;
+    }
+}
new file mode 100644
--- /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
new file mode 100644
--- /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
--- 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
 
 
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -81,7 +81,7 @@ ngx_writev_chain(ngx_connection_t *c, ng
             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) {