Author: rjung Date: Sun Jan 4 09:55:05 2015 New Revision: 1649306 URL: http://svn.apache.org/r1649306 Log: BZ 44454: Improve busy counter by using atomics.
Atomics are used on Windows, when building with gcc and when APR is available. Not used e.g. for NSAPI on Solaris when building with Sun Studio compiler. Some problems still remain: theoretically the counter can get skewed when doing a web server restart (although some testing with Apache on Solaris didn't actually show this problem). Modified: tomcat/jk/trunk/native/common/jk_ajp_common.c tomcat/jk/trunk/native/common/jk_global.h tomcat/jk/trunk/native/common/jk_lb_worker.c tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Modified: tomcat/jk/trunk/native/common/jk_ajp_common.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_ajp_common.c?rev=1649306&r1=1649305&r2=1649306&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_ajp_common.c (original) +++ tomcat/jk/trunk/native/common/jk_ajp_common.c Sun Jan 4 09:55:05 2015 @@ -2397,8 +2397,7 @@ static void ajp_update_stats(jk_endpoint { aw->s->readed += e->rd; aw->s->transferred += e->wr; - if (aw->s->busy) - aw->s->busy--; + JK_ATOMIC_DECREMENT(&(aw->s->busy)); if (rc == JK_TRUE) { aw->s->state = JK_AJP_STATE_OK; } @@ -2464,6 +2463,7 @@ static int JK_METHOD ajp_service(jk_endp int rc = JK_UNSET; char *msg = ""; int retry_interval; + int busy; JK_TRACE_ENTER(l); @@ -2561,11 +2561,11 @@ static int JK_METHOD ajp_service(jk_endp jk_log(l, JK_LOG_DEBUG, "processing %s with %d retries", aw->name, aw->retries); } - aw->s->busy++; + busy = JK_ATOMIC_INCREMENT(&(aw->s->busy)); if (aw->s->state == JK_AJP_STATE_ERROR) aw->s->state = JK_AJP_STATE_PROBE; - if (aw->s->busy > aw->s->max_busy) - aw->s->max_busy = aw->s->busy; + if (busy > aw->s->max_busy) + aw->s->max_busy = busy; retry_interval = p->worker->retry_interval; for (i = 0; i < aw->retries; i++) { /* Reset reply message buffer for each retry Modified: tomcat/jk/trunk/native/common/jk_global.h URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_global.h?rev=1649306&r1=1649305&r2=1649306&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_global.h (original) +++ tomcat/jk/trunk/native/common/jk_global.h Sun Jan 4 09:55:05 2015 @@ -65,6 +65,7 @@ #ifdef HAVE_APR #include "apr_lib.h" #include "apr_strings.h" +#include "apr_atomic.h" #endif #include <stdio.h> @@ -413,6 +414,36 @@ typedef int jk_sock_t; #define strcasecmp(a,b) apr_strnatcasecmp(a,b) #endif +/* Atomics */ +#if defined(WIN32) +#define JK_ATOMIC_INCREMENT(x) InterlockedIncrement(x) +#define JK_ATOMIC_DECREMENT(x) \ + do {\ + if (InterlockedDecrement(x) < 0) InterlockedIncrement(x);\ + } while (0) +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +#define JK_ATOMIC_INCREMENT(x) __sync_add_and_fetch(x, 1) +#define JK_ATOMIC_DECREMENT(x) \ + do {\ + if (__sync_sub_and_fetch(x, 1) < 0) __sync_add_and_fetch(x, 1);\ + } while (0) +#elif defined(HAVE_APR) +#define JK_ATOMIC_INCREMENT(x) ((int)apr_atomic_inc32((volatile apr_uint32_t *)x) + 1) +#define JK_ATOMIC_DECREMENT(x) \ + do {\ + /* apr_atomic_add32 returns the *old* value */\ + apr_uint32_t y;\ + y = apr_atomic_add32((volatile apr_uint32_t *)x, -1);\ + if (y == 0 || y > INT_MAX) apr_atomic_inc32((volatile apr_uint32_t *)x);\ + } while (0) +#else +#define JK_ATOMIC_INCREMENT(x) (++(*x)) +#define JK_ATOMIC_DECREMENT(x) \ + do {\ + if (--(*x) < 0) (++(*x));\ + } while (0) +#endif + /* IPV6 support */ #if defined(HAVE_APR) #define JK_HAVE_IPV6 APR_HAVE_IPV6 Modified: tomcat/jk/trunk/native/common/jk_lb_worker.c URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/native/common/jk_lb_worker.c?rev=1649306&r1=1649305&r2=1649306&view=diff ============================================================================== --- tomcat/jk/trunk/native/common/jk_lb_worker.c (original) +++ tomcat/jk/trunk/native/common/jk_lb_worker.c Sun Jan 4 09:55:05 2015 @@ -1310,6 +1310,7 @@ static int JK_METHOD service(jk_endpoint int service_stat = JK_UNSET; jk_uint64_t rd = 0; jk_uint64_t wr = 0; + int busy; /* Reset endpoint read and write sizes for * this request. */ @@ -1319,10 +1320,10 @@ static int JK_METHOD service(jk_endpoint jk_shm_lock(); /* Increment the number of workers serving request */ - p->worker->s->busy++; - rec->s->busy++; - if (p->worker->s->busy > p->worker->s->max_busy) - p->worker->s->max_busy = p->worker->s->busy; + busy = JK_ATOMIC_INCREMENT(&(rec->s->busy)); + busy = JK_ATOMIC_INCREMENT(&(p->worker->s->busy)); + if (busy > p->worker->s->max_busy) + p->worker->s->max_busy = busy; if (p->worker->lbmethod == JK_LB_METHOD_REQUESTS || p->worker->lbmethod == JK_LB_METHOD_BUSYNESS || (!sessionid && @@ -1419,10 +1420,8 @@ static int JK_METHOD service(jk_endpoint * Check if the busy was reset to zero by graceful * restart of the server. */ - if (p->worker->s->busy) - p->worker->s->busy--; - if (rec->s->busy) - rec->s->busy--; + JK_ATOMIC_DECREMENT(&(p->worker->s->busy)); + JK_ATOMIC_DECREMENT(&(rec->s->busy)); if (service_stat == JK_TRUE) { /* * Successful request. Modified: tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml?rev=1649306&r1=1649305&r2=1649306&view=diff ============================================================================== --- tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml (original) +++ tomcat/jk/trunk/xdocs/miscellaneous/changelog.xml Sun Jan 4 09:55:05 2015 @@ -168,6 +168,9 @@ <bug>44454</bug>: LB: Add warning to docs about problems with "busyness" load balancing method. (rjung) </update> + <fix> + <bug>44454</bug>: Improve busy counter by using atomics. (rjung) + </fix> </changelog> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org